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
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
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
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
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
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
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
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
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
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
def __parse_assignment_operator(self) -> Ast: """ <assignment-operator> ::= '=' """ ast = Ast(AstType.ASSIGNMENT_OPERATOR) ast.add_child(self.__assert_token('=', TokenType.ASSIGN)) return ast
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
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)
def __parse_expression(self) -> Ast: """ <expression> ::= <additive-expression> """ ast = Ast(AstType.EXPRESSION) ast.add_child(self.__parse_additive_expression()) return ast
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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