def test_precedence(self): buf = """ fn prec() -> int { 2 + 3 * 2 + 2 / 8; } """ exprs = [ ast.Function( "prec", [], [ ast.ExprStatement( ast.BinaryOp( ast.BinaryOp( ast.Number(2), ast.BinaryOp(ast.Number(3), ast.Number(2), Token(TokenType.MULTIPLY, "*")), Token(TokenType.ADD, "+"), ), ast.BinaryOp(ast.Number(2), ast.Number(8), Token(TokenType.DIVIDE, "/")), Token(TokenType.ADD, "+"), )) ], ast.Type(ast.TypeKind.INT), ) ] self._test_parse_impl(buf, exprs)
def test_while_loop(self): buf = """ fn loopTest(int x) -> int { while (x < 5) { print("blah"); } return 0; } """ exprs = [ ast.Function( "loopTest", [("x", ast.Type(ast.TypeKind.INT))], [ ast.WhileLoop( ast.BinaryOp(ast.VariableRef("x"), ast.Number(5), Token(TokenType.LESS_THAN, "<")), [ ast.ExprStatement( ast.FunctionCall("print", [ast.String("blah")])) ], ), ast.ReturnStatement(ast.Number(0)), ], ast.Type(ast.TypeKind.INT), ) ] self._test_parse_impl(buf, exprs)
def test_if_statements(self): buf = """ fn foo() -> string { if (3 == 3) { return "foo"; } return "bar"; } """ exprs = [ ast.Function( "foo", [], [ ast.IfStatement( ast.BinaryOp(ast.Number(3), ast.Number(3), Token(TokenType.EQUALS, "==")), [ast.ReturnStatement(ast.String("foo"))], list(), ), ast.ReturnStatement(ast.String("bar")), ], ast.Type(ast.TypeKind.STRING), ) ] self._test_parse_impl(buf, exprs)
def _parse_multiplication(self): lhs = self._parse_postfix() while True: tok = self.cur_tok if self._consume_token(TokenType.MULTIPLY) or self._consume_token(TokenType.DIVIDE): lhs = ast.BinaryOp(lhs, self._parse_primary_expr(), tok) else: return lhs
def _parse_addition(self): lhs = self._parse_multiplication() while True: tok = self.cur_tok if self._consume_token(TokenType.ADD) or self._consume_token(TokenType.SUBTRACT): lhs = ast.BinaryOp(lhs, self._parse_multiplication(), tok) else: return lhs
def _parse_equality(self): lhs = self._parse_relational() while True: tok = self.cur_tok if self._consume_token(TokenType.EQUALS) or self._consume_token(TokenType.NOT_EQUALS): lhs = ast.BinaryOp(lhs, self._parse_relational(), tok) else: return lhs
def _parse_assignment(self): lhs = self._parse_equality() while True: tok = self.cur_tok if self._consume_token(TokenType.ASSIGN): lhs = ast.BinaryOp(lhs, self._parse_equality(), tok) else: return lhs
def _parse_relational(self): lhs = self._parse_addition() while True: tok = self.cur_tok if ( self._consume_token(TokenType.LESS_THAN) or self._consume_token(TokenType.LESS_THAN_EQ) or self._consume_token(TokenType.GREATER_THAN) or self._consume_token(TokenType.GREATER_THAN_EQ) ): lhs = ast.BinaryOp(lhs, self._parse_addition(), tok) else: return lhs