def test_dangling_else_iiaeiaea(): text = """ if (a < b) if (c < d) break; else if (e < f) continue; else return; """ ast = parser.parse(text) assert ast == Program( Instructions([ If( Condition('<', Variable('a'), Variable('b')), If( Condition('<', Variable('c'), Variable('d')), Break(), If(Condition('<', Variable('e'), Variable('f')), Continue(), Return()))) ])) if1 = ast.instructions.instructions[0] if2 = if1.instruction_then if3 = if2.instruction_else assert if1.instruction_else is None assert if2.instruction_else is not None assert if3.instruction_else is not None
def test_expression_group_nested(): text = "foo = (12 + ((34 - 56) * 78)) / 90;" ast = parser.parse(text) assert ast == Program( Instructions([ Assignment( '=', Variable('foo'), BinExpr( '/', BinExpr( '+', IntNum(12), BinExpr( '*', BinExpr( '-', IntNum(34), IntNum(56), ), IntNum(78) ) ), IntNum(90) ) ) ]) )
def test_instruction_block_nested(): text = """ { { break; { { } } } continue; } { } """ ast = parser.parse(text) assert ast == Program( Instructions([ Instructions([ Instructions([ Break(), Instructions([Instructions([])]), ]), Continue() ]), Instructions([]) ]))
def test_nested_while(): text = """ while (i > 0) while (j > 0) break; """ ast = parser.parse(text) assert ast == Program( Instructions([ While( Condition( '>', Variable('i'), IntNum(0) ), While( Condition( '>', Variable('j'), IntNum(0) ), Break() ) ) ]) )
def test_if_else(): text = "if (a < b) break; else continue;" ast = parser.parse(text) assert ast == Program( Instructions([ If(Condition('<', Variable('a'), Variable('b')), Break(), Continue()) ]))
def test_multiple_instructions(): text = """ break; continue; return; """ ast = parser.parse(text) assert ast == Program(Instructions([Break(), Continue(), Return()]))
def test_precedence_transpose_over_unary_minus(): text = "foo = -A';" ast = parser.parse(text) assert ast == Program( Instructions([ Assignment('=', Variable('foo'), UnaryExpr('-', UnaryExpr("'", Variable('A')))) ]))
def test_matrix_function(function, node_type, argc): args = ', '.join(['42'] * argc) text = f"foo = {function}({args});" ast = parser.parse(text) assert ast == Program( Instructions([ Assignment('=', Variable('foo'), node_type(*[IntNum(42) for _ in range(argc)])) ]))
def test_precedence_mul_op_over_add_op(add_op, mul_op): text = f"foo = 123 {add_op} 456 {mul_op} 789;" ast = parser.parse(text) assert ast == Program( Instructions([ Assignment( '=', Variable('foo'), BinExpr(add_op, IntNum(123), BinExpr(mul_op, IntNum(456), IntNum(789)))) ]))
def test_left_associativity(op1, op2): text = f"foo = 123 {op1} 456 {op2} 789;" ast = parser.parse(text) assert ast == Program( Instructions([ Assignment( '=', Variable('foo'), BinExpr(op2, BinExpr(op1, IntNum(123), IntNum(456)), IntNum(789))) ]))
def test_precedence_expression_op_over_comparision_op(expr_op, comp_op): text = f"if (a {expr_op} b {comp_op} c {expr_op} d) break;" ast = parser.parse(text) assert ast == Program( Instructions([ If( Condition(comp_op, BinExpr(expr_op, Variable('a'), Variable('b')), BinExpr(expr_op, Variable('c'), Variable('d'))), Break()) ]))
def test_expression_group_nested_multiple(n): text = f"foo = {'(' * n}123{')' * n};" ast = parser.parse(text) assert ast == Program( Instructions([ Assignment( '=', Variable('foo'), IntNum(123) ) ]) )
def test_nested_if(): text = """ if (a < b) if (c < d) break; """ ast = parser.parse(text) assert ast == Program( Instructions([ If(Condition('<', Variable('a'), Variable('b')), If(Condition('<', Variable('c'), Variable('d')), Break())) ]))
def test_memory_value(text, expected_value): text = f'foo = {text};' ast = parser.parse(text, lexer=lexer) interpreter = Interpreter() ast.accept(interpreter) foo = interpreter.memory_stack.stack[0].symbols['foo'] if isinstance(expected_value, np.ndarray): assert np.array_equal(foo, expected_value) else: assert foo == expected_value assert type(foo) == type(expected_value)
def test_for(): text = """ for i = 1:10 print i; """ ast = parser.parse(text) assert ast == Program( Instructions([ For(Variable('i'), Range( IntNum(1), IntNum(10), ), Print([Variable('i')])) ]))
def test_binary_operator(op): text = f"foo = 123 {op} 456;" ast = parser.parse(text) assert ast == Program( Instructions([ Assignment( '=', Variable('foo'), BinExpr( op, IntNum(123), IntNum(456) ) ) ]) )
def test_for_range_expression(): text = """ for i = 2+3*5 : n*n print i; """ ast = parser.parse(text) assert ast == Program( Instructions([ For( Variable('i'), Range( BinExpr('+', IntNum(2), BinExpr('*', IntNum(3), IntNum(5))), BinExpr('*', Variable('n'), Variable('n'))), Print([Variable('i')])) ]))
def test_expression_group_unary(): text = "foo = (-A)';" ast = parser.parse(text) assert ast == Program( Instructions([ Assignment( '=', Variable('foo'), UnaryExpr( "'", UnaryExpr( '-', Variable('A') ) ) ) ]) )
def test_expression_group_binary(): text = "foo = (123 + 456) * 789;" ast = parser.parse(text) assert ast == Program( Instructions([ Assignment( '=', Variable('foo'), BinExpr( '*', BinExpr( '+', IntNum(123), IntNum(456) ), IntNum(789) ) ) ]) )
def test_matrix(): text = """ E1 = [ [ 1, 2, 3], [ 4, 5, 6], [ 7, 8, 9] ]; """ ast = parser.parse(text) assert ast == Program( Instructions([ Assignment( '=', Variable('E1'), Vector([ Vector([IntNum(1), IntNum(2), IntNum(3)]), Vector([IntNum(4), IntNum(5), IntNum(6)]), Vector([IntNum(7), IntNum(8), IntNum(9)]) ]) ) ]) )
def test_dangling_else_iiaea(): text = """ if (a < b) if (c < d) break; else continue; """ ast = parser.parse(text) assert ast == Program( Instructions([ If( Condition('<', Variable('a'), Variable('b')), If(Condition('<', Variable('c'), Variable('d')), Break(), Continue())) ])) outer_if = ast.instructions.instructions[0] inner_if = outer_if.instruction_then assert outer_if.instruction_else is None assert inner_if.instruction_else is not None
def test_condition_is_not_expression(): text = "foo = a < b;" parser.parse(text) assert not parser.errorok
except (RuntimeError, EOFError): break return text if __name__ == '__main__': if len(sys.argv) > 1: with open(sys.argv[1], 'r') as f: text = f.read() else: text = read() # lexer.input(text) # for token in lexer: # # column = find_column(text, token) # # print('(%d,%d): %s(%s)' % (token.lineno, column, token.type, token.value)) # print('(%d): %s(%s)' % (token.lineno, token.type, token.value)) ast = parser.parse(text, lexer=lexer) if not parser.errorok: raise SystemExit # ast.printTree() typeChecker = TypeChecker() typeChecker.visit(ast) if not typeChecker.errorok: raise SystemExit ast.accept(Interpreter())
def test_empty_program(): text = "" ast = parser.parse(text) assert ast == Program(Instructions([]))
def test_empty_instruction_block(): text = "{}" ast = parser.parse(text) assert ast == Program(Instructions([Instructions([])]))
def test_single_instruction(): text = "break;" ast = parser.parse(text) assert ast == Program(Instructions([Break()]))
def test_condition(comp_op): text = f"if (a {comp_op} b) break;" ast = parser.parse(text) assert ast == Program( Instructions( [If(Condition(comp_op, Variable('a'), Variable('b')), Break())]))
def typechecker_passes(text: str): ast = parser.parse(text) typechecker = TypeChecker() typechecker.visit(ast) return typechecker.errorok
def test_compare_stdout(text, expected_stdout, capsys): ast = parser.parse(text, lexer=lexer) ast.accept(Interpreter()) captured = capsys.readouterr() assert captured.out == expected_stdout
def test_condition_nonassoc(): text = "if (a < b < c) break;" parser.parse(text) assert not parser.errorok