def test_parse_atoms(self): self.assertEqual(expr.parse('1'), True) self.assertEqual(expr.parse('0'), False) self.assertEqual(expr.parse('a'), expr.Variable(name='a')) self.assertEqual(expr.parse('ab'), expr.Variable(name='ab')) self.assertEqual(expr.parse('(a)'), expr.Variable(name='a')) self.assertEqual(expr.parse(' 1'), True) self.assertEqual(expr.parse('1 '), True)
def test_parse_exprs(self): self.assertEqual( expr.parse('a&1&0'), expr.AndExpr( exprs=frozenset([expr.Variable(name='a'), True, False]))) self.assertEqual( expr.parse('a|1|0'), expr.OrExpr(exprs=frozenset([expr.Variable( name='a'), True, False]))) self.assertEqual(expr.parse('~a'), expr.NotExpr(expr=expr.Variable(name='a')))
def primary(self) -> e.Expr: if self.match(TokenType.FALSE): return e.Literal(False) if self.match(TokenType.TRUE): return e.Literal(True) if self.match(TokenType.NIL): return e.Literal(None) if self.match(TokenType.NUMBER, TokenType.STRING): return e.Literal(self.previous().literal) if self.match(TokenType.SUPER): keyword: Token = self.previous() self.consume(TokenType.DOT, "Expect '.' after 'super'.") method: Token = self.consume(TokenType.IDENTIFIER, "Expect superclass method name.") return e.Super(keyword, method) if self.match(TokenType.THIS): return e.This(self.previous()) if self.match(TokenType.IDENTIFIER): return e.Variable(self.previous()) if self.match(TokenType.LEFT_PAREN): expr: e.Expr = self.expression() self.consume(TokenType.RIGHT_PAREN, "Expect ')' after expression.") return e.Grouping(expr) raise self.error(self.peek(), "Expect expression.")
def _primary(self) -> ex.Expr: if self._match(TokenType.FALSE): return ex.Literal(False) if self._match(TokenType.TRUE): return ex.Literal(True) if self._match(TokenType.NIL): return ex.Literal(None) if self._match(TokenType.NUMBER, TokenType.STRING): return ex.Literal(self._previous.literal) if self._match(TokenType.SUPER): keyword = self._previous self._consume(TokenType.DOT, "Expect a '.' after 'super'.") method = self._consume(TokenType.IDENTIFIER, 'Expect superclass method name.') return ex.Super(keyword, method) if self._match(TokenType.THIS): return ex.This(self._previous) if self._match(TokenType.IDENTIFIER): return ex.Variable(self._previous) if self._match(TokenType.LEFT_PAREN): expr = self._expression() self._consume(TokenType.RIGHT_PAREN, "Expect ')' after expression.") return ex.Grouping(expr) raise self._error(self._peek(), 'Expect expression.')
def crement(self): isAdding = False if self.peek(-1).type == TokenType.PLUS_PLUS: isAdding = True identifier = self.peek(-2) if isAdding: tok = TokenType.PLUS else: tok = TokenType.MINUS val = 1 return Expr.Assignment( Expr.Variable(identifier).name, Expr.Binary(Expr.Variable(identifier), Token(tok, None, None, None), Expr.Literal(val)))
def _class_declaration(self) -> st.Class: name = self._consume(TokenType.IDENTIFIER, 'Expect class name.') superclass = None if self._match(TokenType.LESS): self._consume(TokenType.IDENTIFIER, 'Expect superclass name.') superclass = ex.Variable(self._previous) self._consume(TokenType.LEFT_BRACE, "Expect '{' before class body.") methods = [] while not self._check(TokenType.RIGHT_BRACE) and not self._is_at_end: methods.append(self._function('method')) self._consume(TokenType.RIGHT_BRACE, "Expect '}' after class body.") return st.Class(name, superclass, methods)
def assignment(self): left = self.ternary() if self.match(TokenType.EQUAL): equals = self.peek(-1) value = self.assignment() if isinstance(left, Expr.Variable): return Expr.Assignment(left.name, value) self.error(equals, "Invalid assignment target.") elif self.match(TokenType.PLUS_EQUAL, TokenType.MINUS_EQUAL): tok = TokenType.MINUS if self.peek(-1).type == TokenType.PLUS_EQUAL: tok = TokenType.PLUS identifier = self.peek(-2) val = self.expression() return Expr.Assignment( Expr.Variable(identifier).name, Expr.Binary(Expr.Variable(identifier), Token(tok, None, None, None), val)) return left
def classDeclaration(self) -> s.Stmt: name: Token = self.consume(TokenType.IDENTIFIER, "Expect class name.") superclass: Optional[e.Variable] = None if self.match(TokenType.LESS): self.consume(TokenType.IDENTIFIER, "Expect superclass name.") superclass = e.Variable(self.previous()) self.consume(TokenType.LEFT_BRACE, "Expect '{' before class body.") methods: List[s.Function] = [] while not self.check(TokenType.RIGHT_BRACE) and not self.isAtEnd(): methods.append(self.function("method")) self.consume(TokenType.RIGHT_BRACE, "Expect '}' after class body.") return s.Class(name, superclass, methods)
def primary(self): if self.match(TokenType.FALSE): return Expr.Literal(False) if self.match(TokenType.TRUE): return Expr.Literal(True) if self.match(TokenType.NIL): return Expr.Literal(None) if self.match(TokenType.NUMBER, TokenType.STRING): return Expr.Literal(self.peek(-1).literal) if self.match(TokenType.LEFT_PAREN): expr = self.expression() self.consume(TokenType.RIGHT_PAREN, "Missing ')' after expression") return Expr.Grouping(expr) if self.match(TokenType.IDENTIFIER): return Expr.Variable(self.peek(-1)) raise self.error(self.peek(), "Requires an expression")
def parse_atom(self): token = self.get_token if token.tag == Token.LPAREN: e = self.parse_expr() self.expect(Token.RPAREN) return e elif token.tag == Token.NUMBER: return E.NumberLit(token.value) elif token.tag == Token.ID: return E.Variable(token.value) elif token.tag == Token.LET: var = self.get_token assert (var.tag == Token.ID) self.expect(Token.ASSIGN) e1 = self.parse_expr() self.expect(Token.IN) e2 = self.parse_expr() self.expect(Token.END) return E.LetIn(var.value, e1, e2)