/** * Function VisitBinaryExpr : it checks : * Right and left operands are the same type * For '+' only INT and STRING are allowed * For '-', '*', '/' only INT are allowed * Param : binary expression to check * Return : type of the right and left operands or error */ public VALTYPE VisitBinaryExpr(Expr.Binary expr) { VALTYPE left = GetType(expr.Left); VALTYPE right = GetType(expr.Right); /* Case the binary operator is '=' or '<' */ if (matching.Contains(expr.OperatorToken.Kind)) { /* If left and right are the same type return BOOL */ if (left.Equals(right)) { return(VALTYPE.BOOL); } /* Error not same type */ else { throw new TypeError(expr.OperatorToken, "'" + expr.OperatorToken.Text + "' arguments should have the same type."); } } /* Case the binary operator is '-', '*' or '/' */ else if (numbers.Contains(expr.OperatorToken.Kind)) { /* Case left and right are both INT */ if (left.Equals(right) && left.Equals(VALTYPE.INT)) { return(VALTYPE.INT); } /* Error not same type*/ else { throw new TypeError(expr.OperatorToken, "'" + expr.OperatorToken.Text + "' arguments should both be " + VALTYPE.INT.ToString() + ", got " + left.ToString() + " and " + right.ToString() + " instead."); } } /* Case the binary operator is '+' */ else if (expr.OperatorToken.Kind.Equals(TokenKind.Sum)) { /* If left and right are the same type */ if (left.Equals(right)) { /* If the type is not bool we return the type they are */ if (!left.Equals(VALTYPE.BOOL)) { return(left); } /* Error it cannot happen BOOL + BOOL */ else { throw new TypeError(expr.OperatorToken, "'" + expr.OperatorToken.Text + "' arguments should both be " + VALTYPE.INT.ToString() + ", got twice " + left.ToString() + " instead."); } } /* Error not same type */ else { throw new TypeError(expr.OperatorToken, "'" + expr.OperatorToken.Text + "' arguments should both be either " + VALTYPE.INT.ToString() + " or " + VALTYPE.STRING.ToString() + ", got " + left.ToString() + " and " + right.ToString() + " instead."); } } throw new TypeError(expr.OperatorToken, "Didn't get the right types."); /* Unreachable */ }
/***************************************************************** * FUNCTIONS FOR EXPRESSIONS * *****************************************************************/ /** * Function VisitBinaryExpr : it evaluates both right and left expressions * of the binary expression, checking that both operands are the same type * and returns the value of them depending on the operator * Param : binary expression to evaluate * Return : the value of the binary expression */ public Value VisitBinaryExpr(Expr.Binary expr) { Value left = Evaluate(expr.Left); Value right = Evaluate(expr.Right); switch (expr.OperatorToken.Kind) { /* Case '-' for only numbers */ case TokenKind.Minus: CheckNumberOperand(expr.OperatorToken, left, right); return(new Value(VALTYPE.INT, (int)left.Val - (int)right.Val)); /* Case '*' for only numbers */ case TokenKind.Mult: CheckNumberOperand(expr.OperatorToken, left, right); return(new Value(VALTYPE.INT, (int)left.Val * (int)right.Val)); /* Case '/' for only numbers */ case TokenKind.Div: CheckNumberOperand(expr.OperatorToken, left, right); return(new Value(VALTYPE.INT, (int)left.Val / (int)right.Val)); /* Case '+' for both numbers and strings */ case TokenKind.Sum: if (left.Type.Equals(VALTYPE.INT) && right.Type.Equals(VALTYPE.INT)) { return(new Value(VALTYPE.INT, (int)left.Val + (int)right.Val)); } else if (left.Type.Equals(VALTYPE.STRING) && right.Type.Equals(VALTYPE.STRING)) { return(new Value(VALTYPE.STRING, (string)left.Val + (string)right.Val)); } break; /* Case '=' for both numbers, strings or bools */ case TokenKind.Equal: if (left.Type.Equals(VALTYPE.INT) && right.Type.Equals(VALTYPE.INT)) { return(new Value(VALTYPE.BOOL, ((int)left.Val == (int)right.Val))); } else if (left.Type.Equals(VALTYPE.STRING) && right.Type.Equals(VALTYPE.STRING)) { return(new Value(VALTYPE.BOOL, ((string)left.Val == (string)right.Val))); } else if (left.Type.Equals(VALTYPE.BOOL) && right.Type.Equals(VALTYPE.BOOL)) { return(new Value(VALTYPE.BOOL, ((bool)left.Val == (bool)right.Val))); } break; /* Case '<' for both numbers, strings or bools */ case TokenKind.Less: if (left.Type.Equals(VALTYPE.INT) && right.Type.Equals(VALTYPE.INT)) { return(new Value(VALTYPE.BOOL, ((int)left.Val < (int)right.Val))); } else if (left.Type.Equals(VALTYPE.STRING) && right.Type.Equals(VALTYPE.STRING)) { return(new Value(VALTYPE.BOOL, (string.Compare((string)left.Val, (string)right.Val) == -1))); } else if (left.Type.Equals(VALTYPE.BOOL) && right.Type.Equals(VALTYPE.BOOL)) { return(new Value(VALTYPE.BOOL, (((bool)left.Val).CompareTo((bool)right.Val) < 0))); } break; } /* Error if the operands are different type */ throw new RuntimeError(expr.OperatorToken, "Operands must be the same type."); }
/** * Function VisitBinaryExpression * Param : binary expression to visit * Return : the parse tree of the left and right with the operator */ public String VisitBinaryExpr(Expr.Binary expr) { return(Print(expr.Left) + " " + expr.OperatorToken.Text + " " + Print(expr.Right)); }