def test_struct_with_member_functions(self): buf = """ struct Foo { string name; int age; fn memberFunc() -> int { return age; } }; """ exprs = [ ast.Structure( "Foo", [ ast.Member("name", ast.Type(ast.TypeKind.STRING)), ast.Member("age", ast.Type(ast.TypeKind.INT)), ], [ ast.Function( "memberFunc", [("this", ast.Type(ast.TypeKind.USER, "Foo"))], [ast.ReturnStatement(ast.VariableRef("age"))], 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_function(self): buf = """ fn fooFunc(string name, int age) -> int { return 1; } """ exprs = [ ast.Function( "fooFunc", [("name", ast.Type(ast.TypeKind.STRING)), ("age", ast.Type(ast.TypeKind.INT))], [ast.ReturnStatement(ast.Number(1))], ast.Type(ast.TypeKind.INT), ) ] self._test_parse_impl(buf, exprs)
def test_constructor(self): buf = """ fn constructorTest() -> int { let foo = new Foo(name, age); return 0; } """ exprs = [ ast.Function( "constructorTest", [], [ ast.LetStatement( "foo", ast.Constructor( "Foo", [ast.VariableRef("name"), ast.VariableRef("age")]), ), 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 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_struct(self): buf = """ struct Foo { string name; int age; }; """ exprs = [ ast.Structure( "Foo", [ ast.Member("name", ast.Type(ast.TypeKind.STRING)), ast.Member("age", ast.Type(ast.TypeKind.INT)), ], [], ) ] self._test_parse_impl(buf, exprs)
def test_string_literals(self): buf = """ fn fooString() -> string { return "string_literal_value"; } """ exprs = [ ast.Function( "fooString", [], [ast.ReturnStatement(ast.String("string_literal_value"))], ast.Type(ast.TypeKind.STRING), ) ] self._test_parse_impl(buf, exprs)
def test_function_call(self): buf = """ fn funcCall() -> int { return otherFunc(); } """ exprs = [ ast.Function( "funcCall", [], [ast.ReturnStatement(ast.FunctionCall("otherFunc", []))], ast.Type(ast.TypeKind.INT), ) ] self._test_parse_impl(buf, exprs)
def test_member_access(self): buf = """ fn foo() -> int { return bar.age; } """ exprs = [ ast.Function( "foo", [], [ ast.ReturnStatement( ast.MemberAccess(ast.VariableRef("bar"), "age")) ], ast.Type(ast.TypeKind.INT), ) ] self._test_parse_impl(buf, exprs)
def test_let_statement(self): buf = """ fn letFunc() -> int { let x = 1; return x; } """ exprs = [ ast.Function( "letFunc", [], [ ast.LetStatement("x", ast.Number(1)), ast.ReturnStatement(ast.VariableRef("x")) ], ast.Type(ast.TypeKind.INT), ) ] self._test_parse_impl(buf, exprs)
def _parse_structure(self): s_name = self.cur_tok.value self._expect_token(TokenType.IDENTIFIER) self._expect_token(TokenType.L_BRACE) # Parse members. members = list() while not ( self.cur_tok.type == TokenType.FUNCTION or self.cur_tok.type == TokenType.R_BRACE ): members.append(self._parse_member()) member_functions = list() while self._consume_token(TokenType.FUNCTION): member_functions.append( self._parse_function(("this", ast.Type(ast.TypeKind.USER, s_name))) ) self._expect_token(TokenType.R_BRACE) self._expect_token(TokenType.SEMICOLON) return ast.Structure(s_name, members, member_functions)
def _parse_type(self): if self._consume_token(TokenType.INT): return ast.Type(ast.TypeKind.INT) elif self._consume_token(TokenType.STRING): return ast.Type(ast.TypeKind.STRING) elif self._consume_token(TokenType.VECTOR): self._expect_token(TokenType.LESS_THAN) container_type = self._parse_type() self._expect_token(TokenType.GREATER_THAN) return ast.Type(ast.TypeKind.VECTOR, None, container_type) elif self._consume_token(TokenType.MAP): self._expect_token(TokenType.LESS_THAN) container_type = self._parse_type() self._expect_token(TokenType.GREATER_THAN) return ast.Type(ast.TypeKind.MAP, None, container_type) elif self._consume_token(TokenType.VOID): return ast.Type(ast.TypeKind.VOID) else: # User defined type. Should just look like a regular identifier. identifier = self.cur_tok.value self._expect_token(TokenType.IDENTIFIER) return ast.Type(ast.TypeKind.USER, identifier)