コード例 #1
0
ファイル: parser.py プロジェクト: yiranyyu/C0-Compiler
    def __parse_integer_literal(self) -> Ast:
        ast = Ast(AstType.INTEGER_LITERAL)

        token = self.__next_token()
        if token.tok_type != TokenType.INTEGER_LITERAL:
            raise ExpectedInt32(token.st_pos)
        ast.add_child(Ast(AstType.TOKEN, token))
        return ast
コード例 #2
0
ファイル: parser.py プロジェクト: yiranyyu/C0-Compiler
    def __parse_str_literal(self) -> Ast:
        ast = Ast(AstType.STR_LITERAL)

        token = self.__next_token()
        if token.tok_type != TokenType.STR_LITERAL:
            raise ExpectedStrLiteral(token.st_pos)
        ast.add_child(Ast(AstType.TOKEN, token))
        return ast
コード例 #3
0
ファイル: parser.py プロジェクト: yiranyyu/C0-Compiler
    def __parse_additive_operator(self) -> Ast:
        """
        <additive-operator>       ::= '+' | '-'
        """
        ast = Ast(AstType.ADDITIVE_OPERATOR)

        token = self.__next_token()
        if token.tok_type not in [TokenType.ADD, TokenType.SUB]:
            raise ExpectedSymbol(token.st_pos, '+ or -')
        ast.add_child(Ast(AstType.TOKEN, token))
        return ast
コード例 #4
0
ファイル: parser.py プロジェクト: yiranyyu/C0-Compiler
    def __parse_multiplicative_operator(self) -> Ast:
        """
        <multiplicative-operator> ::= '*' | '/'
        """
        ast = Ast(AstType.MULTIPLICATIVE_OPERATOR)

        token = self.__next_token()
        if token.tok_type not in [TokenType.MUL, TokenType.DIV]:
            raise ExpectedSymbol(token.st_pos, '* or /')
        ast.add_child(Ast(AstType.TOKEN, token))
        return ast
コード例 #5
0
ファイル: parser.py プロジェクト: yiranyyu/C0-Compiler
    def __parse_identifier(self) -> Ast:
        ast = Ast(AstType.IDENTIFIER)

        token = self.__next_token(suppress_exception=True)
        if token is None:
            raise ExpectedIdentifier(self.__prev_token().st_pos)

        if token.tok_type != TokenType.IDENTIFIER:
            raise ExpectedIdentifier(token.st_pos)
        ast.add_child(Ast(AstType.TOKEN, token))
        return ast
コード例 #6
0
ファイル: parser.py プロジェクト: yiranyyu/C0-Compiler
    def __parse_relational_operator(self) -> Ast:
        """
        <relational-operator>     ::= '<' | '<=' | '>' | '>=' | '!=' | '=='
        """
        ast = Ast(AstType.RELATIONAL_OPERATOR)

        token = self.__next_token()
        if token.tok_type not in TokenType.relations:
            raise ExpectedSymbol(token.st_pos,
                                 "'<' | '<=' | '>' | '>=' | '!=' | '=='")
        ast.add_child(Ast(AstType.TOKEN, token))
        return ast
コード例 #7
0
ファイル: parser.py プロジェクト: yiranyyu/C0-Compiler
    def __parse_simple_type_specifier(self) -> Ast:
        """
        <simple-type-specifier>  ::= 'void'|'int'|'char'|'double'
        """
        ast = Ast(AstType.SIMPLE_TYPE_SPECIFIER)

        token = self.__next_token()
        if token.tok_type in TokenType.types:
            ast.add_child(Ast(AstType.TOKEN, token))
        else:
            raise UnknownVariableType(token.st_pos, token.literal)

        return ast
コード例 #8
0
ファイル: parser.py プロジェクト: yiranyyu/C0-Compiler
    def __parse_cast_expression(self) -> Ast:
        """
        <cast-expression> ::=
            {'('<type-specifier>')'}<unary-expression>
        """
        ast = Ast(AstType.CAST_EXPRESSION)

        while True:
            token = self.__peek_token(suppress_exception=True)
            if token is None:
                raise InvalidExpression(self.__prev_token().ed_pos)

            if token.tok_type != TokenType.LEFT_PARENTHESES:
                break
            ast.add_child(self.__assert_token('(', TokenType.LEFT_PARENTHESES))

            token = self.__peek_token(suppress_exception=True)
            if token is None:
                raise InvalidExpression(self.__prev_token().ed_pos)
            if token.tok_type not in TokenType.types:
                self.__unread_token()
                break
            ast.add_child(self.__parse_type_specifier())
            ast.add_child(self.__assert_token(')',
                                              TokenType.RIGHT_PARENTHESES))

        ast.add_child(self.__parse_unary_expression())
        return ast
コード例 #9
0
ファイル: parser.py プロジェクト: yiranyyu/C0-Compiler
 def __parse_const_qualifier(self) -> Ast:
     """
     <const-qualifier>        ::= 'const'
     """
     ast = Ast(AstType.CONST_QUALIFIER)
     ast.add_child(self.__assert_token('const', TokenType.CONST))
     return ast
コード例 #10
0
ファイル: parser.py プロジェクト: yiranyyu/C0-Compiler
    def __parse_labeled_statement(self) -> Ast:
        """
        <labeled-statement> ::=
            'case' (<integer-literal>|<char-literal>) ':' <statement>
            |'default' ':' <statement>
        """
        ast = Ast(AstType.LABELED_STATEMENT)

        token = self.__peek_token()
        if token.tok_type == TokenType.CASE:
            ast.add_child(self.__assert_token('case', TokenType.CASE))

            token = self.__peek_token(suppress_exception=True)
            if token is None:
                raise ExpectedSymbol(self.__prev_token().ed_pos,
                                     'char or integer literal')
            if token.tok_type not in [
                    TokenType.INTEGER_LITERAL, TokenType.CHAR_LITERAL
            ]:
                raise ExpectedSymbol(token.st_pos,
                                     'char-literal or integer-literal')
            if token.tok_type == TokenType.INTEGER_LITERAL:
                ast.add_child(self.__parse_integer_literal())
            else:
                ast.add_child(self.__parse_char_literal())

            ast.add_child(self.__assert_token(':', TokenType.COLON))
            ast.add_child(self.__parse_statement())
        elif token.tok_type == TokenType.DEFAULT:
            ast.add_child(self.__assert_token('default', TokenType.DEFAULT))
            ast.add_child(self.__assert_token(':', TokenType.COLON))
            ast.add_child(self.__parse_statement())
        else:
            raise ExpectedSymbol(token.st_pos, '`case` or `default`')
        return ast
コード例 #11
0
ファイル: parser.py プロジェクト: yiranyyu/C0-Compiler
 def __parse_assignment_operator(self) -> Ast:
     """
     <assignment-operator>     ::= '='
     """
     ast = Ast(AstType.ASSIGNMENT_OPERATOR)
     ast.add_child(self.__assert_token('=', TokenType.ASSIGN))
     return ast
コード例 #12
0
ファイル: parser.py プロジェクト: yiranyyu/C0-Compiler
 def __parse_type_specifier(self) -> Ast:
     """
     <type-specifier>         ::= <simple-type-specifier>
     """
     ast = Ast(AstType.TYPE_SPECIFIER)
     ast.add_child(self.__parse_simple_type_specifier())
     return ast
コード例 #13
0
ファイル: parser.py プロジェクト: yiranyyu/C0-Compiler
 def __assert_token(self, symbol: str, tok_type: TokenType) -> Ast:
     token = self.__next_token(suppress_exception=True)
     if token is None:
         raise ExpectedSymbol(self.__prev_token().ed_pos, symbol)
     if token.tok_type != tok_type:
         raise ExpectedSymbol(self.__prev_token().st_pos, symbol)
     return Ast(AstType.TOKEN, token)
コード例 #14
0
ファイル: parser.py プロジェクト: yiranyyu/C0-Compiler
 def __parse_expression(self) -> Ast:
     """
     <expression> ::=
         <additive-expression>
     """
     ast = Ast(AstType.EXPRESSION)
     ast.add_child(self.__parse_additive_expression())
     return ast
コード例 #15
0
ファイル: parser.py プロジェクト: yiranyyu/C0-Compiler
    def __parse_condition_statement(self) -> Ast:
        """
        <condition-statement> ::=
            'if' '(' <condition> ')' <statement> ['else' <statement>]
            |'switch' '(' <expression> ')' '{' {<labeled-statement>} '}'
        """
        ast = Ast(AstType.CONDITION_STATEMENT)

        token = self.__peek_token()
        if token.tok_type == TokenType.IF:
            try:
                # 'if' '(' <condition> ')' <statement>
                ast.add_child(self.__assert_token('if', TokenType.IF))
                ast.add_child(
                    self.__assert_token('(', TokenType.LEFT_PARENTHESES))
                ast.add_child(self.__parse_condition())
                ast.add_child(
                    self.__assert_token(')', TokenType.RIGHT_PARENTHESES))
                ast.add_child(self.__parse_statement())

                # ['else' <statement>]
                token = self.__peek_token(suppress_exception=True)
                if token is not None and (token.tok_type == TokenType.ELSE):
                    ast.add_child(self.__assert_token('else', TokenType.ELSE))
                    ast.add_child(self.__parse_statement())
            except TokenIndexOutOfRange as e:
                print(e, file=sys.stderr)
                raise InvalidIfStatement(self.__prev_token().ed_pos)
        elif token.tok_type == TokenType.SWITCH:
            # 'switch' '(' <expression> ')' '{' {<labeled-statement>} '}'
            try:
                ast.add_child(self.__assert_token('switch', TokenType.SWITCH))
                ast.add_child(
                    self.__assert_token('(', TokenType.LEFT_PARENTHESES))
                ast.add_child(self.__parse_expression())
                ast.add_child(
                    self.__assert_token(')', TokenType.RIGHT_PARENTHESES))
                ast.add_child(self.__assert_token('{', TokenType.LEFT_BRACE))

                # {<labeled-statement>}
                while True:
                    token = self.__peek_token(suppress_exception=True)
                    if token is None:
                        raise ExpectedSymbol(self.__prev_token().ed_pos, '}')
                    if token.tok_type not in [
                            TokenType.CASE, TokenType.DEFAULT
                    ]:
                        break
                    ast.add_child(self.__parse_labeled_statement())

                ast.add_child(self.__assert_token('}', TokenType.RIGHT_BRACE))

            except TokenIndexOutOfRange as e:
                print(e, file=sys.stderr)
                raise InvalidSwitchStatement(self.__prev_token().ed_pos)
        else:
            raise ExpectedSymbol(token.st_pos, 'if or switch')
        return ast
コード例 #16
0
ファイル: parser.py プロジェクト: yiranyyu/C0-Compiler
 def __parse_assignment_expression(self) -> Ast:
     """
     <assignment-expression> ::=
         <identifier><assignment-operator><expression>
     """
     ast = Ast(AstType.ASSIGNMENT_EXPRESSION)
     ast.add_child(self.__parse_identifier())
     ast.add_child(self.__parse_assignment_operator())
     ast.add_child(self.__parse_expression())
     return ast
コード例 #17
0
ファイル: parser.py プロジェクト: yiranyyu/C0-Compiler
    def __parse_initializer(self) -> Ast:
        """
        <initializer> ::=
            '='<expression>
        """
        ast = Ast(AstType.INITIALIZER)

        ast.add_child(self.__assert_token('=', TokenType.ASSIGN))
        ast.add_child(self.__parse_expression())
        return ast
コード例 #18
0
ファイル: parser.py プロジェクト: yiranyyu/C0-Compiler
    def __parse_loop_statement(self) -> Ast:
        """
        <loop-statement> ::=
            'while' '(' <condition> ')' <statement>
            |'do' <statement> 'while' '(' <condition> ')' ';'
            |'for' '('<for-init-statement> [<condition>]';' [<for-update-expression>]')' <statement>
        """
        ast = Ast(AstType.LOOP_STATEMENT)

        token = self.__peek_token()
        if token.tok_type == TokenType.WHILE:
            # 'while' '(' <condition> ')' <statement>
            ast.add_child(self.__assert_token('while', TokenType.WHILE))
            ast.add_child(self.__assert_token('(', TokenType.LEFT_PARENTHESES))
            ast.add_child(self.__parse_condition())
            ast.add_child(self.__assert_token(')',
                                              TokenType.RIGHT_PARENTHESES))
            ast.add_child(self.__parse_statement())
        elif token.tok_type == TokenType.DO:
            # 'do' <statement> 'while' '(' <condition> ')' ';'
            ast.add_child(self.__assert_token('do', TokenType.DO))
            ast.add_child(self.__parse_statement())
            ast.add_child(self.__assert_token('while', TokenType.WHILE))
            ast.add_child(self.__assert_token('(', TokenType.LEFT_PARENTHESES))
            ast.add_child(self.__parse_condition())
            ast.add_child(self.__assert_token(')',
                                              TokenType.RIGHT_PARENTHESES))
            ast.add_child(self.__assert_token(';', TokenType.SEMICOLON))
        elif token.tok_type == TokenType.FOR:
            # 'for' '('<for-init-statement> [<condition>]';' [<for-update-expression>]')' <statement>
            ast.add_child(self.__assert_token('for', TokenType.FOR))
            ast.add_child(self.__assert_token('(', TokenType.LEFT_PARENTHESES))
            ast.add_child(self.__parse_for_init_statement())

            # [<condition>] ';'
            token = self.__peek_token(suppress_exception=True)
            if token is None:
                raise ExpectedSymbol(self.__prev_token().ed_pos, ';')
            if token.tok_type != TokenType.SEMICOLON:
                ast.add_child(self.__parse_condition())
            ast.add_child(self.__assert_token(';', TokenType.SEMICOLON))

            # [<for-update-expression>]')' <statement>
            token = self.__peek_token(suppress_exception=True)
            if token is None:
                raise ExpectedSymbol(self.__prev_token().ed_pos, ')')
            if token.tok_type != TokenType.RIGHT_PARENTHESES:
                ast.add_child(self.__parse_for_update_expression())
            ast.add_child(self.__assert_token(')',
                                              TokenType.RIGHT_PARENTHESES))
            ast.add_child(self.__parse_statement())

        return ast
コード例 #19
0
ファイル: parser.py プロジェクト: yiranyyu/C0-Compiler
    def __parse_statement(self) -> Ast:
        """
        <statement> ::=
            <compound-statement>
            |<condition-statement>
            |<loop-statement>
            |<jump-statement>
            |<print-statement>
            |<scan-statement>
            |<assignment-expression>';'
            |<function-call>';'
            |';'
        """
        ast = Ast(AstType.STATEMENT)

        token = self.__peek_token()
        if token.tok_type == TokenType.LEFT_BRACE:
            ast.add_child(self.__parse_compound_statement())
        elif token.tok_type in [TokenType.IF, TokenType.SWITCH]:
            ast.add_child(self.__parse_condition_statement())
        elif token.tok_type in [TokenType.WHILE, TokenType.DO, TokenType.FOR]:
            ast.add_child(self.__parse_loop_statement())
        elif token.tok_type in [
                TokenType.BREAK, TokenType.CONTINUE, TokenType.RETURN
        ]:
            ast.add_child(self.__parse_jump_statement())
        elif token.tok_type == TokenType.PRINT:
            ast.add_child(self.__parse_print_statement())
        elif token.tok_type == TokenType.SCAN:
            ast.add_child(self.__parse_scan_statement())
        elif token.tok_type == TokenType.SEMICOLON:
            ast.add_child(self.__assert_token(';', TokenType.SEMICOLON))
        elif token.tok_type == TokenType.IDENTIFIER:
            self.__next_token()
            token = self.__next_token(suppress_exception=True)
            if token is None:
                raise ExpectedSymbol(self.__prev_token().ed_pos, '( or =')
            if token.tok_type not in [
                    TokenType.ASSIGN, TokenType.LEFT_PARENTHESES
            ]:
                raise ExpectedSymbol(token.st_pos, '( or =')

            self.__unread_token()
            self.__unread_token()
            if token.tok_type == TokenType.ASSIGN:
                ast.add_child(self.__parse_assignment_expression())
                ast.add_child(self.__assert_token(';', TokenType.SEMICOLON))
            elif token.tok_type == TokenType.LEFT_PARENTHESES:
                ast.add_child(self.__parse_function_call())
                ast.add_child(self.__assert_token(';', TokenType.SEMICOLON))
        else:
            raise InvalidStatement(token.st_pos)
        return ast
コード例 #20
0
ファイル: parser.py プロジェクト: yiranyyu/C0-Compiler
    def __parse_init_declarator(self) -> Ast:
        """
        <init-declarator> ::=
            <identifier>[<initializer>]
        """
        ast = Ast(AstType.INIT_DECLARATOR)

        ast.add_child(self.__parse_identifier())

        token = self.__peek_token()
        if token.tok_type == TokenType.ASSIGN:
            ast.add_child(self.__parse_initializer())
        return ast
コード例 #21
0
ファイル: parser.py プロジェクト: yiranyyu/C0-Compiler
    def __parse_scan_statement(self) -> Ast:
        """
        <scan-statement> ::=
            'scan' '(' <identifier> ')' ';'
        """
        ast = Ast(AstType.SCAN_STATEMENT)

        ast.add_child(self.__assert_token('scan', TokenType.SCAN))
        ast.add_child(self.__assert_token('(', TokenType.LEFT_PARENTHESES))
        ast.add_child(self.__parse_identifier())
        ast.add_child(self.__assert_token(')', TokenType.RIGHT_PARENTHESES))
        ast.add_child(self.__assert_token(';', TokenType.SEMICOLON))

        return ast
コード例 #22
0
ファイル: parser.py プロジェクト: yiranyyu/C0-Compiler
    def __parse_parameter_declaration_list(self) -> Ast:
        """
        <parameter-declaration-list> ::=
            <parameter-declaration>{','<parameter-declaration>}
        """
        ast = Ast(AstType.PARAMETER_DECLARATION_LIST)

        ast.add_child(self.__parse_parameter_declaration())
        while True:
            token = self.__peek_token(suppress_exception=True)
            if token is None or token.tok_type != TokenType.COMMA:
                break
            ast.add_child(self.__assert_token(',', TokenType.COMMA))
            ast.add_child(self.__parse_parameter_declaration())
        return ast
コード例 #23
0
ファイル: parser.py プロジェクト: yiranyyu/C0-Compiler
    def __parse_expression_list(self) -> Ast:
        """
        <expression-list> ::=
            <expression>{','<expression>}
        """
        ast = Ast(AstType.EXPRESSION_LIST)

        ast.add_child(self.__parse_expression())
        while True:
            token = self.__peek_token(suppress_exception=True)
            if token is None or token.tok_type != TokenType.COMMA:
                break
            ast.add_child(self.__assert_token(',', TokenType.COMMA))
            ast.add_child(self.__parse_expression())
        return ast
コード例 #24
0
ファイル: parser.py プロジェクト: yiranyyu/C0-Compiler
    def __parse_printable_list(self) -> Ast:
        """
        <printable-list>  ::=
            <printable> {',' <printable>}
        """
        ast = Ast(AstType.PRINTABLE_LIST)

        ast.add_child(self.__parse_printable())
        while True:
            token = self.__peek_token(suppress_exception=True)
            if token is None or token.tok_type != TokenType.COMMA:
                break
            ast.add_child(self.__assert_token(',', TokenType.COMMA))
            ast.add_child(self.__parse_printable())
        return ast
コード例 #25
0
ファイル: parser.py プロジェクト: yiranyyu/C0-Compiler
    def __parse_unary_expression(self) -> Ast:
        """
        <unary-expression> ::=
            [<unary-operator>]<primary-expression>
        """
        ast = Ast(AstType.UNARY_EXPRESSION)

        token = self.__peek_token(suppress_exception=True)
        if token is None:
            raise InvalidExpression(self.__prev_token().ed_pos)

        if token.tok_type in [TokenType.ADD, TokenType.SUB]:
            ast.add_child(self.__parse_unary_operator())
        ast.add_child(self.__parse_primary_expression())
        return ast
コード例 #26
0
ファイル: parser.py プロジェクト: yiranyyu/C0-Compiler
    def __parse_init_declarator_list(self) -> Ast:
        """
        <init-declarator-list> ::=
            <init-declarator>{','<init-declarator>}
        """
        ast = Ast(AstType.INIT_DECLARATOR_LIST)

        ast.add_child(self.__parse_init_declarator())

        while True:
            token = self.__peek_token(suppress_exception=True)
            if token is None or token.tok_type != TokenType.COMMA:
                break
            ast.add_child(self.__assert_token(',', TokenType.COMMA))
            ast.add_child(self.__parse_init_declarator())
        return ast
コード例 #27
0
ファイル: parser.py プロジェクト: yiranyyu/C0-Compiler
    def __parse_parameter_declaration(self) -> Ast:
        """
        <parameter-declaration> ::=
            [<const-qualifier>]<type-specifier><identifier>
        """
        ast = Ast(AstType.PARAMETER_DECLARATION)

        token = self.__peek_token(suppress_exception=True)
        if token is None:
            raise ExpectedTypeSpecifier(self.__prev_token().ed_pos)
        if token.tok_type == TokenType.CONST:
            ast.add_child(self.__parse_const_qualifier())

        ast.add_child(self.__parse_type_specifier())
        ast.add_child(self.__parse_identifier())
        return ast
コード例 #28
0
ファイル: parser.py プロジェクト: yiranyyu/C0-Compiler
    def __parse_return_statement(self) -> Ast:
        """
        <return-statement> ::= 'return' [<expression>] ';'
        """
        ast = Ast(AstType.RETURN_STATEMENT)

        ast.add_child(self.__assert_token('return', TokenType.RETURN))

        token = self.__peek_token(suppress_exception=True)
        if token is None:
            raise ExpectedSymbol(self.__prev_token().ed_pos, ';')

        if token.tok_type != TokenType.SEMICOLON:
            ast.add_child(self.__parse_expression())
        ast.add_child(self.__assert_token(';', TokenType.SEMICOLON))
        return ast
コード例 #29
0
ファイル: parser.py プロジェクト: yiranyyu/C0-Compiler
    def __parse_for_update_expression(self) -> Ast:
        """
        <for-update-expression> ::=
            (<assignment-expression>|<function-call>){','(<assignment-expression>|<function-call>)}
        """
        ast = Ast(AstType.FOR_UPDATE_STATEMENT)

        ast.add_child(self.__parse_assignment_expression_or_function_call())
        while True:
            token = self.__peek_token(suppress_exception=True)
            if token is None or token.tok_type != TokenType.COMMA:
                break
            ast.add_child(self.__assert_token(',', TokenType.COMMA))
            ast.add_child(
                self.__parse_assignment_expression_or_function_call())
        return ast
コード例 #30
0
ファイル: parser.py プロジェクト: yiranyyu/C0-Compiler
    def __parse_condition(self) -> Ast:
        """
        <condition> ::=
             <expression>[<relational-operator><expression>]
        """
        ast = Ast(AstType.CONDITION)

        # <expression>
        ast.add_child(self.__parse_expression())

        # [<relational-operator><expression>]
        token = self.__peek_token(suppress_exception=True)
        if token is not None and token.tok_type in TokenType.relations:
            ast.add_child(self.__parse_relational_operator())
            ast.add_child(self.__parse_expression())
        return ast