// 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); }
// 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); }
// 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); }
// 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); }
// 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); }
public string VisitBinaryExpr(Expr.Binary expr) { return(Parenthesize(expr.op.lexeme, expr.left, expr.right)); }
public object VisitBinaryExpr(Expr.Binary expr) { Resolve(expr.left); Resolve(expr.right); return(null); }
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); }