コード例 #1
0
    def test_expr_assignment_with_ids(self):
        '''Can parse assignment to expression with ids:
           `duck = (goose + 10) * duck;`'''
        given = iter([
            Token('ID', 'duck'),
            Token('EQUAL', '='),
            Token('LPAREN', '('),
            Token('ID', 'goose'),
            Token('PLUS', '+'),
            Token('INTEGER', '10'),
            Token('RPAREN', ')'),
            Token('MUL', '*'),
            Token('ID', 'duck'),
            Token('SEMI', ';')
        ])

        result = parser.parse(given)

        expected = ast.Block([
            ast.Assignment(
                ast.ID('duck'),
                ast.BinOp(
                    '*',
                    ast.BinOp('+', ast.ID('goose'), ast.Integer(10)),
                    ast.ID('duck')
                )
            )
        ])

        assert result == expected
コード例 #2
0
    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
コード例 #3
0
    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
コード例 #4
0
    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
コード例 #5
0
    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
コード例 #6
0
ファイル: typechecker_test.py プロジェクト: vkolmakov/minic
    def test_id_expr_error(self):
        '''No error with given program:
           `int ducks;
            float wildcats;
            ducks = 100;
            wildcats = 200 % ducks;`'''

        given = ast.Block([
            ast.Declaration('int', [ast.ID('ducks')]),
            ast.Declaration('float', [ast.ID('wildcats')]),
            ast.Assignment(ast.ID('ducks'), ast.Integer(100)),
            ast.Assignment(ast.ID('wildcats'),
                           ast.BinOp('%', ast.Integer(200), ast.ID('ducks')))
        ])

        report = typechecker.typecheck(given)
        expected_errors = [
            TypecheckerError(
                ast.Assignment(
                    ast.ID('wildcats'),
                    ast.BinOp('%', ast.Integer(200), ast.ID('ducks'))))
        ]

        for (r, e) in zip_longest(report.get_errors(), expected_errors):
            assert r == e
コード例 #7
0
ファイル: typechecker_test.py プロジェクト: vkolmakov/minic
    def test_simple_program_correct(self):
        '''Can typecheck a simple program:
           `int wildcat, animals[2];
            float duck;

            wildcat = 1;
            duck = 1.0;

            if(duck) {
              animals[0] = wildcat;
              animals[1] = 2;
            } else {
              animals[0] = 1;
            }

            duck = (duck + 2.5) * 33.0 / 2.0;
            `
        '''

        given = ast.Block([
            ast.Declaration('int', [
                ast.ID('wildcat'),
                ast.ArrayRef(ast.ID('animals'), ast.Integer(2))
            ]),
            ast.Declaration('float', [ast.ID('duck')]),
            ast.Assignment(ast.ID('wildcat'), ast.Integer(1)),
            ast.Assignment(ast.ID('duck'), ast.Float(1.0)),
            ast.IfStatement(
                ast.ID('duck'),
                ast.Block([
                    ast.Assignment(
                        ast.ArrayRef(ast.ID('animals'), ast.Integer(0)),
                        ast.ID('wildcat')),
                    ast.Assignment(
                        ast.ArrayRef(ast.ID('animals'), ast.Integer(1)),
                        ast.Integer(2))
                ]),
                ast.Block([
                    ast.Assignment(
                        ast.ArrayRef(ast.ID('animals'), ast.Integer(0)),
                        ast.Integer(1))
                ])),
            ast.Assignment(
                ast.ID('duck'),
                ast.BinOp(
                    '/',
                    ast.BinOp('*',
                              ast.BinOp('+', ast.ID('duck'), ast.Float(2.5)),
                              ast.Float(33.0)), ast.Float(2.0)))
        ])

        report = typechecker.typecheck(given)
        expected_errors = []

        for (r, e) in zip_longest(report.get_errors(), expected_errors):
            assert r == e
コード例 #8
0
    def test_multiline_assignment(self):
        '''Can parse multiple assignments:
           `x = 5;
            y = 10 * z;
            sum_times_five = (x + y) * 5;`'''
        given = iter([
            Token('ID', 'x'),
            Token('EQUAL', '='),
            Token('INTEGER', '5'),
            Token('SEMI', ';'),
            Token('ID', 'y'),
            Token('EQUAL', '='),
            Token('INTEGER', '10'),
            Token('MUL', '*'),
            Token('ID', 'z'),
            Token('SEMI', ';'),
            Token('ID', 'sum_times_five'),
            Token('EQUAL', '='),
            Token('LPAREN', '('),
            Token('ID', 'x'),
            Token('PLUS', '+'),
            Token('ID', 'y'),
            Token('RPAREN', ')'),
            Token('MUL', '*'),
            Token('INTEGER', '5'),
            Token('SEMI', ';'),
        ])

        result = parser.parse(given)

        expected = ast.Block([
            ast.Assignment(
                ast.ID('x'),
                ast.Integer(5)
            ),
            ast.Assignment(
                ast.ID('y'),
                ast.BinOp('*', ast.Integer(10), ast.ID('z'))
            ),
            ast.Assignment(
                ast.ID('sum_times_five'),
                ast.BinOp(
                    '*',
                    ast.BinOp('+', ast.ID('x'), ast.ID('y')),
                    ast.Integer(5)
                )
            )
        ])

        assert result == expected
コード例 #9
0
ファイル: typechecker_test.py プロジェクト: vkolmakov/minic
    def test_binop_error(self):
        '''An error with given program:
           `int more_cowbell;
            more_cowbell = 2000.0 + 1;`'''

        given = ast.Block([
            ast.Declaration('int', [ast.ID('more_cowbell')]),
            ast.Assignment(ast.ID('more_cowbell'),
                           ast.BinOp('+', ast.Float(2000.0), ast.Integer(1)))
        ])

        report = typechecker.typecheck(given)
        expected_errors = [
            TypecheckerError(
                ast.Assignment(
                    ast.ID('more_cowbell'),
                    ast.BinOp('+', ast.Float(2000.0), ast.Integer(1))))
        ]

        for (r, e) in zip_longest(report.get_errors(), expected_errors):
            assert r == e
コード例 #10
0
    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
コード例 #11
0
    def test_if_else_statement(self):
        '''Can parse an if-else statement
           `if (x + 3) {
              duck = x;
            } else {
              goose = x;
            }`
        '''
        given = iter([
            Token('IF', 'if'),
            Token('LPAREN', '('),
            Token('ID', 'x'),
            Token('PLUS', '+'),
            Token('INTEGER', '3'),
            Token('RPAREN', ')'),

            Token('LCURLY', '{'),
            Token('ID', 'duck'),
            Token('EQUAL', '='),
            Token('ID', 'x'),
            Token('SEMI', ';'),
            Token('RCURLY', '}'),

            Token('ELSE', 'else'),

            Token('LCURLY', '{'),
            Token('ID', 'goose'),
            Token('EQUAL', '='),
            Token('ID', 'x'),
            Token('SEMI', ';'),
            Token('RCURLY', '}'),
        ])

        expected = ast.Block([
            ast.IfStatement(
                ast.BinOp('+', ast.ID('x'), ast.Integer(3)),
                ast.Block([
                    ast.Assignment(ast.ID('duck'), ast.ID('x'))
                ]),
                ast.Block([
                    ast.Assignment(ast.ID('goose'), ast.ID('x'))
                ])
            )
        ])

        result = parser.parse(given)

        assert expected == result
コード例 #12
0
    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
コード例 #13
0
    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
コード例 #14
0
    def test_simple_program(self):
        '''Can parse a simple program
           `int x[3], duck, goose, wildcat;

            duck = 1;
            goose = 2;

            x[0] = duck;
            x[duck] = goose;

            if (duck + x[duck]) {
              wildcat = duck;
            } else {
              wildcat = goose;
            }
            x[2] = wildcat;`
        '''
        given = iter([
            Token('INT_TYPE', 'int'),
            Token('ID', 'x'), Token('LBRACE', '['), Token('INTEGER', '3'), Token('RBRACE', ']'), Token('COMMA', ','),
            Token('ID', 'duck'), Token('COMMA', ','),
            Token('ID', 'goose'), Token('COMMA', ','),
            Token('ID', 'wildcat'), Token('SEMI', ';'),

            Token('ID', 'duck'), Token('EQUAL', '='), Token('INTEGER', '1'), Token('SEMI', ';'),
            Token('ID', 'goose'), Token('EQUAL', '='), Token('INTEGER', '2'), Token('SEMI', ';'),
            Token('ID', 'x'), Token('LBRACE', '['), Token('INTEGER', '0'), Token('RBRACE', ']'), Token('EQUAL', '='), Token('ID', 'duck'), Token('SEMI', ';'),
            Token('ID', 'x'), Token('LBRACE', '['), Token('ID', 'duck'), Token('RBRACE', ']'), Token('EQUAL', '='), Token('ID', 'goose'), Token('SEMI', ';'),
            Token('IF', 'if'), Token('LPAREN', '('), Token('ID', 'duck'), Token('PLUS', '+'), Token('ID', 'x'), Token('LBRACE', '['), Token('ID', 'duck'), Token('RBRACE', ']'), Token('RPAREN', ')'),
            Token('LCURLY', '{'), Token('ID', 'wildcat'), Token('EQUAL', '='), Token('ID', 'duck'), Token('SEMI', ';'), Token('RCURLY', '}'),
            Token('ELSE', 'else'), Token('LCURLY', '{'), Token('ID', 'wildcat'), Token('EQUAL', '='), Token('ID', 'goose'), Token('SEMI', ';'), Token('RCURLY', '}'),
            Token('ID', 'x'), Token('LBRACE', '['), Token('INTEGER', '2'), Token('RBRACE', ']'), Token('EQUAL', '='), Token('ID', 'wildcat'), Token('SEMI', ';')
        ])

        expected = ast.Block([
            ast.Declaration(
                'int',
                [ast.ArrayRef(ast.ID('x'), ast.Integer(3)), ast.ID('duck'), ast.ID('goose'), ast.ID('wildcat')]
            ),
            ast.Assignment(ast.ID('duck'), ast.Integer(1)),
            ast.Assignment(ast.ID('goose'), ast.Integer(2)),

            ast.Assignment(ast.ArrayRef(ast.ID('x'), ast.Integer(0)), ast.ID('duck')),
            ast.Assignment(ast.ArrayRef(ast.ID('x'), ast.ID('duck')), ast.ID('goose')),

            ast.IfStatement(
                ast.BinOp('+', ast.ID('duck'), ast.ArrayRef(ast.ID('x'), ast.ID('duck'))),
                ast.Block([
                    ast.Assignment(ast.ID('wildcat'), ast.ID('duck'))
                ]),
                ast.Block([
                    ast.Assignment(ast.ID('wildcat'), ast.ID('goose'))
                ])
            ),

            ast.Assignment(ast.ArrayRef(ast.ID('x'), ast.Integer(2)), ast.ID('wildcat')),
        ])

        result = parser.parse(given)

        assert expected == result
コード例 #15
0
ファイル: productions.py プロジェクト: vkolmakov/minic
 def expr_binop(s):
     return ast.BinOp(s[1].getstr(), s[0], s[2])