def parse_bracket_expression(self): token = self.pop_token() # remove left bracket node = ASTNode(n_type=ASTNodeType.ARRAY_LIST_EXP, n_line=token.get_line()) while True: while self.get_token_type() == TokenType.EO_STMT: token = self.pop_token() # EO_STMT if str(token) == "," and node.children and node.children[ -1].get_text() == ',': raise InvalidExpressionError3(token.row, token.col) node.add_child( ASTNode(n_type=ASTNodeType.EO_STMT, n_text=token.get_text(), n_line=token.get_line())) if self.get_token_type() is None: self.pop_token() raise IncompleteStatementError(self.last_token.row, self.last_token.col) node.add_child(self.parse_logic_or_expression()) token = self.get_token() if token.get_type() == TokenType.R_BRACKET: break self.pop_token() # remove right bracket return node
def parse_identifier_list(self): node = ASTNode(n_type=ASTNodeType.IDENT_LIST_EXP) while self.get_token_type() == TokenType.IDENTIFIER: token = self.pop_token() node.add_child( ASTNode(n_type=ASTNodeType.IDENTIFIER_EXP, n_text=token.get_text(), n_line=token.get_text())) return node
def parse_identifier_expression(self): token = self.pop_token() root = ASTNode(n_type=ASTNodeType.IDENTIFIER_EXP, n_text=token.get_text(), n_line=token.get_line()) if self.get_token_type() == TokenType.L_PAREN: self.pop_token() # remove left paren node = self.parse_index_list() self.pop_token() # remove right paren root.add_child(node) return root
def parse_statement_list(self, terminators=('None', )): """ when parse program, terminators use it default value, only if no token left will the parsing stop when parse code blocks like selection, iteration, function, terminators will be some specified keywords """ node = ASTNode(n_type=ASTNodeType.STMT_LIST) while str(self.get_token()) not in terminators: if self.get_token() is None: # indicates a invalid code block error, but raise outside the block return None if self.get_token_type() == TokenType.EO_STMT: self.pop_token() continue node.add_child(self.parse_statement()) return node
def parse_iteration_statement(self): if self.get_token().get_text() not in ('while', 'for'): return None node = ASTNode(n_type=ASTNodeType.ITR_STMT, n_text=self.get_token().get_text(), n_line=self.get_token().get_line()) start_token = self.pop_token() clause = self.parse_iteration_clause(start_token.get_text()) if clause is None: raise EndMissingError(start_token.row, start_token.col) node.add_child(clause) self.pop_token() # remove 'end' return self.complete_statement(node)
def parse_level_7_expression(self): """ binary/trinary colon operator (left associate): : """ root = self.parse_level_6_expression() while self.get_token_type() == TokenType.COLON: token = self.pop_token() # ':' node1 = self.parse_level_6_expression() root = ASTNode(n_type=ASTNodeType.CLN_EXP, n_text=token.get_text(), n_line=token.get_line(), children=[root, node1]) if self.get_token_type() == TokenType.COLON: self.pop_token() # the second ':' node2 = self.parse_level_6_expression() root.add_child(node2) return root
def parse_iteration_clause(self, clause): node = ASTNode(n_type=ASTNodeType.ITR_CLS, n_text=clause) expression = self.parse_logic_or_expression( ) if clause == 'while' else self.parse_assignment_expression() if expression is None: # exception raised outside return None node.add_child(expression) statement_list = self.parse_statement_list(terminators=('end', )) if statement_list is None: # exception raised outside return None node.add_child(statement_list) return node
def parse_selection_clause(self, clause): node = ASTNode(n_type=ASTNodeType.SEL_ClS, n_text=clause) if clause not in ('else', 'otherwise'): expression = self.parse_logic_or_expression() node.add_child(expression) if clause != 'switch': statement_list = self.parse_statement_list( terminators=SEL_TERMINATOR_MAP[clause]) if statement_list is None: # exception raised outside return None node.add_child(statement_list) else: # remove redundant EO_STMT tokens after switch before the first case while self.get_token_type() == TokenType.EO_STMT: self.pop_token() return node
def parse_selection_statement(self): if self.get_token().get_text() not in ("if", 'switch'): return None node = ASTNode(n_type=ASTNodeType.SEL_STMT, n_text=self.get_token().get_text(), n_line=self.get_token().get_line()) start_token = self.pop_token() # firstly a if/switch clause = self.parse_selection_clause(start_token.get_text()) if clause is None: raise EndMissingError(start_token.row, start_token.col) node.add_child(clause) a, b = SEL_CLAUSES_MAP[start_token.get_text()] # then unlimited elseif/case while self.get_token().get_text() == a: clause = self.parse_selection_clause(self.pop_token().get_text()) if clause is None: raise EndMissingError(start_token.row, start_token.col) node.add_child(clause) # finally sometimes a else/otherwise if self.get_token().get_text() == b: clause = self.parse_selection_clause(self.pop_token().get_text()) if clause is None: raise EndMissingError(start_token.row, start_token.col) node.add_child(clause) self.pop_token() # remove 'end' return self.complete_statement(node)
def parse_index_list(self): root = ASTNode(n_type=ASTNodeType.INDEX_LIST_EXP) while True: if self.get_token_type() == TokenType.COLON: token = self.pop_token() # COLON root.add_child( ASTNode(n_type=ASTNodeType.CLN_EXP, n_text=token.get_text(), n_line=token.get_line())) else: child = self.parse_logic_or_expression() root.add_child(child) token = self.get_token() if str(token) == ",": # one argument finished, continue to parse another argument self.pop_token() continue elif token.get_type() == TokenType.R_PAREN: break else: raise InvalidExpressionError3(token.row, token.col) return root