def _assignment(self): expression = self._or() if self._match([TokenType.LEFT_ARROW]): leftArrow = self._previous() value = self._assignment() if isinstance(expression, Expression.Variable): identifier = expression.getIdentifier() return Expression.Assign(identifier, value) elif isinstance(expression, Expression.Get): return Expression.Set(expression.getObject(), expression.getIdentifier(), value) elif isinstance(expression, Expression.GetIndex): return Expression.SetIndex(expression.getObject(), expression.getIndices(), expression.getBrackets(), value) self._error(leftArrow, "Invalid assignment target.") return expression
def _unary(self): if self._match([TokenType.NOT, TokenType.MINUS]): operator = self._previous() right = self._unary() return Expression.Unary(operator, right) return self._index()
def _or(self): expression = self._and() while self._match([TokenType.OR]): operator = self._previous() right = self._and() #check this line! expression = Expression.Logical(expression, operator, right) return expression
def _twoDimensionalArithmetic(self): expression = self._unary() while self._match([TokenType.SLASH, TokenType.STAR]): operator = self._previous() right = self._unary() expression = Expression.Binary(expression, operator, right) return expression
def _oneDimensionalArithmetic(self): expression = self._twoDimensionalArithmetic() while self._match([TokenType.PLUS, TokenType.MINUS]): operator = self._previous() right = self._twoDimensionalArithmetic() expression = Expression.Binary(expression, operator, right) return expression
def _comparison(self): expression = self._oneDimensionalArithmetic() while self._match([TokenType.LESS, TokenType.GREATER, TokenType.LESS_EQUAL, TokenType.GREATER_EQUAL]): operator = self._previous() right = self._oneDimensionalArithmetic() expression = Expression.Binary(expression, operator, right) return expression
def _equality(self): expression = self._comparison() while self._match([TokenType.NOT_EQUAL, TokenType.EQUAL]): operator = self._previous() right = self._comparison() expression = Expression.Binary(expression, operator, right) return expression
def _and(self): expression = self._equality() while self._match([TokenType.AND]): operator = self._previous() right = self._equality() expression = Expression.Logical(expression, operator, right) return expression
def _finishFunctionCall(self, caller): arguments = [] if not self._check(TokenType.RIGHT_PAREN): while True: if len(arguments) >= 8: self._error(self._peek(), "Cannot have more than 8 arguments.") arguments.append(self._expression()) if not self._match([TokenType.COMMA]): break parantheses = self._consume(TokenType.RIGHT_PAREN, "Expect ')' after arguments.") return Expression.Call(caller, parantheses, arguments)
def _forStatement(self): if self._match([TokenType.VAR]): identifier = self._consume(TokenType.IDENTIFIER, "Expect variable identifier.") self._consume(TokenType.LEFT_ARROW, "Expect '<-' after variable identifier.") expression = self._expression() initializer = Statement.Variable(identifier, expression) else: raise self._error(self._peek(), "Expect a variable declaration after 'FOR'.") self._consume(TokenType.TO, "Expect 'TO' after varable declaration.") right = self._oneDimensionalArithmetic() condition = Expression.Binary( Expression.Variable(identifier), Token(TokenType.LESS_EQUAL, "<=", None, "NULL", -1), right ) increment = Expression.Assign(identifier, Expression.Binary( Expression.Variable(identifier), Token(TokenType.PLUS, "+", None, "NULL", -1), Expression.Literal(1.0) )) self._consume(TokenType.DO, "Expect 'DO' at end of for loop initialization.") body = self._bodyDeclaration(TokenType.ENDFOR) self._consume(TokenType.ENDFOR, "Expect 'ENDFOR' at end of the for loop.") body.append(Statement.Expression(increment)) return Statement.For(initializer, condition, body)
def _functionCall(self): expression = self._primary() while True: if self._match([TokenType.LEFT_PAREN]): expression = self._finishFunctionCall(expression) elif self._match([TokenType.DOT]): identifier = self._consume(TokenType.IDENTIFIER, "Expect property identifier after '.'.") expression = Expression.Get(expression, identifier) else: break return expression
def _classDeclaration(self): identifier = self._consume(TokenType.IDENTIFIER, "Expect class identifier.") superClass = None if self._match([TokenType.INHERITS]): self._consume(TokenType.IDENTIFIER, "Expect superclass identifier.") superClass = Expression.Variable(self._previous()) methods = [] while not self._check(TokenType.ENDCLASS) and not self._isAtEnd(): if self._match([TokenType.FUNCTION]): methods.append(self._functionDeclaration()) self._consume(TokenType.ENDCLASS, "Expect 'ENDCLASS' after class body.") return Statement.Class(identifier, superClass, methods)
def _primary(self): if self._match([TokenType.FALSE]): return Expression.Literal(False) if self._match([TokenType.TRUE]): return Expression.Literal(True) if self._match([TokenType.NULL]): return Expression.Literal(None) if self._match([TokenType.NUMBER, TokenType.STRING]): return Expression.Literal(self._previous().getLiteral()) if self._match([TokenType.SUPER]): keyword = self._previous() self._consume(TokenType.DOT, "Expect '.' after 'SUPER'.") method = self._consume(TokenType.IDENTIFIER, "Expect super class method name.") return Expression.Super(keyword, method) if self._match([TokenType.THIS]): return Expression.This(self._previous()) if self._match([TokenType.LEFT_BRACE]): values = [] while True: values.append(self._expression()) if not self._match([TokenType.COMMA]): break self._consume(TokenType.RIGHT_BRACE, "Expect '}' after values.") return Expression.List(values) if self._match([TokenType.IDENTIFIER]): return Expression.Variable(self._previous()) if self._match([TokenType.LEFT_PAREN]): expression = self._expression() self._consume(TokenType.RIGHT_PAREN, "Expect ')' after expression.") return Expression.Grouping(expression) raise self._error(self._peek(), "Expect expression.")
def _index(self): expression = self._functionCall() if self._match([TokenType.LEFT_SQUARE]): indices = [] while True: if not self._peek().getType() in [TokenType.IDENTIFIER, TokenType.NUMBER]: self._error(self._peek(), "Expect identifier or number for index value.") indices.append(self._expression()) if not self._match([TokenType.COMMA]): break brackets = self._consume(TokenType.RIGHT_SQUARE, "Expect ']' after index value.") return Expression.GetIndex(expression, indices, brackets) return expression