private Expr Term() { Expr expression = Factor(); while (Match(TokenType.Minus, TokenType.Plus)) { Token @operator = Previous(); Expr right = Factor(); expression = new Expr.Binary(expression, @operator, right); } return(expression); }
private Expr Factor() { Expr expression = Unary(); while (Match(TokenType.Slash, TokenType.Star, TokenType.Modulus)) { Token @operator = Previous(); Expr right = Unary(); expression = new Expr.Binary(expression, @operator, right); } return(expression); }
/// <summary> /// The grammar rule is virtually identical and so is the code. /// The only differences are the token types for the operators we match, and the /// method we call for the operands, now term(). The remaining two binary /// operator rules follow the same pattern: /// </summary> /// <returns></returns> private Expr Comparison() { Expr expression = Term(); while (Match(TokenType.Greater, TokenType.GreaterEqual, TokenType.Less, TokenType.LessEqual)) { Token @operator = Previous(); Expr right = Term(); expression = new Expr.Binary(expression, @operator, right); } return(expression); }
public Expr Equality() { Expr expression = Comparison(); while (Match(TokenType.BangEqual, TokenType.EqualEqual)) { Token @operator = Previous(); Expr right = Comparison(); expression = new Expr.Binary(expression, @operator, right); } return(expression); }
public object Visit(Expr.Binary _binary) { Resolve(_binary.lhs); Resolve(_binary.rhs); return(null); }
// Visitors string Expr.IVisitor <string> .Visit(Expr.Binary binary) { return(Parenthesize(binary.opp.lexeme, binary.lhs, binary.rhs)); }
public object Visit(Expr.Binary binary) { object right = Evaluate(binary.rhs); object left = Evaluate(binary.lhs); switch (binary.opp.type) { case TokenType.Greater: ValidateNumberOperand(binary.opp, left, right); return((double)left > (double)right); case TokenType.GreaterEqual: ValidateNumberOperand(binary.opp, left, right); return((double)left >= (double)right); case TokenType.Less: ValidateNumberOperand(binary.opp, left, right); return((double)left < (double)right); case TokenType.LessEqual: ValidateNumberOperand(binary.opp, left, right); return((double)left <= (double)right); case TokenType.Minus: ValidateNumberOperand(binary.opp, left, right); return((double)left - (double)right); case TokenType.Plus: if (left is double && right is double) { return((double)left + (double)right); } else if (left is string) { return((string)left + Stringify(right)); } // Not valid addition type. throw new RuntimeError(binary.opp, "Operands must be two numbers or two strings."); case TokenType.Modulus: ValidateNumberOperand(binary.opp, left, right); return((double)left % (double)right); case TokenType.Slash: ValidateNumberOperand(binary.opp, left, right); ValidateDivision(binary.opp, right); return((double)left / (double)right); case TokenType.Star: ValidateNumberOperand(binary.opp, left, right); return((double)left * (double)right); case TokenType.BangEqual: return(!IsEqual(left, right)); case TokenType.EqualEqual: return(IsEqual(left, right)); } // Unreachable. return(null); }