示例#1
0
        // generates an expr for multiplication
        private Expr Multiplication()
        {
            Expr expr = Unary();

            while (Match(Token.TokenType.Slash, Token.TokenType.Star, Token.TokenType.Percent))
            {
                Token op    = Previous();
                Expr  right = Unary();
                expr = new Expr.Binary(expr, op, right);
            }

            return(expr);
        }
示例#2
0
        // generates an expr for addition
        private Expr Addition()
        {
            Expr expr = Multiplication();

            while (Match(Token.TokenType.Minus, Token.TokenType.Plus))
            {
                Token op    = Previous();
                Expr  right = Multiplication();
                expr = new Expr.Binary(expr, op, right);
            }

            return(expr);
        }
示例#3
0
        // generates an expr for comparison
        private Expr Comparison()
        {
            Expr expr = Addition();

            while (Match(Token.TokenType.Greater, Token.TokenType.GreaterEqual, Token.TokenType.Less, Token.TokenType.LessEqual))
            {
                Token op    = Previous();
                Expr  right = Addition();
                expr = new Expr.Binary(expr, op, right);
            }

            return(expr);
        }
示例#4
0
        // generates an expr for equality check
        private Expr Equality()
        {
            Expr expr = Comparison();

            // exit when we find an equality operator
            while (Match(Token.TokenType.BangEqual, Token.TokenType.EqualEqual))
            {
                Token op    = Previous();
                Expr  right = Comparison();
                expr = new Expr.Binary(expr, op, right);
            }

            return(expr);
        }
示例#5
0
        // evaluates a number of binary expressions
        public object VisitBinaryExpr(Expr.Binary expr)
        {
            object left  = Evaluate(expr.left);
            object right = Evaluate(expr.right);

            switch (expr.op.type)
            {
            case Token.TokenType.Greater:
                CheckNumberOperands(expr.op, left, right);
                return((double)left > (double)right);

            case Token.TokenType.GreaterEqual:
                CheckNumberOperands(expr.op, left, right);
                return((double)left >= (double)right);

            case Token.TokenType.Less:
                CheckNumberOperands(expr.op, left, right);
                return((double)left < (double)right);

            case Token.TokenType.LessEqual:
                CheckNumberOperands(expr.op, left, right);
                return((double)left <= (double)right);

            // arithmetic operators
            case Token.TokenType.Minus:
                CheckNumberOperands(expr.op, left, right);
                return((double)left - (double)right);

            case Token.TokenType.Plus:
                if (left is double && right is double)
                {
                    return((double)left + (double)right);
                }

                if (left is string && right is string)
                {
                    return((string)left + (string)right);
                }

                // try to ToString whatever the value is
                if (left is string && !(right is string) && right != null)
                {
                    return((string)left + right.ToString());
                }
                else if (!(left is string) && left != null && right is string)
                {
                    return(left.ToString() + (string)right);
                }

                if (left is double && right is double)
                {
                }
                else
                {
                    Console.WriteLine("Not Double");
                }

                if (left is string && right is string)
                {
                }
                else
                {
                    Console.WriteLine("Not String");
                }

                Console.WriteLine(left.GetType());

                // THIS IS THROWING ERROR
                Console.WriteLine($"{expr.op}, left:{left}, right:{right}");
                throw new RuntimeError(expr.op,
                                       "Operands must be two numbers or two strings.");

            case Token.TokenType.Slash:
                CheckNumberOperands(expr.op, left, right);
                return((double)left / (double)right);

            case Token.TokenType.Star:
                CheckNumberOperands(expr.op, left, right);
                return((double)left * (double)right);

            case Token.TokenType.Percent:
                CheckNumberOperands(expr.op, left, right);
                return((double)left % (double)right);

            case Token.TokenType.BangEqual: return(!IsEqual(left, right));

            case Token.TokenType.EqualEqual: return(IsEqual(left, right));
            }

            // Unreachable.
            return(null);
        }
示例#6
0
 public string VisitBinaryExpr(Expr.Binary expr)
 {
     return(Parenthesize(expr.op.lexeme, expr.left, expr.right));
 }
示例#7
0
 public object VisitBinaryExpr(Expr.Binary expr)
 {
     Resolve(expr.left);
     Resolve(expr.right);
     return(null);
 }
示例#8
0
        private Expr Assignment()
        {
            Expr expr = Or();

            if (Match(Token.TokenType.PlusPlus))
            {
                Token variable = Previous();

                if (expr is Expr.Variable v)
                {
                    Token name = v.name;
                    return(new Expr.Assign(name,
                                           new Expr.Binary(expr, new Token(Token.TokenType.Plus, "+", null, variable.line), new Expr.Literal(1.0))));
                }
                else if (expr is Expr.Get)
                {
                    Expr.Get get = (Expr.Get)expr;
                    return(new Expr.Set(get.Objekt, get.Name, new Expr.Binary(expr, new Token(Token.TokenType.Plus, "+", null, variable.line), new Expr.Literal(1.0))));
                }
                Error(variable, "Invalid assignment target.");
            }

            if (Match(Token.TokenType.MinusMinus))
            {
                Token variable = Previous();

                if (expr is Expr.Variable v)
                {
                    Token name = v.name;
                    return(new Expr.Assign(name,
                                           new Expr.Binary(expr, new Token(Token.TokenType.Plus, "+", null, variable.line), new Expr.Literal(-1.0))));
                }
                else if (expr is Expr.Get)
                {
                    Expr.Get get = (Expr.Get)expr;
                    return(new Expr.Set(get.Objekt, get.Name, new Expr.Binary(expr, new Token(Token.TokenType.Plus, "+", null, variable.line), new Expr.Literal(-1.0))));
                }
                Error(variable, "Invalid assignment target.");
            }

            if (Match(Token.TokenType.Equal, Token.TokenType.MinusEqual, Token.TokenType.PlusEqual,
                      Token.TokenType.StarEqual, Token.TokenType.SlashEqual, Token.TokenType.PercentEqual,
                      Token.TokenType.PlusPlus))
            {
                Token equals        = Previous();
                Expr  tempValue     = Assignment();
                Expr  assignedValue = tempValue;

                switch (equals.type)
                {
                case Token.TokenType.Equal: break;

                case Token.TokenType.MinusEqual:
                    assignedValue = new Expr.Binary(expr, new Token(Token.TokenType.Minus, "-", null, equals.line), tempValue);
                    break;

                case Token.TokenType.PlusEqual:
                    assignedValue = new Expr.Binary(expr, new Token(Token.TokenType.Plus, "+", null, equals.line), tempValue);
                    break;

                case Token.TokenType.StarEqual:
                    assignedValue = new Expr.Binary(expr, new Token(Token.TokenType.Star, "*", null, equals.line), tempValue);
                    break;

                case Token.TokenType.SlashEqual:
                    assignedValue = new Expr.Binary(expr, new Token(Token.TokenType.Slash, "/", null, equals.line), tempValue);
                    break;

                case Token.TokenType.PercentEqual:
                    assignedValue = new Expr.Binary(expr, new Token(Token.TokenType.Percent, "%", null, equals.line), tempValue);
                    break;

                default: Basil.Error(Previous().line, "Tried to create assignment statement but tokens were invalid.");
                    break;
                }

                if (expr is Expr.Variable v)
                {
                    Token name = v.name;
                    return(new Expr.Assign(name, assignedValue));
                }
                else if (expr is Expr.Get)
                {
                    Expr.Get get = (Expr.Get)expr;
                    return(new Expr.Set(get.Objekt, get.Name, assignedValue));
                }
                Error(equals, "Invalid assignment target.");
            }
            //else if (Match(Token.TokenType.MinusEqual))
            //{
            //    Token equals = Previous();
            //    Expr value = Assignment();
            //    // replace assignment expression with (expr - value)
            //    Expr minusEquals = new Expr.Binary(expr, new Token(Token.TokenType.Minus, "-", null, equals.line), value);
            //    if (expr is Expr.Variable v)
            //    {
            //        Token name = v.name;

            //        return new Expr.Assign(name, minusEquals);
            //    }
            //    else if (expr is Expr.Get)
            //    {
            //        Expr.Get get = (Expr.Get)expr;
            //        return new Expr.Set(get.Objekt, get.Name, minusEquals);
            //    }
            //    Error(equals, "Invalid assignment target.");
            //}
            return(expr);
        }