Example #1
0
        private Expression parseExpression(Precedence precedence)
        {
            ParserTracing.Trace($"expression({precedence})");
            if (!_prefixParseFunctions.TryGetValue(_currentToken.Type, out var prefix))
            {
                noPrefixParseFnError(_currentToken.Type);
                return(null);
            }

            var leftExp = prefix();

            while (!peekTokenIs(TokenType.SEMICOLON) && precedence < peekPrecedence())
            {
                if (!_infixParseFunctions.TryGetValue(_peekToken.Type, out var infix))
                {
                    return(null);
                }

                nextToken();
                leftExp = infix(leftExp);
            }

            ParserTracing.Untrace($"expression({precedence})");
            return(leftExp);
        }
Example #2
0
        private LetStatement parseLetStatement()
        {
            ParserTracing.Trace("let statement");
            var token = _currentToken;

            if (!expectPeek(TokenType.IDENT))
            {
                return(null);
            }

            var name = new Identifier {
                Token = _currentToken, Value = _currentToken.Literal
            };

            if (!expectPeek(TokenType.EQUALS))
            {
                return(null);
            }

            nextToken();
            var value = parseExpression(Precedence.LOWEST);

            if (!expectPeek(TokenType.SEMICOLON))
            {
                return(null);
            }

            ParserTracing.Untrace("let statement");
            return(new LetStatement {
                Token = token, Name = name, Value = value
            });
        }
Example #3
0
        private void peekError(TokenType type)
        {
            var msg = $"expected next token to be {type}, got {_peekToken.Type} instead";

            ParserTracing.Error(msg);
            _errors.Add(msg);
        }
Example #4
0
        private void noPrefixParseFnError(TokenType type)
        {
            var msg = $"no prefix parse function for {type} found";

            ParserTracing.Error(msg);
            _errors.Add(msg);
        }
Example #5
0
 private Expression parseIdentifier()
 {
     ParserTracing.Trace("identifier");
     ParserTracing.Untrace("identifier");
     return(new Identifier {
         Token = _currentToken, Value = _currentToken.Literal
     });
 }
Example #6
0
 private Expression parseBoolean()
 {
     ParserTracing.Trace("boolean");
     ParserTracing.Untrace("boolean");
     return(new BooleanExpression {
         Token = _currentToken, Value = curTokenIs(TokenType.TRUE)
     });
 }
Example #7
0
 private void nextToken()
 {
     _currentToken = _peekToken;
     _peekToken    = _lexer.NextToken();
     ParserTracing.Token(
         $"current token is now {_currentToken?.Type ?? TokenType.ILLEGAL} ({_currentToken?.Literal ?? ""})");
     ParserTracing.Token(
         $"peek token is now {_peekToken?.Type ?? TokenType.ILLEGAL} ({_peekToken?.Literal ?? ""})");
 }
Example #8
0
        private Expression parseCallExpression(Expression function)
        {
            ParserTracing.Trace("call expression");
            var token     = _currentToken;
            var arguments = parseExpressionList(TokenType.RPAREN);

            ParserTracing.Untrace("call expression");
            return(new CallExpression {
                Token = token, Function = function, Arguments = arguments
            });
        }
Example #9
0
        private Expression parseGroupedExpression()
        {
            ParserTracing.Trace("grouped expression");
            nextToken();

            var exp = parseExpression(Precedence.LOWEST);

            if (!expectPeek(TokenType.RPAREN))
            {
                return(null);
            }

            ParserTracing.Untrace("grouped expression");
            return(exp);
        }
Example #10
0
        private Expression parsePrefixExpression()
        {
            ParserTracing.Trace("prefix expression");
            var token = _currentToken;
            var op    = _currentToken.Literal;

            nextToken();

            var right = parseExpression(Precedence.PREFIX);

            ParserTracing.Untrace("prefix expression");
            return(new PrefixExpression {
                Token = token, Op = op, Right = right
            });
        }
Example #11
0
        private Expression parseInfixExpression(Expression left)
        {
            ParserTracing.Trace("infix expression");
            var token = _currentToken;
            var op    = _currentToken.Literal;

            var precedence = curPrecedence();

            nextToken();
            var right = parseExpression(precedence);

            ParserTracing.Untrace("infix expression");
            return(new InfixExpression {
                Token = token, Left = left, Op = op, Right = right
            });
        }
Example #12
0
        private ExpressionStatement parseExpressionStatement()
        {
            ParserTracing.Trace("expression statement");
            var token = _currentToken;

            var expression = parseExpression(Precedence.LOWEST);

            if (peekTokenIs(TokenType.SEMICOLON))
            {
                nextToken();
            }

            ParserTracing.Untrace("expression statement");
            return(new ExpressionStatement {
                Token = token, Expression = expression
            });
        }
Example #13
0
        private ReturnStatement parseReturnStatement()
        {
            ParserTracing.Trace("return statement");
            var token = _currentToken;

            nextToken();
            var returnValue = parseExpression(Precedence.LOWEST);

            if (!expectPeek(TokenType.SEMICOLON))
            {
                return(null);
            }

            ParserTracing.Untrace("return statement");
            return(new ReturnStatement {
                Token = token, ReturnValue = returnValue
            });
        }
Example #14
0
        private Expression parseIntegerLiteral()
        {
            ParserTracing.Trace("integer literal");
            var token = _currentToken;

            if (!Int64.TryParse(_currentToken.Literal, System.Globalization.NumberStyles.None, null, out var value))
            {
                var msg = $"could not parse \"{_currentToken.Literal}\" as integer";
                ParserTracing.Error(msg);
                _errors.Add(msg);
                return(null);
            }

            ParserTracing.Untrace("integer literal");
            return(new IntegerLiteral {
                Token = token, Value = value
            });
        }
Example #15
0
        private Expression parseIfExpression()
        {
            ParserTracing.Trace("if expression");
            var token = _currentToken;

            if (!expectPeek(TokenType.LPAREN))
            {
                return(null);
            }

            nextToken();
            var condition = parseExpression(Precedence.LOWEST);

            if (!expectPeek(TokenType.RPAREN))
            {
                return(null);
            }

            if (!expectPeek(TokenType.LBRACE))
            {
                return(null);
            }

            var            consequence = parseBlockStatement();
            BlockStatement alternative = null;

            if (peekTokenIs(TokenType.ELSE))
            {
                nextToken();
                if (!expectPeek(TokenType.LBRACE))
                {
                    return(null);
                }

                alternative = parseBlockStatement();
            }

            ParserTracing.Untrace("if expression");
            return(new IfExpression
            {
                Token = token, Condition = condition, Consequence = consequence, Alternative = alternative
            });
        }
Example #16
0
        public Program ParseProgram()
        {
            var program = new Program();

            ParserTracing.Trace("program");
            while (_currentToken.Type != TokenType.EOF)
            {
                var stmt = parseStatement();
                if (stmt != null)
                {
                    program.Statements.Add(stmt);
                }

                nextToken();
            }

            ParserTracing.Untrace("program");

            return(program);
        }
Example #17
0
        private ImmutableList <Identifier> parseFunctionParameters()
        {
            ParserTracing.Trace("function parameters");
            var identifiers = new List <Identifier>();

            if (peekTokenIs(TokenType.RPAREN))
            {
                nextToken();
                return(identifiers.ToImmutableList());
            }

            nextToken();

            var ident = new Identifier {
                Token = _currentToken, Value = _currentToken.Literal
            };

            identifiers.Add(ident);

            while (peekTokenIs(TokenType.COMMA))
            {
                nextToken();
                nextToken();

                var suffixIdent = new Identifier {
                    Token = _currentToken, Value = _currentToken.Literal
                };
                identifiers.Add(suffixIdent);
            }

            if (!expectPeek(TokenType.RPAREN))
            {
                return(null);
            }

            ParserTracing.Untrace("function parameters");
            return(identifiers.ToImmutableList());
        }
Example #18
0
        private Statement parseStatement()
        {
            ParserTracing.Trace("statement");
            Statement s;

            switch (_currentToken.Type)
            {
            case TokenType.LET:
                s = parseLetStatement();
                break;

            case TokenType.RETURN:
                s = parseReturnStatement();
                break;

            default:
                s = parseExpressionStatement();
                break;
            }

            ParserTracing.Untrace("statement");
            return(s);
        }
Example #19
0
        private BlockStatement parseBlockStatement()
        {
            ParserTracing.Trace("block statement");
            var token      = _currentToken;
            var statements = new List <Statement>();

            nextToken();

            while (!curTokenIs(TokenType.RBRACE) && !curTokenIs(TokenType.EOF))
            {
                var stmt = parseStatement();
                if (stmt != null)
                {
                    statements.Add(stmt);
                }

                nextToken();
            }

            ParserTracing.Untrace("block statement");
            return(new BlockStatement {
                Token = token, Statements = statements.ToImmutableArray()
            });
        }
Example #20
0
        private Expression parseFunctionLiteral()
        {
            ParserTracing.Trace("function");
            var token = _currentToken;

            if (!expectPeek(TokenType.LPAREN))
            {
                return(null);
            }

            var parameters = parseFunctionParameters();

            if (!expectPeek(TokenType.LBRACE))
            {
                return(null);
            }

            var body = parseBlockStatement();

            ParserTracing.Untrace("function");
            return(new FunctionLiteral {
                Token = token, Parameters = parameters, Body = body
            });
        }