def test_relational_op_order(self): '''Relational ops have lowest precedence: `3 * 5 + 3 == 18;`''' given = iter([ Token('INTEGER', '3'), Token('MUL', '*'), Token('INTEGER', '5'), Token('PLUS', '+'), Token('INTEGER', '3'), Token('EQUAL_EQUAL', '=='), Token('INTEGER', '18'), Token('SEMI', ';') ]) result = parser.parse(given) expected = ast.Block([ ast.Statement( ast.BinOp( '==', ast.BinOp( '+', ast.BinOp('*', ast.Integer(3), ast.Integer(5)), ast.Integer(3) ), ast.Integer(18) ) ) ]) assert result == expected
def test_mixed_expression(self): '''An expression can have both numbers and ids: `x * (y + 10);`''' given = iter([ Token('ID', 'x'), Token('MUL', '*'), Token('LPAREN', '('), Token('ID', 'y'), Token('PLUS', '+'), Token('INTEGER', '10'), Token('RPAREN', ')'), Token('SEMI', ';') ]) result = parser.parse(given) expected = ast.Block([ ast.Statement( ast.BinOp( '*', ast.ID('x'), ast.BinOp('+', ast.ID('y'), ast.Integer(10)) ) ) ]) assert result == expected
def test_parens(self): '''Honors parenthesis: `(1 + 5) * 20;`''' given = iter([ Token('LPAREN', '('), Token('INTEGER', '1'), Token('PLUS', '+'), Token('INTEGER', '5'), Token('RPAREN', ')'), Token('MUL', '*'), Token('INTEGER', '20'), Token('SEMI', ';') ]) result = parser.parse(given) expected = ast.Block([ ast.Statement( ast.BinOp( '*', ast.BinOp('+', ast.Integer(1), ast.Integer(5)), ast.Integer(20) ) ) ]) assert result == expected
def test_unary_op_expression(self): '''Unary operations are supported: `(5 + -1) - !3;`''' given = iter([ Token('LPAREN', '('), Token('INTEGER', '5'), Token('PLUS', '+'), Token('MINUS', '-'), Token('INTEGER', '1'), Token('RPAREN', ')'), Token('MINUS', '-'), Token('BANG', '!'), Token('INTEGER', '3'), Token('SEMI', ';') ]) result = parser.parse(given) expected = ast.Block([ ast.Statement( ast.BinOp( '-', ast.BinOp( '+', ast.Integer(5), ast.UnaryOp('-', ast.Integer(1)) ), ast.UnaryOp('!', ast.Integer(3)) ) ) ]) assert result == expected
def test_simple_id(self): '''IDs are treated as expressions: `x;`''' given = iter([ Token('ID', 'x'), Token('SEMI', ';') ]) result = parser.parse(given) expected = ast.Block([ ast.Statement( ast.ID('x') ) ]) assert result == expected
def test_add(self): '''Can parse a simple addition: `1 + 1;`''' given = iter([ Token('INTEGER', '1'), Token('PLUS', '+'), Token('INTEGER', '1'), Token('SEMI', ';') ]) expected = ast.Block([ ast.Statement(ast.BinOp('+', ast.Integer(1), ast.Integer(1))) ]) result = parser.parse(given) assert expected == result
def test_arrayref_expression(self): '''Array reference is an expression: `arr[1];`''' given = iter([ Token('ID', 'arr'), Token('LBRACE', '['), Token('INTEGER', '1'), Token('RBRACE', ']'), Token('SEMI', ';') ]) result = parser.parse(given) expected = ast.Block([ ast.Statement( ast.ArrayRef(ast.ID('arr'), ast.Integer(1)) ) ]) assert result == expected
def test_float_expression(self): '''Expression with floats and integers: `1.0 + 2;`''' given = iter([ Token('FLOAT', '1.0'), Token('PLUS', '+'), Token('INTEGER', '2'), Token('SEMI', ';') ]) result = parser.parse(given) expected = ast.Block([ ast.Statement( ast.BinOp( '+', ast.Float(1.0), ast.Integer(2) ) ) ]) assert result == expected
def test_op_order(self): '''Enforces the right op. precedence: `1 + 5 * 20;`''' given = iter([ Token('INTEGER', '1'), Token('PLUS', '+'), Token('INTEGER', '5'), Token('MUL', '*'), Token('INTEGER', '20'), Token('SEMI', ';') ]) expected = ast.Block([ ast.Statement( ast.BinOp( '+', ast.Integer(1), ast.BinOp('*', ast.Integer(5), ast.Integer(20)) ) ) ]) result = parser.parse(given) assert expected == result
def statement_expr(s): return ast.Statement(s[0])