Example #1
0
 def __parse_assignment_operator(self) -> Ast:
     """
     <assignment-operator>     ::= '='
     """
     ast = Ast(AstType.ASSIGNMENT_OPERATOR)
     ast.add_child(self.__assert_token('=', TokenType.ASSIGN))
     return ast
Example #2
0
 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
Example #3
0
 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
Example #4
0
    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
Example #5
0
 def __parse_expression(self) -> Ast:
     """
     <expression> ::=
         <additive-expression>
     """
     ast = Ast(AstType.EXPRESSION)
     ast.add_child(self.__parse_additive_expression())
     return ast
Example #6
0
    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
Example #7
0
    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
Example #8
0
    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
Example #9
0
    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
Example #10
0
    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
Example #11
0
    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
Example #12
0
    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
Example #13
0
    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
Example #14
0
    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
Example #15
0
    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
Example #16
0
    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
Example #17
0
    def __parse_printable(self) -> Ast:
        """
        <printable> ::=
            <expression> | <string-literal>
        """
        ast = Ast(AstType.PRINTABLE)

        token = self.__peek_token(suppress_exception=True)
        if token is None:
            raise ExpectedSymbol(self.__prev_token().ed_pos,
                                 'string-literal or identifier')

        if token.tok_type == TokenType.STR_LITERAL:
            ast.add_child(self.__parse_str_literal())
        else:
            ast.add_child(self.__parse_expression())
        return ast
Example #18
0
    def __parse_print_statement(self) -> Ast:
        """
        <print-statement> ::=
            'print' '(' [<printable-list>] ')' ';'
        """
        ast = Ast(AstType.PRINT_STATEMENT)

        ast.add_child(self.__assert_token('print', TokenType.PRINT))
        ast.add_child(self.__assert_token('(', TokenType.LEFT_PARENTHESES))

        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_printable_list())

        ast.add_child(self.__assert_token(')', TokenType.RIGHT_PARENTHESES))
        ast.add_child(self.__assert_token(';', TokenType.SEMICOLON))

        return ast
Example #19
0
    def __parse_statement_seq(self) -> Ast:
        """
        <statement-seq> ::=
            {<statement>}
        """
        ast = Ast(AstType.STATEMENT_SEQ)

        while True:
            token = self.__peek_token(suppress_exception=True)
            if token is None:
                raise ExpectedSymbol(self.__prev_token().ed_pos, '}')
            elif token.tok_type in [
                    TokenType.LEFT_BRACE, TokenType.IF, TokenType.SWITCH,
                    TokenType.WHILE, TokenType.DO, TokenType.FOR,
                    TokenType.BREAK, TokenType.CONTINUE, TokenType.RETURN,
                    TokenType.PRINT, TokenType.SCAN, TokenType.IDENTIFIER,
                    TokenType.SEMICOLON
            ]:
                ast.add_child(self.__parse_statement())
            else:
                break
        return ast
Example #20
0
 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
Example #21
0
    def __parse_function_definition(self) -> Ast:
        """
        <function-definition> ::=
            <type-specifier><identifier><parameter-clause><compound-statement>
        """
        ast = Ast(AstType.FUNCTION_DEFINITION)
        start_pos = self.__current_pos()

        try:
            ast.add_child(self.__parse_type_specifier())
            ast.add_child(self.__parse_identifier())
            ast.add_child(self.__parse_parameter_clause())
            ast.add_child(self.__parse_compound_statement())
        except TokenIndexOutOfRange as e:
            print(e, file=sys.stderr)
            raise InvalidFunctionDefinition(start_pos)

        return ast
Example #22
0
    def __parse_function_call(self) -> Ast:
        """
        <function-call> ::=
            <identifier> '(' [<expression-list>] ')'
        """
        ast = Ast(AstType.FUNCTION_CALL)

        ast.add_child(self.__parse_identifier())
        ast.add_child(self.__assert_token('(', TokenType.LEFT_PARENTHESES))

        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_expression_list())

        ast.add_child(self.__assert_token(')', TokenType.RIGHT_PARENTHESES))
        return ast
Example #23
0
    def __parse_compound_statement(self) -> Ast:
        """
        <compound-statement> ::=
            '{' {<variable-declaration>} <statement-seq> '}'
        """
        ast = Ast(AstType.COMPOUND_STATEMENT)

        ast.add_child(self.__assert_token('{', TokenType.LEFT_BRACE))
        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.types + [TokenType.CONST]:
                break
            ast.add_child(self.__parse_variable_declaration())

        ast.add_child(self.__parse_statement_seq())
        ast.add_child(self.__assert_token('}', TokenType.RIGHT_BRACE))
        return ast
Example #24
0
    def __parse_jump_statement(self) -> Ast:
        """
        <jump-statement> ::=
            'break' ';'
            |'continue' ';'
            |<return-statement>
        """
        ast = Ast(AstType.JUMP_STATEMENT)

        token = self.__peek_token()
        if token.tok_type == TokenType.BREAK:
            ast.add_child(self.__assert_token('break', TokenType.BREAK))
            ast.add_child(self.__assert_token(';', TokenType.SEMICOLON))
        elif token.tok_type == TokenType.CONTINUE:
            ast.add_child(self.__assert_token('continue', TokenType.CONTINUE))
            ast.add_child(self.__assert_token(';', TokenType.SEMICOLON))
        else:
            ast.add_child(self.__parse_return_statement())

        return ast
Example #25
0
    def __parse_variable_declaration(self) -> Ast:
        """
        <variable-declaration> ::=
            [<const-qualifier>]<type-specifier><init-declarator-list>';'
        """
        ast = Ast(AstType.VARIABLE_DECLARATION)
        start_pos = self.__current_pos()

        try:
            token = self.__peek_token()
            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_init_declarator_list())
            ast.add_child(self.__assert_token(';', TokenType.SEMICOLON))
        except TokenIndexOutOfRange as e:
            print(e, file=sys.stderr)
            raise InvalidVariableDeclaration(start_pos)

        return ast
Example #26
0
    def __parse_for_init_statement(self) -> Ast:
        """
        <for-init-statement> ::=
            [<assignment-expression>{','<assignment-expression>}]';'
        """
        ast = Ast(AstType.FOR_INIT_STATEMENT)

        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_assignment_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_assignment_expression())

        ast.add_child(self.__assert_token(';', TokenType.SEMICOLON))
        return ast
Example #27
0
    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
Example #28
0
    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
Example #29
0
    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
Example #30
0
    def __parse_c0(self) -> Ast:
        """
        Analyse C0 program, generate the AST
        <C0-program> ::= {<variable-declaration>}{<function-definition>}
        """

        ast = Ast(AstType.C0)

        # {<variable-declaration>}
        while self.__peek_token(suppress_exception=True) is not None:
            token = self.__peek_token()

            if token.tok_type == TokenType.CONST:
                ast.add_child(self.__parse_variable_declaration())
            elif token.tok_type in TokenType.types:
                a, b, c = [
                    self.__next_token(suppress_exception=True)
                    for _ in range(3)
                ]
                if c is None:
                    raise InvalidVariableDeclaration(token.st_pos)

                for _ in range(3):
                    self.__unread_token()

                if c.tok_type == TokenType.LEFT_PARENTHESES:
                    ast.add_child(self.__parse_function_definition())
                    break
                else:
                    ast.add_child(self.__parse_variable_declaration())
            else:
                raise ExpectedTypeSpecifier(token.st_pos)

        # {<function-definition>}
        while self.__peek_token(suppress_exception=True) is not None:
            ast.add_child(self.__parse_function_definition())

        return ast