예제 #1
0
        private GExpr.Expr assignment()
        {
            GExpr.Expr expr = or();

            if (Match(tt.EQUAL))
            {
                Token      equals = previous();
                GExpr.Expr value  = assignment();

                if (expr is GExpr.Variable)
                {
                    Token name = ((GExpr.Variable)expr).name;
                    return(new GExpr.Assign(name, value));
                }
                else if (expr is GExpr.Get)
                {
                    GExpr.Get get = (GExpr.Get)expr;
                    return(new GExpr.Set(get.Object, get.name, value));
                }

                error(equals, "Invalid assignment target.");
            }

            return(expr);
        }
예제 #2
0
        private GStmt.Stmt whileStatement()
        {
            consume(tt.LEFT_PAREN, "Expect '(' after 'while'");
            GExpr.Expr condition = expression();
            consume(tt.RIGHT_PAREN, "Expect ')' after condition");
            GStmt.Stmt body = statement();

            return(new GStmt.While(condition, body));
        }
예제 #3
0
        private GStmt.Stmt forStatement()
        {
            consume(tt.LEFT_PAREN, "Expect '(' after 'for'.");

            GStmt.Stmt initializer;
            if (Match(tt.SEMICOLON))
            {
                initializer = null;
            }
            else if (Match(tt.VAR))
            {
                initializer = varDeclaration();
            }
            else
            {
                initializer = expressionStatement();
            }

            GExpr.Expr condition = null;
            if (!check(tt.SEMICOLON))
            {
                condition = expression();
            }
            consume(tt.SEMICOLON, "Expect ';' after loop condition.");

            GExpr.Expr increment = null;
            if (!check(tt.RIGHT_PAREN))
            {
                increment = expression();
            }
            consume(tt.RIGHT_PAREN, "Expect ')' after for clauses");
            GStmt.Stmt body = statement();
            if (increment != null)
            {
                body = new GStmt.Block(new List <GStmt.Stmt>()
                {
                    body, new GStmt.Expression(increment)
                });
            }
            if (condition == null)
            {
                condition = new GExpr.Literal(true);
            }
            body = new GStmt.While(condition, body);

            if (initializer != null)
            {
                body = new GStmt.Block(new List <GStmt.Stmt>()
                {
                    initializer, body
                });
            }


            return(body);
        }
예제 #4
0
 private GStmt.Stmt expressionStatement()
 {
     GExpr.Expr expr = expression();
     consume(tt.SEMICOLON, "Expect ';' after value.");
     if (isRepl)
     {
         return(new GStmt.Print(expr));
     }
     return(new GStmt.Expression(expr));
 }
예제 #5
0
 private void resolveLocal(GExpr.Expr expr, Token name)
 {
     for (int i = scopes.Count - 1; i >= 0; i--)
     {
         if (scopes.ElementAt(i).ContainsKey(name.lexeme))
         {
             interpreter.resolve(expr, i);
             return;
         }
     }
 }
예제 #6
0
        private GExpr.Expr unary()
        {
            if (Match(tt.BANG, tt.MINUS))
            {
                Token      Operator = previous();
                GExpr.Expr right    = unary();
                return(new GExpr.Unary(Operator, right));
            }

            return(call());
        }
예제 #7
0
        private GExpr.Expr equality()
        {
            GExpr.Expr expr = comparison();
            while (Match(tt.BANG_EQUAL, tt.EQUAL_EQUAL))
            {
                Token      Operator = previous();
                GExpr.Expr right    = comparison();
                expr = new GExpr.Binary(expr, Operator, right);
            }

            return(expr);
        }
예제 #8
0
        private GExpr.Expr and()
        {
            GExpr.Expr expr = equality();

            while (Match(tt.AND))
            {
                Token      op    = previous();
                GExpr.Expr right = equality();
                expr = new GExpr.Logical(expr, op, right);
            }

            return(expr);
        }
예제 #9
0
        private GExpr.Expr or()
        {
            GExpr.Expr expr = and();

            while (Match(tt.OR))
            {
                Token      op    = previous();
                GExpr.Expr right = and();
                expr = new GExpr.Logical(expr, op, right);
            }

            return(expr);
        }
예제 #10
0
        private Object lookUpVariable(Token name, GExpr.Expr expression)
        {
            int distance = locals.ContainsKey(expression) ? locals[expression] : -1;

            if (distance >= 0)
            {
                return(environment.getAt(distance, name.lexeme));
            }
            else
            {
                return(globals.get(name));
            }
        }
예제 #11
0
        private GExpr.Expr addition()
        {
            GExpr.Expr expr = multiplication();

            while (Match(tt.MINUS, tt.PLUS))
            {
                Token      Operator = previous();
                GExpr.Expr right    = multiplication();
                expr = new GExpr.Binary(expr, Operator, right);
            }

            return(expr);
        }
예제 #12
0
        private GStmt.Stmt varDeclaration()
        {
            Token name = consume(tt.IDENTIFIER, "Expect variable name");

            GExpr.Expr initializer = null;
            if (Match(tt.EQUAL))
            {
                initializer = expression();
            }

            consume(tt.SEMICOLON, "Expect ';' after variable declaration");
            return(new GStmt.Var(name, initializer));
        }
예제 #13
0
        private GExpr.Expr multiplication()
        {
            GExpr.Expr expr = unary();

            while (Match(tt.SLASH, tt.STAR))
            {
                Token      Operator = previous();
                GExpr.Expr right    = unary();
                expr = new GExpr.Binary(expr, Operator, right);
            }

            return(expr);
        }
예제 #14
0
        private GExpr.Expr comparison()
        {
            GExpr.Expr expr = addition();

            while (Match(tt.GREATER, tt.GREATER_EQUAL, tt.LESS, tt.LESS_EQUAL))
            {
                Token      Operator = previous();
                GExpr.Expr right    = addition();
                expr = new GExpr.Binary(expr, Operator, right);
            }

            return(expr);
        }
예제 #15
0
        private GStmt.Stmt returnStatement()
        {
            Token keyword = previous();

            GExpr.Expr value = null;

            if (!check(tt.SEMICOLON))
            {
                value = expression();
            }

            consume(tt.SEMICOLON, "Expect ';' after return value");
            return(new GStmt.Return(keyword, value));
        }
예제 #16
0
        private GStmt.Stmt ifStatement()
        {
            consume(tt.LEFT_PAREN, "Expect ( after 'if'");
            GExpr.Expr condition = expression();
            consume(tt.RIGHT_PAREN, "Expect ) after if condition.");

            GStmt.Stmt thenBranch = statement();
            GStmt.Stmt elseBranch = null;
            if (Match(tt.ELSE))
            {
                elseBranch = statement();
            }

            return(new GStmt.If(condition, thenBranch, elseBranch));
        }
예제 #17
0
        private GExpr.Expr primary()
        {
            if (Match(tt.FALSE))
            {
                return(new GExpr.Literal(false));
            }

            if (Match(tt.TRUE))
            {
                return(new GExpr.Literal(true));
            }

            if (Match(tt.NIL))
            {
                return(new GExpr.Literal(null));
            }

            if (Match(tt.SUPER))
            {
                Token keyword = previous();
                consume(tt.DOT, "Expect '.' after 'super'");
                Token method = consume(tt.IDENTIFIER, "Expect superclass method name");
                return(new GExpr.Super(keyword, method));
            }

            if (Match(tt.NUMBER, tt.STRING))
            {
                return(new GExpr.Literal(previous().literal));
            }

            if (Match(tt.LEFT_PAREN))
            {
                GExpr.Expr expr = expression();
                consume(tt.RIGHT_PAREN, "Expect ')' after expression.");
                return(new GExpr.Grouping(expr));
            }

            if (Match(tt.THIS))
            {
                return(new GExpr.This(previous()));
            }
            if (Match(tt.IDENTIFIER))
            {
                return(new GExpr.Variable(previous()));
            }

            throw error(peek(), "unexpected token");
        }
예제 #18
0
        private GExpr.Expr finishCall(GExpr.Expr callee)
        {
            List <GExpr.Expr> arguments = new List <GExpr.Expr>();

            if (!check(tt.RIGHT_PAREN))
            {
                do
                {
                    if (arguments.Count >= 8)
                    {
                        error(peek(), "Cannot have more than 8 arguments");
                    }
                    arguments.Add(expression());
                } while (Match(tt.COMMA));
            }

            Token paren = consume(tt.RIGHT_PAREN, "Expect ')' after arguments");

            return(new GExpr.Call(callee, paren, arguments));
        }
예제 #19
0
        private GExpr.Expr call()
        {
            GExpr.Expr expr = primary();

            while (true)
            {
                if (Match(tt.LEFT_PAREN))
                {
                    expr = finishCall(expr);
                }
                else if (Match(tt.DOT))
                {
                    Token name = consume(tt.IDENTIFIER, "Expect property name after '.'.");
                    expr = new GExpr.Get(expr, name);
                }
                else
                {
                    break;
                }
            }

            return(expr);
        }
예제 #20
0
 private Object evaluate(GExpr.Expr Expression)
 {
     return(Expression.Accept(this));
 }
예제 #21
0
 public void resolve(GExpr.Expr expr, int depth)
 {
     locals.Add(expr, depth);
 }
예제 #22
0
 private void resolve(GExpr.Expr expr)
 {
     expr.Accept(this);
 }
예제 #23
0
 private GStmt.Stmt printStatement()
 {
     GExpr.Expr value = expression();
     consume(tt.SEMICOLON, "Expect ';' after value.");
     return(new GStmt.Print(value));
 }