public string visitBinaryExpr(Expression.Binary expr)
    {
        var firstType  = expr.First.Accept(this);
        var secondType = expr.Second.Accept(this);

        if (firstType == null || secondType == null)
        {
            return(null);
        }

        if (firstType != secondType)
        {
            ErrorWriter.Write(expr.First, "Cannot operate with {0} and {1}", firstType, secondType);
            return(null);
        }

        // TODO use eval to get types?
        var type = expr.Operator.Type;

        if (
            (type == TokenType.EQUAL ||
             type == TokenType.AND ||
             type == TokenType.NOT))
        {
            return("bool");
        }

        return(expr.First.Accept(this));
    }
Exemple #2
0
 protected override object?Visit(Expression.Binary bin)
 {
     base.Visit(bin);
     if (bin.Operator == Expression.BinOp.Assign ||
         Expression.CompoundBinaryOperators.ContainsKey(bin.Operator))
     {
         // For assignment the sides must match
         var leftType  = System.TypeOf(bin.Left);
         var rightType = System.TypeOf(bin.Right);
         if (!leftType.Equals(rightType))
         {
             var leftIdent  = bin.Left as Expression.Identifier;
             var leftSymbol = leftIdent == null ? null : System.SymbolTable.ReferredSymbol(leftIdent);
             System.Report(new TypeMismatchError(leftType, rightType)
             {
                 Context = "assignment",
                 Defined = leftSymbol?.Definition?.ParseTreeNode,
                 Wrong   = bin.Right.ParseTreeNode,
             });
         }
     }
     else
     {
         // TODO
     }
     return(null);
 }
Exemple #3
0
 public object VisitBinaryExpr(Expression.Binary expr)
 {
     if (expr != null && expr.left != null && expr.right != null)
     {
         Resolve(expr.left);
         Resolve(expr.right);
     }
     return(new Expression.Binary());
 }
Exemple #4
0
        // Hack to test printer.
        static void Main(string[] args)
        {
            Expression expression = new Expression.Binary(
                new Expression.Unary(
                    new Token(TokenType.MINUS, "-", null, 1),
                    new Expression.Literal(123)),
                new Token(TokenType.STAR, "*", null, 1),
                new Expression.Grouping(new Expression.Literal(45.67))
                );

            Console.WriteLine(new AstPrinter().Print(expression));
        }
Exemple #5
0
        private Expression Equality()
        {
            Expression left = Comparison();

            while (Match(TokenType.BANG_EQUAL, TokenType.EQUAL_EQUAL))
            {
                Token      op    = Previous();
                Expression right = Comparison();
                left = new Expression.Binary(left, op, right);
            }

            return(left);
        }
Exemple #6
0
        public ByteCodeChunk VisitBinaryExpression(Expression.Binary expression)
        {
            var chunk = new ByteCodeChunk();

            chunk.AddRange(VisitExpression(expression.Right));
            chunk.AddRange(VisitExpression(expression.Left));
            switch (expression.Operator.Type)
            {
            case TokenType.Asterisk:
                chunk.AddInstruction(Instruction.MulI);
                break;

            case TokenType.Minus:
                chunk.AddInstruction(Instruction.SubI);
                break;

            case TokenType.Plus:
                chunk.AddInstruction(Instruction.AddI);
                break;

            case TokenType.Slash:
                chunk.AddInstruction(Instruction.DivI);
                break;

            case TokenType.Ampersand:
                chunk.AddInstruction(Instruction.And);
                break;

            case TokenType.Pipe:
                chunk.AddInstruction(Instruction.Or);
                break;

            case TokenType.Caret:
                chunk.AddInstruction(Instruction.Xor);
                break;

            case TokenType.Less:
                chunk.AddInstruction(Instruction.CmpLessI);
                break;

            case TokenType.Greater:
                chunk.AddInstruction(Instruction.CmpGreaterI);
                break;

            default:
                throw new ArgumentOutOfRangeException(
                          $"`{expression.Operator.Type.ToString()} is not a valid binary operator.'");
            }

            return(chunk);
        }
Exemple #7
0
        private Expression Factor()
        {
            Expression left = Unary();


            while (Match(TokenType.SLASH, TokenType.STAR))
            {
                Token      op    = Previous();
                Expression right = Unary();
                left = new Expression.Binary(left, op, right);
            }

            return(left);
        }
Exemple #8
0
        private Expression Term()
        {
            Expression left = Factor();


            while (Match(TokenType.MINUS, TokenType.PLUS))
            {
                Token      op    = Previous();
                Expression right = Factor();
                left = new Expression.Binary(left, op, right);
            }

            return(left);
        }
Exemple #9
0
        private Expression Comparison()
        {
            Expression left = Term();


            while (Match(TokenType.GREATER, TokenType.GREATER_EQUAL, TokenType.LESS, TokenType.LESS_EQUAL))
            {
                Token      op    = Previous();
                Expression right = Term();
                left = new Expression.Binary(left, op, right);
            }

            return(left);
        }
Exemple #10
0
        public object VisitBinaryExpr(Expression.Binary expr)
        {
            object left  = Evaluate(expr.left);
            object right = Evaluate(expr.right);

            var leftLiteralType  = left as Expression.LexemeTypeLiteral;
            var rightLiteralType = right as Expression.LexemeTypeLiteral;

            if (leftLiteralType == null || rightLiteralType == null)
            {
                throw new ArgumentNullException("unable to get literal");
            }

            long leftValueType  = leftLiteralType.lexemeType;
            long rightValueType = rightLiteralType.lexemeType;

            object leftValue  = leftLiteralType.Literal;
            object rightValue = rightLiteralType.Literal;

            switch (expr.op.ToString())
            {
            case "!=":
                return(!IsEqual(leftValue, rightValue));

            case "==":
                return(IsEqual(leftValue, rightValue));

            case ">":
                return(IsLessThan(leftValueType, rightValueType, leftValue, rightValue));

            case "/":
                return(DivideTypes(leftValueType, rightValueType, leftValue, rightValue));

            case "*":
                return(MultiplyTypes(leftValueType, rightValueType, leftValue, rightValue));

            case "-":
                return(SubtractTypes(leftValueType, rightValueType, leftValue, rightValue));

            case "+":
                return(AddTypes(leftValueType, rightValueType, leftValue, rightValue));
                //case "<":
                //case "<=":
                //case ">=":
            }

            return(new Expression.LexemeTypeLiteral());
        }
Exemple #11
0
        private Expression ParseBinaryExpression(ExprState state, int precedence = 0)
        {
            if (precedence >= PrecedenceTable.Length || state.HasFlag(ExprState.TypeOnly))
            {
                // Out of precedence table entries or we are parsing a type
                return(ParsePrefixExpression(state));
            }

            var desc   = PrecedenceTable[precedence];
            var result = ParseBinaryExpression(state, precedence + 1);

            if (desc.Associativity == Associativity.Left)
            {
                while (true)
                {
                    var op = Peek();
                    if (!desc.Operators.Contains(op.Type))
                    {
                        break;
                    }

                    op = Next();
                    var right = ParseBinaryExpression(state, precedence + 1);
                    result = new Expression.Binary(result, op, right);
                }
                return(result);
            }
            else
            {
                var op = Peek();
                if (!desc.Operators.Contains(op.Type))
                {
                    return(result);
                }

                op = Next();
                var right = ParseBinaryExpression(state, precedence);
                return(new Expression.Binary(result, op, right));
            }
        }
    public object visitBinaryExpr(Expression.Binary expr)
    {
        var second = expr.Second.Accept(this);

        var first = expr.First.Accept(this);

        // TODO Sematically check available operations (string - string impossible)
        // TODO abstract these operations (and maybe variable types)
        switch (expr.Operator.GetName())
        {
        case "PLUS":
            if (first is string)
            {
                return(first.ToString() + second.ToString());
            }
            return(((int)first) + ((int)second));

        case "MINUS":
            return(((int)first) - ((int)second));

        case "STAR":
            return(((int)first) * ((int)second));

        case "SLASH":
            return(((int)first) / ((int)second));

        case "AND":
            return(((bool)first) && ((bool)second));

        case "EQUAL":
            return(first.Equals(second));

        default:
            throw new System.NotImplementedException(string.Format("BINARY {0} NOT IMPLEMENTED", expr.Operator.GetName()));
        }
    }
Exemple #13
0
 public string VisitBinaryExpression(Expression.Binary expression)
 {
     return(Parenthesize(expression.op.lexeme, expression.left, expression.right));
 }
 public object VisitBinaryExpression(Expression.Binary expression)
 {
     Resolve(expression.left);
     Resolve(expression.right);
     return(null);
 }
        public object VisitBinaryExpression(Expression.Binary expression)
        {
            object left  = Evaluate(expression.left);
            object right = Evaluate(expression.right);

            switch (expression.op.type)
            {
            case TokenType.GREATER:
                CheckNumberOperands(expression.op, left, right);
                return((double)left > (double)right);

            case TokenType.GREATER_EQUAL:
                CheckNumberOperands(expression.op, left, right);
                return((double)left >= (double)right);

            case TokenType.LESS:
                CheckNumberOperands(expression.op, left, right);
                return((double)left < (double)right);

            case TokenType.LESS_EQUAL:
                CheckNumberOperands(expression.op, left, right);
                return((double)left <= (double)right);

            case TokenType.MINUS:
                CheckNumberOperands(expression.op, left, right);
                return((double)left - (double)right);

            case TokenType.SLASH:
                CheckNumberOperands(expression.op, left, right);

                // Handle a zero divisor operation.
                if ((double)right <= 0d)
                {
                    throw new RuntimeError(expression.op, "Unable to divide by zero.");
                }

                return((double)left / (double)right);

            case TokenType.STAR:
                CheckNumberOperands(expression.op, left, right);
                return((double)left * (double)right);

            case TokenType.PLUS:
                if (left.GetType() == typeof(double) &&
                    right.GetType() == typeof(double))
                {
                    return((double)left + (double)right);
                }

                if (left.GetType() == typeof(string) &&
                    right.GetType() == typeof(string))
                {
                    return((string)left + (string)right);
                }

                throw new RuntimeError(expression.op,
                                       "Operands must be two numbers or two strings.");

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

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

            // Unreachable.
            return(null);
        }