コード例 #1
0
ファイル: parser.py プロジェクト: tuxinhang1989/tinypie
    def _atom(self):
        """Atom rule.

        atom -> ID | INT | STRING | call | '(' expr ')'
        """
        if (self._lookahead_type(0) == tokens.ID
                and self._lookahead_type(1) == tokens.LPAREN):
            return self._call()

        elif self._lookahead_type(0) == tokens.ID:
            node = AST(self._lookahead_token(0))
            self._match(tokens.ID)
            return node

        elif self._lookahead_type(0) == tokens.INT:
            node = AST(self._lookahead_token(0))
            self._match(tokens.INT)
            return node

        elif self._lookahead_type(0) == tokens.STRING:
            # strip single quote around the string
            token = self._lookahead_token(0)
            token.text = token.text.strip("'")
            node = AST(token)
            self._match(tokens.STRING)
            return node

        elif self._lookahead_type(0) == tokens.LPAREN:
            self._match(tokens.LPAREN)
            node = self._expr()
            self._match(tokens.RPAREN)
            return node
コード例 #2
0
ファイル: parser.py プロジェクト: fengzishiren/tinypie
    def _slist(self):
        """Statement list rule.

        slist -> ':' NL statement+ '.' NL
                 | statement
        """
        node = AST(tokens.BLOCK)

        if self._lookahead_type(0) == tokens.COLON:
            self._match(tokens.COLON)
            self._match(tokens.NL)

            while not (self._lookahead_type(0) == tokens.DOT and
                       self._lookahead_type(1) == tokens.NL):
                st_node = self._statement()
                if st_node is not None:
                    node.add_child(st_node)

            self._match(tokens.DOT)
            self._match(tokens.NL)

        else:
            st_node = self._statement()
            if st_node is not None:
                node.add_child(st_node)

        return node
コード例 #3
0
ファイル: parser.py プロジェクト: fengzishiren/tinypie
    def _mult_expr(self):
        """Multiply expression rule.

        mult_expr -> atom ('*' atom)*
        """
        result_node = self._atom()

        while self._lookahead_type(0) == tokens.MUL:
            node = AST(self._lookahead_token(0))
            node.add_child(result_node)
            self._match(tokens.MUL)
            node.add_child(self._atom())
            result_node = node

        return result_node
コード例 #4
0
ファイル: parser.py プロジェクト: fengzishiren/tinypie
    def _expr(self):
        """Expression rule.

        expr -> add_expr (('<' | '==') add_expr)?
        """
        left_node = self._add_expr()

        if self._lookahead_type(0) in (tokens.LT, tokens.EQ):
            node = AST(self._lookahead_token(0))
            node.add_child(left_node)
            self._match(self._lookahead_type(0))
            node.add_child(self._add_expr())
            left_node = node

        return left_node
コード例 #5
0
ファイル: parser.py プロジェクト: fengzishiren/tinypie
    def _add_expr(self):
        """Add expression rule.

        add_expr -> mult_expr (('+' | '-') mult_expr)*
        """
        left_node = self._mult_expr()

        while self._lookahead_type(0) in (tokens.ADD, tokens.SUB):
            node = AST(self._lookahead_token(0))
            node.add_child(left_node)
            self._match(self._lookahead_type(0))
            node.add_child(self._mult_expr())
            left_node = node

        return left_node
コード例 #6
0
ファイル: parser.py プロジェクト: fengzishiren/tinypie
    def parse(self):
        node = AST(tokens.BLOCK)

        while self._lookahead_type(0) != tokens.EOF:

            token_type = self._lookahead_type(0)

            if token_type == tokens.DEF:
                node.add_child(self._function_definition())
            else:
                st_node = self._statement()
                if st_node is not None:
                    node.add_child(st_node)

        self.root = node
コード例 #7
0
ファイル: parser.py プロジェクト: fengzishiren/tinypie
    def _function_definition(self):
        """Function definition rule.

        function_definition -> 'def' ID '(' (ID (',' ID)*)? ')' slist
        """
        self._match(tokens.DEF)

        node = AST(tokens.FUNC_DEF)
        id_token = self._lookahead_token(0)
        node.add_child(AST(id_token))

        func_symbol = FunctionSymbol(id_token.text, self.current_scope)
        func_symbol.scope = self.current_scope
        self.current_scope.define(func_symbol)
        self.current_scope = func_symbol

        self._match(tokens.ID)
        self._match(tokens.LPAREN)

        if self._lookahead_type(0) == tokens.ID:
            node.add_child(AST(self._lookahead_token(0)))

            variable_symbol = VariableSymbol(self._lookahead_token(0).text)
            variable_symbol.scope = self.current_scope
            self.current_scope.define(variable_symbol)

            self._match(tokens.ID)

            while self._lookahead_type(0) == tokens.COMMA:
                self._match(tokens.COMMA)
                node.add_child(AST(self._lookahead_token(0)))

                variable_symbol = VariableSymbol(self._lookahead_token(0).text)
                self.current_scope.define(variable_symbol)
                variable_symbol.scope = self.current_scope

                self._match(tokens.ID)

        self._match(tokens.RPAREN)

        self.current_scope = LocalScope(self.current_scope)

        block_ast = self._slist()
        func_symbol.block_ast = block_ast
        node.add_child(block_ast)

        # pop LocalScope
        self.current_scope = self.current_scope.get_enclosing_scope()

        # pop FunctionSymbol
        self.current_scope = self.current_scope.get_enclosing_scope()

        return node
コード例 #8
0
ファイル: parser.py プロジェクト: fengzishiren/tinypie
    def _assign(self):
        """Assign rule.

        assign -> ID '=' expr
        """
        node = AST(tokens.ASSIGN)
        node.add_child(AST(self._lookahead_token(0)))

        variable_symbol = VariableSymbol(self._lookahead_token(0).text)
        variable_symbol.scope = self.current_scope
        self.current_scope.define(variable_symbol)

        self._match(tokens.ID)
        self._match(tokens.ASSIGN)
        node.add_child(self._expr())

        return node
コード例 #9
0
ファイル: parser.py プロジェクト: tuxinhang1989/tinypie
 def __init__(self, lexer, lookahead_limit=2, interpreter=None):
     self.lexer = lexer
     self.lookahead = [None] * lookahead_limit
     self.lookahead_limit = lookahead_limit
     self.pos = 0
     self._init_lookahead()
     self.root = AST(tokens.BLOCK)
     self.current_node = self.root
     self.interpreter = interpreter
     self.current_scope = interpreter.global_scope
コード例 #10
0
    def test_return(self):
        from tinypie.ast import AST
        from tinypie.lexer import Token
        from tinypie import tokens

        text = """
        return x
        """
        parser = self._get_parser(text)
        parser.parse()

        tree = AST(tokens.BLOCK)
        return_node = AST(Token(tokens.RETURN, 'return'))
        return_node.add_child(AST(Token(tokens.ID, 'x')))
        tree.add_child(return_node)

        self._compare_tree(tree, parser.root)
コード例 #11
0
    def test_print(self):
        from tinypie.ast import AST
        from tinypie.lexer import Token
        from tinypie import tokens

        text = """
        print x
        """
        parser = self._get_parser(text)
        parser.parse()

        tree = AST(tokens.BLOCK)
        print_node = AST(Token(tokens.PRINT, 'print'))
        print_node.add_child(AST(Token(tokens.ID, 'x')))
        tree.add_child(print_node)

        self._compare_tree(tree, parser.root)
コード例 #12
0
ファイル: parser.py プロジェクト: tuxinhang1989/tinypie
    def _call(self):
        """Call rule.

        call -> ID '(' (expr (',' expr)*)? ')'
        """
        node = AST(tokens.CALL)
        node.scope = self.current_scope
        node.add_child(AST(self._lookahead_token(0)))

        self._match(tokens.ID)
        self._match(tokens.LPAREN)
        result_node = self._expr()
        if result_node is not None:
            node.add_child(result_node)

        while self._lookahead_type(0) == tokens.COMMA:
            self._match(tokens.COMMA)
            node.add_child(self._expr())
        self._match(tokens.RPAREN)

        return node
コード例 #13
0
ファイル: parser.py プロジェクト: tuxinhang1989/tinypie
    def _slist(self):
        """Statement list rule.

        slist -> ':' NL statement+ '.' NL
                 | statement
        """
        node = AST(tokens.BLOCK)

        if self._lookahead_type(0) == tokens.COLON:
            self._match(tokens.COLON)
            self._match(tokens.NL)

            while not (self._lookahead_type(0) == tokens.DOT
                       and self._lookahead_type(1) == tokens.NL):
                st_node = self._statement()
                if st_node is not None:
                    node.add_child(st_node)

            self._match(tokens.DOT)
            self._match(tokens.NL)

        else:
            st_node = self._statement()
            if st_node is not None:
                node.add_child(st_node)

        return node
コード例 #14
0
ファイル: test_parser.py プロジェクト: fengzishiren/tinypie
    def test_call(self):
        from tinypie.ast import AST
        from tinypie.lexer import Token
        from tinypie import tokens

        text = """
        foo(5)
        """
        parser = self._get_parser(text)
        parser.parse()

        tree = AST(tokens.BLOCK)
        call_node = AST(Token(tokens.CALL))
        call_node.add_child(AST(Token(tokens.ID, 'foo')))
        call_node.add_child(AST(Token(tokens.INT, '5')))
        tree.add_child(call_node)

        self._compare_tree(tree, parser.root)
コード例 #15
0
ファイル: parser.py プロジェクト: tuxinhang1989/tinypie
    def _assign(self):
        """Assign rule.

        assign -> ID '=' expr
        """
        node = AST(tokens.ASSIGN)
        node.add_child(AST(self._lookahead_token(0)))

        variable_symbol = VariableSymbol(self._lookahead_token(0).text)
        variable_symbol.scope = self.current_scope
        self.current_scope.define(variable_symbol)

        self._match(tokens.ID)
        self._match(tokens.ASSIGN)
        node.add_child(self._expr())

        return node
コード例 #16
0
ファイル: parser.py プロジェクト: fengzishiren/tinypie
    def _call(self):
        """Call rule.

        call -> ID '(' (expr (',' expr)*)? ')'
        """
        node = AST(tokens.CALL)
        node.scope = self.current_scope
        node.add_child(AST(self._lookahead_token(0)))

        self._match(tokens.ID)
        self._match(tokens.LPAREN)
        result_node = self._expr()
        if result_node is not None:
            node.add_child(result_node)

        while self._lookahead_type(0) == tokens.COMMA:
            self._match(tokens.COMMA)
            node.add_child(self._expr())
        self._match(tokens.RPAREN)

        return node
コード例 #17
0
ファイル: parser.py プロジェクト: tuxinhang1989/tinypie
    def _expr(self):
        """Expression rule.

        expr -> add_expr (('<' | '==') add_expr)?
        """
        left_node = self._add_expr()

        if self._lookahead_type(0) in (tokens.LT, tokens.EQ):
            node = AST(self._lookahead_token(0))
            node.add_child(left_node)
            self._match(self._lookahead_type(0))
            node.add_child(self._add_expr())
            left_node = node

        return left_node
コード例 #18
0
ファイル: parser.py プロジェクト: tuxinhang1989/tinypie
    def _mult_expr(self):
        """Multiply expression rule.

        mult_expr -> atom ('*' atom)*
        """
        result_node = self._atom()

        while self._lookahead_type(0) == tokens.MUL:
            node = AST(self._lookahead_token(0))
            node.add_child(result_node)
            self._match(tokens.MUL)
            node.add_child(self._atom())
            result_node = node

        return result_node
コード例 #19
0
ファイル: parser.py プロジェクト: tuxinhang1989/tinypie
    def _add_expr(self):
        """Add expression rule.

        add_expr -> mult_expr (('+' | '-') mult_expr)*
        """
        left_node = self._mult_expr()

        while self._lookahead_type(0) in (tokens.ADD, tokens.SUB):
            node = AST(self._lookahead_token(0))
            node.add_child(left_node)
            self._match(self._lookahead_type(0))
            node.add_child(self._mult_expr())
            left_node = node

        return left_node
コード例 #20
0
ファイル: parser.py プロジェクト: tuxinhang1989/tinypie
    def parse(self):
        node = AST(tokens.BLOCK)

        while self._lookahead_type(0) != tokens.EOF:

            token_type = self._lookahead_type(0)

            if token_type == tokens.DEF:
                node.add_child(self._function_definition())
            else:
                st_node = self._statement()
                if st_node is not None:
                    node.add_child(st_node)

        self.root = node
コード例 #21
0
ファイル: test_parser.py プロジェクト: fengzishiren/tinypie
    def test_print(self):
        from tinypie.ast import AST
        from tinypie.lexer import Token
        from tinypie import tokens

        text = """
        print x
        """
        parser = self._get_parser(text)
        parser.parse()

        tree = AST(tokens.BLOCK)
        print_node = AST(Token(tokens.PRINT, 'print'))
        print_node.add_child(AST(Token(tokens.ID, 'x')))
        tree.add_child(print_node)

        self._compare_tree(tree, parser.root)
コード例 #22
0
ファイル: test_parser.py プロジェクト: fengzishiren/tinypie
    def test_return(self):
        from tinypie.ast import AST
        from tinypie.lexer import Token
        from tinypie import tokens

        text = """
        return x
        """
        parser = self._get_parser(text)
        parser.parse()

        tree = AST(tokens.BLOCK)
        return_node = AST(Token(tokens.RETURN, 'return'))
        return_node.add_child(AST(Token(tokens.ID, 'x')))
        tree.add_child(return_node)

        self._compare_tree(tree, parser.root)
コード例 #23
0
    def test_function_definition(self):
        from tinypie.ast import AST
        from tinypie.lexer import Token
        from tinypie import tokens

        text = """
        def foo(x) print x
        """
        parser = self._get_parser(text)
        parser.parse()

        tree = AST(tokens.BLOCK)

        func_node = AST(tokens.FUNC_DEF)
        func_node.add_child(AST(Token(tokens.ID, 'foo')))
        func_node.add_child(AST(Token(tokens.ID, 'x')))

        block_node = AST(tokens.BLOCK)
        print_node = AST(Token(tokens.PRINT, 'print'))
        print_node.add_child(AST(Token(tokens.ID, 'x')))
        block_node.add_child(print_node)
        func_node.add_child(block_node)

        tree.add_child(func_node)

        self._compare_tree(tree, parser.root)
コード例 #24
0
    def test_call(self):
        from tinypie.ast import AST
        from tinypie.lexer import Token
        from tinypie import tokens

        text = """
        foo(5)
        """
        parser = self._get_parser(text)
        parser.parse()

        tree = AST(tokens.BLOCK)
        call_node = AST(Token(tokens.CALL))
        call_node.add_child(AST(Token(tokens.ID, 'foo')))
        call_node.add_child(AST(Token(tokens.INT, '5')))
        tree.add_child(call_node)

        self._compare_tree(tree, parser.root)
コード例 #25
0
    def test_while(self):
        from tinypie.ast import AST
        from tinypie.lexer import Token
        from tinypie import tokens

        text = """
        while x < 10:
            print x
        .
        """
        parser = self._get_parser(text)
        parser.parse()

        tree = AST(tokens.BLOCK)
        while_node = AST(Token(tokens.WHILE, 'while'))

        lt_node = AST(Token(tokens.LT, '<'))
        lt_node.add_child(AST(Token(tokens.ID, 'x')))
        lt_node.add_child(AST(Token(tokens.INT, '10')))
        while_node.add_child(lt_node)

        block_node = AST(tokens.BLOCK)
        print_node = AST(Token(tokens.PRINT, 'print'))
        print_node.add_child(AST(Token(tokens.ID, 'x')))
        block_node.add_child(print_node)
        while_node.add_child(block_node)

        tree.add_child(while_node)

        self._compare_tree(tree, parser.root)
コード例 #26
0
    def test_ifstat(self):
        from tinypie.ast import AST
        from tinypie.lexer import Token
        from tinypie import tokens

        text = """
        if x < 10 print x
        else print 'less'
        """
        parser = self._get_parser(text)
        parser.parse()

        tree = AST(tokens.BLOCK)
        ifstat_node = AST(Token(tokens.IF, 'if'))

        lt_node = AST(Token(tokens.LT, '<'))
        lt_node.add_child(AST(Token(tokens.ID, 'x')))
        lt_node.add_child(AST(Token(tokens.INT, '10')))
        ifstat_node.add_child(lt_node)

        block_node = AST(tokens.BLOCK)
        print_node = AST(Token(tokens.PRINT, 'print'))
        print_node.add_child(AST(Token(tokens.ID, 'x')))
        block_node.add_child(print_node)
        ifstat_node.add_child(block_node)

        block_node = AST(tokens.BLOCK)
        print_node = AST(Token(tokens.PRINT, 'print'))
        print_node.add_child(AST(Token(tokens.STRING, 'less')))
        block_node.add_child(print_node)
        ifstat_node.add_child(block_node)

        tree.add_child(ifstat_node)

        self._compare_tree(tree, parser.root)
コード例 #27
0
ファイル: parser.py プロジェクト: tuxinhang1989/tinypie
    def _function_definition(self):
        """Function definition rule.

        function_definition -> 'def' ID '(' (ID (',' ID)*)? ')' slist
        """
        self._match(tokens.DEF)

        node = AST(tokens.FUNC_DEF)
        id_token = self._lookahead_token(0)
        node.add_child(AST(id_token))

        func_symbol = FunctionSymbol(id_token.text, self.current_scope)
        func_symbol.scope = self.current_scope
        self.current_scope.define(func_symbol)
        self.current_scope = func_symbol

        self._match(tokens.ID)
        self._match(tokens.LPAREN)

        if self._lookahead_type(0) == tokens.ID:
            node.add_child(AST(self._lookahead_token(0)))

            variable_symbol = VariableSymbol(self._lookahead_token(0).text)
            variable_symbol.scope = self.current_scope
            self.current_scope.define(variable_symbol)

            self._match(tokens.ID)

            while self._lookahead_type(0) == tokens.COMMA:
                self._match(tokens.COMMA)
                node.add_child(AST(self._lookahead_token(0)))

                variable_symbol = VariableSymbol(self._lookahead_token(0).text)
                self.current_scope.define(variable_symbol)
                variable_symbol.scope = self.current_scope

                self._match(tokens.ID)

        self._match(tokens.RPAREN)

        self.current_scope = LocalScope(self.current_scope)

        block_ast = self._slist()
        func_symbol.block_ast = block_ast
        node.add_child(block_ast)

        # pop LocalScope
        self.current_scope = self.current_scope.get_enclosing_scope()

        # pop FunctionSymbol
        self.current_scope = self.current_scope.get_enclosing_scope()

        return node
コード例 #28
0
ファイル: parser.py プロジェクト: tuxinhang1989/tinypie
    def _statement(self):
        """Statement rule.

        statement -> 'print' expr NL
                     | 'return' expr NL
                     | call NL
                     | assign NL
                     | 'if' expr slist ('else' slist)?
                     | 'while' expr slist
                     | NL
        """
        if self._lookahead_type(0) == tokens.PRINT:
            node = AST(self._lookahead_token(0))
            self._match(tokens.PRINT)
            node.add_child(self._expr())
            self._match(tokens.NL)
            return node

        elif self._lookahead_type(0) == tokens.RETURN:
            node = AST(self._lookahead_token(0))
            self._match(tokens.RETURN)
            node.add_child(self._expr())
            self._match(tokens.NL)
            return node

        elif self._lookahead_type(0) == tokens.NL:
            self._match(tokens.NL)

        elif (self._lookahead_type(0) == tokens.ID
              and self._lookahead_type(1) == tokens.LPAREN):
            return self._call()

        elif self._lookahead_type(0) == tokens.IF:
            node = AST(self._lookahead_token(0))
            self._match(tokens.IF)
            node.add_child(self._expr())
            node.add_child(self._slist())
            if self._lookahead_type(0) == tokens.ELSE:
                self._match(tokens.ELSE)
                node.add_child(self._slist())
            return node

        elif self._lookahead_type(0) == tokens.WHILE:
            node = AST(self._lookahead_token(0))
            self._match(tokens.WHILE)
            node.add_child(self._expr())
            node.add_child(self._slist())
            return node

        else:
            return self._assign()
コード例 #29
0
ファイル: parser.py プロジェクト: fengzishiren/tinypie
    def _statement(self):
        """Statement rule.

        statement -> 'print' expr NL
                     | 'return' expr NL
                     | call NL
                     | assign NL
                     | 'if' expr slist ('else' slist)?
                     | 'while' expr slist
                     | NL
        """
        if self._lookahead_type(0) == tokens.PRINT:
            node = AST(self._lookahead_token(0))
            self._match(tokens.PRINT)
            node.add_child(self._expr())
            self._match(tokens.NL)
            return node

        elif self._lookahead_type(0) == tokens.RETURN:
            node = AST(self._lookahead_token(0))
            self._match(tokens.RETURN)
            node.add_child(self._expr())
            self._match(tokens.NL)
            return node

        elif self._lookahead_type(0) == tokens.NL:
            self._match(tokens.NL)

        elif (self._lookahead_type(0) == tokens.ID and
              self._lookahead_type(1) == tokens.LPAREN
              ):
            return self._call()

        elif self._lookahead_type(0) == tokens.IF:
            node = AST(self._lookahead_token(0))
            self._match(tokens.IF)
            node.add_child(self._expr())
            node.add_child(self._slist())
            if self._lookahead_type(0) == tokens.ELSE:
                self._match(tokens.ELSE)
                node.add_child(self._slist())
            return node

        elif self._lookahead_type(0) == tokens.WHILE:
            node = AST(self._lookahead_token(0))
            self._match(tokens.WHILE)
            node.add_child(self._expr())
            node.add_child(self._slist())
            return node

        else:
            return self._assign()
コード例 #30
0
ファイル: test_parser.py プロジェクト: fengzishiren/tinypie
    def test_function_definition(self):
        from tinypie.ast import AST
        from tinypie.lexer import Token
        from tinypie import tokens

        text = """
        def foo(x) print x
        """
        parser = self._get_parser(text)
        parser.parse()

        tree = AST(tokens.BLOCK)

        func_node = AST(tokens.FUNC_DEF)
        func_node.add_child(AST(Token(tokens.ID, 'foo')))
        func_node.add_child(AST(Token(tokens.ID, 'x')))

        block_node = AST(tokens.BLOCK)
        print_node = AST(Token(tokens.PRINT, 'print'))
        print_node.add_child(AST(Token(tokens.ID, 'x')))
        block_node.add_child(print_node)
        func_node.add_child(block_node)

        tree.add_child(func_node)

        self._compare_tree(tree, parser.root)
コード例 #31
0
ファイル: test_parser.py プロジェクト: fengzishiren/tinypie
    def test_ifstat(self):
        from tinypie.ast import AST
        from tinypie.lexer import Token
        from tinypie import tokens

        text = """
        if x < 10 print x
        else print 'less'
        """
        parser = self._get_parser(text)
        parser.parse()

        tree = AST(tokens.BLOCK)
        ifstat_node = AST(Token(tokens.IF, 'if'))

        lt_node = AST(Token(tokens.LT, '<'))
        lt_node.add_child(AST(Token(tokens.ID, 'x')))
        lt_node.add_child(AST(Token(tokens.INT, '10')))
        ifstat_node.add_child(lt_node)

        block_node = AST(tokens.BLOCK)
        print_node = AST(Token(tokens.PRINT, 'print'))
        print_node.add_child(AST(Token(tokens.ID, 'x')))
        block_node.add_child(print_node)
        ifstat_node.add_child(block_node)

        block_node = AST(tokens.BLOCK)
        print_node = AST(Token(tokens.PRINT, 'print'))
        print_node.add_child(AST(Token(tokens.STRING, 'less')))
        block_node.add_child(print_node)
        ifstat_node.add_child(block_node)

        tree.add_child(ifstat_node)

        self._compare_tree(tree, parser.root)
コード例 #32
0
ファイル: test_parser.py プロジェクト: fengzishiren/tinypie
    def test_while(self):
        from tinypie.ast import AST
        from tinypie.lexer import Token
        from tinypie import tokens

        text = """
        while x < 10:
            print x
        .
        """
        parser = self._get_parser(text)
        parser.parse()

        tree = AST(tokens.BLOCK)
        while_node = AST(Token(tokens.WHILE, 'while'))

        lt_node = AST(Token(tokens.LT, '<'))
        lt_node.add_child(AST(Token(tokens.ID, 'x')))
        lt_node.add_child(AST(Token(tokens.INT, '10')))
        while_node.add_child(lt_node)

        block_node = AST(tokens.BLOCK)
        print_node = AST(Token(tokens.PRINT, 'print'))
        print_node.add_child(AST(Token(tokens.ID, 'x')))
        block_node.add_child(print_node)
        while_node.add_child(block_node)

        tree.add_child(while_node)

        self._compare_tree(tree, parser.root)