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)); }
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); }
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()); }
// 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)); }
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); }
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); }
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); }
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); }
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); }
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()); }
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())); } }
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); }