def test_func_without_return_type_exceptional(parser: RecursiveDescentParser): snippet = r""" test() { ret a or b }""" with io.StringIO(snippet) as f: with pytest.raises(UnexpectedToken): parser.parse(f)
def interpret(snippet: str, grammar: str): scanner = Scanner(grammar) parser = RecursiveDescentParser(scanner) interpreter = Interpreter(is_test=True) with io.StringIO(snippet) as f: return interpreter.interpret(TreeTransformer().transform( parser.parse(f)))
def test_not_matched_parentheses_exceptional(parser: RecursiveDescentParser): snippet = r""" test() void { ret (a(b)(k }""" with io.StringIO(snippet) as f: with pytest.raises(UnexpectedToken): parser.parse(f)
def test_type_with_comma_instead_of_dot_exceptional(parser: RecursiveDescentParser): snippet = r""" test() void { ret a,b }""" with io.StringIO(snippet) as f: with pytest.raises(PrimaryExpressionException): parser.parse(f)
def test_for_without_in_exceptional(parser: RecursiveDescentParser): snippet = r""" test() { for i range(10) { print(i) } }""" with io.StringIO(snippet) as f: with pytest.raises(UnexpectedToken): parser.parse(f)
def main(): with open('../../grammar.txt') as f: data = f.read() scanner = Scanner(data) parser = RecursiveDescentParser(scanner) with open("../../test files/recursive_fibo.txt") as f: tree = parser.parse(f) transformed = TreeTransformer().transform(tree) SemanticAnalyzer().analyze(transformed) Interpreter().interpret(transformed)
def test_elseif_expression(parser: RecursiveDescentParser): snippet = r""" test() void { if a { print(a) } elif b { print(b) } }""" expected = Tree('start', [Tree('function_declaration', [Token('NAME', 'test'), Tree('function_parameters', []), Token('NAME', 'void'), Tree('statements_block', [Tree('if_expression', [Token('NAME', 'a'), Tree('statements_block', [Tree( 'postfix_unary_expression', [Token('NAME', 'print'), Tree('call_suffix', [Token('NAME', 'a')])])]), Tree('elseif_expression', [Token('NAME', 'b'), Tree('statements_block', [ Tree( 'postfix_unary_expression', [Token('NAME', 'print'), Tree('call_suffix', [Token( 'NAME', 'b')])])])])])])])]) with io.StringIO(snippet) as f: res, msg = compare_trees(expected, parser.parse(f)) assert res, msg
def test_reassignment(parser: RecursiveDescentParser): snippet = r""" test() void { var x int = 1 x = 2 }""" expected = Tree('start', [Tree('function_declaration', [Token('NAME', 'test'), Tree('function_parameters', []), Token('NAME', 'void'), Tree('statements_block', [ Tree('assignment', [ Tree('variable_declaration', [ Token('VAR', 'var'), Token('NAME', 'x'), Tree('type', [Token('NAME', 'int')])]), Token('ASSIGNMENT_OPERATOR', '='), Token('DEC_NUMBER', '1')]), Tree('assignment', [ Token('NAME', 'x'), Token('ASSIGNMENT_OPERATOR', '='), Token('DEC_NUMBER', '2')])])])]) with io.StringIO(snippet) as f: res, msg = compare_trees(expected, parser.parse(f)) assert res, msg
def test_parenthesized_expression3(parser: RecursiveDescentParser): snippet = r""" test() int { ret (k / (a + b)) }""" expected = Tree('start', [Tree( 'function_declaration', [Token('NAME', 'test'), Tree( 'function_parameters', []), Token('NAME', 'int'), Tree( 'statements_block', [Tree( 'return_statement', [Tree( 'parenthesized_expression', [Tree( 'multiplicative_expression', [Token('NAME', 'k'), Token( 'MULTIPLICATIVE_OPERATOR', '/'), Tree( 'parenthesized_expression', [Tree( 'additive_expression', [Token('NAME', 'a'), Token( 'ADDITIVE_OPERATOR', '+'), Token('NAME', 'b')])])])])])])])]) with io.StringIO(snippet) as f: res, msg = compare_trees(expected, parser.parse(f)) assert res, msg
def test_multiple_assignments(parser: RecursiveDescentParser): snippet = r""" test() void { let x int = n1 + n2 let y int = n3 + n4 }""" expected = Tree('start', [Tree('function_declaration', [Token('NAME', 'test'), Tree('function_parameters', []), Token('NAME', 'void'), Tree('statements_block', [Tree('assignment', [Tree('variable_declaration', [Token('LET', 'let'), Token('NAME', 'x'), Tree('type', [Token( 'NAME', 'int')])]), Token('ASSIGNMENT_OPERATOR', '='), Tree('additive_expression', [Token('NAME', 'n1'), Token('ADDITIVE_OPERATOR', '+'), Token('NAME', 'n2')])]), Tree('assignment', [Tree('variable_declaration', [Token('LET', 'let'), Token('NAME', 'y'), Tree('type', [Token( 'NAME', 'int')])]), Token('ASSIGNMENT_OPERATOR', '='), Tree('additive_expression', [Token('NAME', 'n3'), Token('ADDITIVE_OPERATOR', '+'), Token('NAME', 'n4')])])])])]) with io.StringIO(snippet) as f: res, msg = compare_trees(expected, parser.parse(f)) assert res, msg
def test_parenthesized_expression(parser: RecursiveDescentParser): snippet = r""" test() int { ret (a) }""" expected = Tree('start', [Tree('function_declaration', [Token('NAME', 'test'), Tree('function_parameters', []), Token('NAME', 'int'), Tree('statements_block', [Tree('return_statement', [ Tree('parenthesized_expression', [Token('NAME', 'a')])])])])]) with io.StringIO(snippet) as f: res, msg = compare_trees(expected, parser.parse(f)) assert res, msg
def test_zero_function_parameters(parser: RecursiveDescentParser): snippet = r""" test() void { ret }""" expected = Tree('start', [Tree('function_declaration', [Token('NAME', 'test'), Tree('function_parameters', []), Token('NAME', 'void'), Tree('statements_block', [Tree('return_statement', [])])])]) with io.StringIO(snippet) as f: res, msg = compare_trees(expected, parser.parse(f)) assert res, msg
def test_equality(parser: RecursiveDescentParser): snippet = r""" test() bool { ret a == b }""" expected = Tree('start', [Tree('function_declaration', [Token('NAME', 'test'), Tree('function_parameters', []), Token('NAME', 'bool'), Tree('statements_block', [Tree('return_statement', [Tree('equality', [Token('NAME', 'a'), Token('EQUALITY_OPERATOR', '=='), Token('NAME', 'b')])])])])]) with io.StringIO(snippet) as f: res, msg = compare_trees(expected, parser.parse(f)) assert res, msg
def test_prefix_unary_expression(parser: RecursiveDescentParser): snippet = r""" test() bool { ret -a }""" expected = Tree('start', [Tree('function_declaration', [Token('NAME', 'test'), Tree('function_parameters', []), Token('NAME', 'bool'), Tree('statements_block', [Tree('return_statement', [Tree('prefix_unary_expression', [Token('ADDITIVE_OPERATOR', '-'), Token('NAME', 'a')])])])])]) with io.StringIO(snippet) as f: res, msg = compare_trees(expected, parser.parse(f)) assert res, msg
def test_collection_literal(parser: RecursiveDescentParser): snippet = r""" test() List { ret [1,2,3] }""" expected = Tree('start', [Tree('function_declaration', [Token('NAME', 'test'), Tree('function_parameters', []), Token('NAME', 'List'), Tree('statements_block', [Tree('return_statement', [Tree('collection_literal', [Token('DEC_NUMBER', '1'), Token('DEC_NUMBER', '2'), Token('DEC_NUMBER', '3')])])])])]) with io.StringIO(snippet) as f: res, msg = compare_trees(expected, parser.parse(f)) assert res, msg
def test_conjunction(parser: RecursiveDescentParser): snippet = r""" test() bool { ret a and b and k }""" expected = Tree('start', [Tree('function_declaration', [Token('NAME', 'test'), Tree('function_parameters', []), Token('NAME', 'bool'), Tree('statements_block', [Tree('return_statement', [Tree('conjunction', [Token('NAME', 'a'), Token('NAME', 'b'), Token('NAME', 'k')])])])])]) with io.StringIO(snippet) as f: res, msg = compare_trees(expected, parser.parse(f)) assert res, msg
def test_indexing_suffix(parser: RecursiveDescentParser): snippet = r""" test() int { ret a[0] }""" expected = Tree('start', [Tree('function_declaration', [Token('NAME', 'test'), Tree('function_parameters', []), Token('NAME', 'int'), Tree('statements_block', [Tree('return_statement', [Tree('postfix_unary_expression', [Token('NAME', 'a'), Tree('indexing_suffix', [Token('DEC_NUMBER', '0')])])])])])]) with io.StringIO(snippet) as f: res, msg = compare_trees(expected, parser.parse(f)) assert res, msg
def test_three_function_parameters(parser: RecursiveDescentParser): snippet = r""" test(age int, isMale bool, name str) int { ret a }""" expected = Tree('start', [Tree('function_declaration', [Token('NAME', 'test'), Tree('function_parameters', [ Tree('function_parameter', [Token('NAME', 'age'), Tree('type', [Token('NAME', 'int')])]), Tree('function_parameter', [Token('NAME', 'isMale'), Tree('type', [Token('NAME', 'bool')])]), Tree('function_parameter', [Token('NAME', 'name'), Tree('type', [Token('NAME', 'str')])])]), Token('NAME', 'int'), Tree('statements_block', [Tree('return_statement', [Token('NAME', 'a')])])])]) with io.StringIO(snippet) as f: res, msg = compare_trees(expected, parser.parse(f)) assert res, msg
def test_wile_stmt(parser: RecursiveDescentParser): snippet = r""" test() void { while ok() { print(i) } }""" expected = Tree('start', [Tree('function_declaration', [Token('NAME', 'test'), Tree('function_parameters', []), Token('NAME', 'void'), Tree('statements_block', [Tree('while_statement', [Tree('postfix_unary_expression', [Token('NAME', 'ok'), Tree('call_suffix', [])]), Tree('statements_block', [Tree( 'postfix_unary_expression', [Token('NAME', 'print'), Tree('call_suffix', [Token('NAME', 'i')])])])])])])]) with io.StringIO(snippet) as f: res, msg = compare_trees(expected, parser.parse(f)) assert res, msg
def test_if_as_expression(parser: RecursiveDescentParser): snippet = r""" test() int { ret if a>b {ret a} else {ret b} }""" expected = Tree('start', [Tree('function_declaration', [Token('NAME', 'test'), Tree('function_parameters', []), Token('NAME', 'int'), Tree('statements_block', [Tree('return_statement', [ Tree('if_expression', [Tree('comparison', [Token('NAME', 'a'), Token('COMPARISON_OPERATOR', '>'), Token('NAME', 'b')]), Tree('statements_block', [Tree('return_statement', [Token('NAME', 'a')])]), Tree('else_expression', [ Tree('statements_block', [Tree('return_statement', [ Token('NAME', 'b')])])])])])])])]) with io.StringIO(snippet) as f: res, msg = compare_trees(expected, parser.parse(f)) assert res, msg
def analyze(snippet: str, grammar: str): scanner = Scanner(grammar) parser = RecursiveDescentParser(scanner) with io.StringIO(snippet) as f: SemanticAnalyzer().analyze(TreeTransformer().transform( parser.parse(f)))
def parser(): with open(Path(os.getenv('PROJECT_ROOT')) / 'grammar.txt') as f: return RecursiveDescentParser(Scanner(f.read()))
def test_while_with_break(parser: RecursiveDescentParser): snippet = r""" main() None { var x int = 0 while x < 5 { if x > 2 { break } test_print(str(x)) x = x + 1 } }""" expected = Tree('start', [Tree('function_declaration', [Token('NAME', 'main'), Tree('function_parameters', []), Token('NAME', 'None'), Tree('statements_block', [ Tree('assignment', [ Tree('variable_declaration', [Token('VAR', 'var'), Token('NAME', 'x'), Tree('type', [Token( 'NAME', 'int')])]), Token('ASSIGNMENT_OPERATOR', '='), Token('DEC_NUMBER', '0')]), Tree('while_statement', [ Tree('comparison', [Token('NAME', 'x'), Token( 'COMPARISON_OPERATOR', '<'), Token('DEC_NUMBER', '5')]), Tree('statements_block', [ Tree('if_expression', [ Tree('comparison', [Token('NAME', 'x'), Token( 'COMPARISON_OPERATOR', '>'), Token('DEC_NUMBER', '2')]), Tree('statements_block', [Tree( 'break_statement', [Token('BREAK', 'break')])])]), Tree( 'postfix_unary_expression', [Token('NAME', 'test_print'), Tree('call_suffix', [ Tree( 'postfix_unary_expression', [Token('NAME', 'str'), Tree( 'call_suffix', [Token( 'NAME', 'x')])])])]), Tree('assignment', [Token('NAME', 'x'), Token( 'ASSIGNMENT_OPERATOR', '='), Tree( 'additive_expression', [Token('NAME', 'x'), Token( 'ADDITIVE_OPERATOR', '+'), Token('DEC_NUMBER', '1')])])])])])])]) with io.StringIO(snippet) as f: res, msg = compare_trees(expected, parser.parse(f)) assert res, msg