Example #1
0
func parseFunctionDeclarationArguments(tokens []*lexer.Token) ([]string, int, error) {
	var args []string

	if len(tokens) == 0 || !tokens[0].IsTypeAndData(lexer.TOKEN_SEPARATOR, "(") {
		return args, 0, nil
	}

	var i int

	for i = 1; i < len(tokens)-1; i++ {
		if tokens[i].IsTypeAndData(lexer.TOKEN_SEPARATOR, ")") {
			break
		}

		args = append(args, tokens[i].Data)
	}

	if !tokens[i].IsTypeAndData(lexer.TOKEN_SEPARATOR, ")") {
		return nil, 0, util.NewSyntaxError("expected an )", tokens[i].Line, tokens[i].Column, tokens[i].File)
	}

	i++

	return args, i, nil
}
Example #2
0
func parseBlock(tokens []*lexer.Token) ([]*lexer.Token, int, error) {
	var block []*lexer.Token
	var i int

	depth := 0

	for i = 0; i < len(tokens); i++ {
		if tokens[i].IsOpening() {
			depth++
		} else if tokens[i].IsClosing() {
			depth--

			if depth == 0 {
				break
			}
		}

		if i > 0 {
			block = append(block, tokens[i])
		}
	}

	if depth != 0 {
		return nil, 0, util.NewSyntaxError("unclosed block", tokens[i-1].Line, tokens[i-1].Column, tokens[i-1].File)
	}

	return block, i, nil
}
Example #3
0
func (n *PushNode) Eval(block *Block) (*Value, error) {
	switch n.Token.Type {
	case lexer.TOKEN_NUMBER:
		num := big.NewRat(0, 1)
		_, ok := num.SetString(n.Token.Data)

		if !ok {
			return nil, util.NewSyntaxError("malformed number", n.Token.Line, n.Token.Column, n.Token.File)
		}

		return NewValueFromRat(num), nil
	case lexer.TOKEN_STRING_SINGLE:
		return NewValueFromString(n.Token.Data), nil
	case lexer.TOKEN_STRING_DOUBLE:
		var newString string

		parts := strings.Split(n.Token.Data, " ")

		for i, part := range parts {
			if len(part) > 0 && part[0] == '$' {
				name := part[1:]

				if block.Scope.GetSymbol(name) == nil {
					return nil, util.NewSyntaxError("symbol "+name+" doesn't exist in scope", n.Token.Line, n.Token.Column, n.Token.File)
				} else {
					newString += block.Scope.GetSymbol(name).Value.String()
				}
			} else {
				newString += part
			}

			if i != len(parts)-1 {
				newString += " "
			}
		}

		return NewValueFromString(newString), nil
	case lexer.TOKEN_IDENTIFIER:
		name := n.Token.Data
		escaped := false

		if name[0] == '\\' {
			name = name[1:]

			escaped = true
		}

		symbol := block.Scope.GetSymbol(name)

		if symbol == nil {
			return nil, util.NewSyntaxError("symbol "+name+" doesn't exist in scope", n.Token.Line, n.Token.Column, n.Token.File)
		}

		value := symbol.Value

		if escaped {
			if value.Type != VALUE_FUNCTION {
				return nil, util.NewSyntaxError("expected a function", n.Token.Line, n.Token.Column, n.Token.File)
			}
		} else if value.Type == VALUE_FUNCTION && value.F.Type != FUNCTION_LAMBDA {
			return nil, value.F.Exec(block, n.Token)
		}

		return value, nil
	}
	return nil, nil
}
Example #4
0
func Nodes(tokens []*lexer.Token) ([]Node, error) {
	var nodes []Node

	for i := 0; i < len(tokens); i++ {
		token := tokens[i]

		switch token.Type {
		case lexer.TOKEN_IDENTIFIER:
			if token.IsDirective() {
				block, increase, err := parseBlock(tokens[i:])

				if err != nil {
					return nil, err
				}

				i += increase

				nodes = append(nodes, &DirectiveNode{NameToken: token, Tokens: block})
			} else {
				nodes = append(nodes, &PushNode{Token: token})
			}
		case lexer.TOKEN_STRING_SINGLE, lexer.TOKEN_STRING_DOUBLE, lexer.TOKEN_NUMBER:
			nodes = append(nodes, &PushNode{Token: token})
		case lexer.TOKEN_SEPARATOR:
			switch token.Data {
			case "[":
				block, increase, err := parseBlock(tokens[i:])

				if err != nil {
					return nil, err
				}

				i += increase

				blockNodes, err := Nodes(block)
				if err != nil {
					return nil, err
				}

				nodes = append(nodes, &BlockNode{Nodes: blockNodes})
			case "{":
				list, increase, err := parseBlock(tokens[i:])

				if err != nil {
					return nil, err
				}

				i += increase

				listNodes, err := Nodes(list)
				if err != nil {
					return nil, err
				}

				nodes = append(nodes, &ListNode{Nodes: listNodes})
			default:
				return nil, util.NewSyntaxError("unexpected "+token.Data, token.Line, token.Column, token.File)
			}
		default:
			return nil, util.NewSyntaxError("unexpected "+token.Data, token.Line, token.Column, token.File)
		}
	}

	return nodes, nil
}
Example #5
0
func (n *DirectiveNode) Eval(block *Block) (*Value, error) {
	name := n.NameToken.Data[:len(n.NameToken.Data)-1]

	switch name {
	case KEYWORD_USING:
		for _, token := range n.Tokens {
			if token.Type != lexer.TOKEN_IDENTIFIER {
				return nil, util.NewSyntaxError("expected an identifier", token.Line, token.Column, token.File)
			}

			module := block.Scope.GetModule(token.Data)
			if module == nil {
				return nil, util.NewSyntaxError("module "+token.Data+" doesn't exist in scope", token.Line, token.Column, token.File)
			}
			for key, value := range module.Data {
				block.Scope.SetSymbolLocally(key, NewSymbol(value, true, false))
			}
		}
	case KEYWORD_OUT:
		for _, token := range n.Tokens {
			if token.Type != lexer.TOKEN_IDENTIFIER {
				return nil, util.NewSyntaxError("expected an identifier", token.Line, token.Column, token.File)
			}
			name := token.Data
			if block.Scope.GetSymbol(name) == nil {
				return nil, util.NewSyntaxError("symbol "+name+" not found in scope", token.Line, token.Column, token.File)
			}
			block.Scope.GetSymbol(name).Exported = true
		}
	case KEYWORD_CONSTANT, KEYWORD_SYMBOL:
		if len(n.Tokens) == 0 {
			return nil, util.NewSyntaxError("missing symbol name", n.NameToken.Line, n.NameToken.Column, n.NameToken.File)
		}

		if n.Tokens[0].Type != lexer.TOKEN_IDENTIFIER {
			return nil, util.NewSyntaxError("expected an identifier", n.Tokens[0].Line, n.Tokens[0].Column, n.Tokens[0].File)
		}

		name := n.Tokens[0].Data

		if block.Scope.GetSymbol(name) != nil && block.Scope.GetSymbol(name).Const == true {
			return nil, util.NewSyntaxError("cannot modify constant "+name, n.Tokens[0].Line, n.Tokens[0].Column, n.Tokens[0].File)
		}

		nodes, err := Nodes(n.Tokens[1:])
		if err != nil {
			return nil, err
		}

		valueBlock := NewBlock(nodes, block, block.File)
		err = valueBlock.Exec()

		if err != nil {
			return nil, err
		}

		if valueBlock.Stack.Len() != 1 {
			return nil, util.NewSyntaxError(fmt.Sprintf("exact 1 value on the stack expected, tried to declare %d value(s)", valueBlock.Stack.Len()), n.NameToken.Line, n.NameToken.Column, n.NameToken.File)
		}

		block.Scope.SetSymbolLocally(name, NewSymbol(valueBlock.Stack.Pop().(*Value), n.NameToken.Data == KEYWORD_CONSTANT, false))
	case "":
		if len(n.Tokens) == 0 {
			return nil, util.NewSyntaxError("missing function name", n.NameToken.Line, n.NameToken.Column, n.NameToken.File)
		}

		if n.Tokens[0].Type != lexer.TOKEN_IDENTIFIER {
			return nil, util.NewSyntaxError("expected an identifier for the function name", n.Tokens[0].Line, n.Tokens[0].Column, n.Tokens[0].File)
		}

		name := n.Tokens[0].Data

		if block.Scope.GetSymbol(name) != nil && block.Scope.GetSymbol(name).Const == true {
			return nil, util.NewSyntaxError("cannot modify constant "+name, n.Tokens[0].Line, n.Tokens[0].Column, n.Tokens[0].File)
		}

		args, increase, err := parseFunctionDeclarationArguments(n.Tokens[1:])

		if err != nil {
			return nil, err
		}

		nodes, err := Nodes(n.Tokens[1+increase : len(n.Tokens)])

		if err != nil {
			return nil, err
		}

		block.Scope.SetSymbolLocally(name, NewSymbol(NewValueFromFunction(&Function{
			Type: FUNCTION_DECLARED,
			Name: name,
			Args: args,
			D:    NewBlock(nodes, block, block.File),
		}), false, false))
	default:
		return nil, util.NewSyntaxError("unknown directive "+n.NameToken.Data, n.NameToken.Line, n.NameToken.Column, n.NameToken.File)
	}
	return nil, nil
}