class Parser(object): def __init__(self, tokens): self.index = len(tokens) self.tokens = iter(tokens) self.cur_token = self.tokens.next() #Default token holder self.next_token = self.tokens.next() #LL2 lookahead token holder for when needed self.cur_symbol_table = None self.root_table = SymbolTable(None) self.sem_analyzer = SemanticAnalyzer(self.root_table) self.program_name = '' self.cur_proc_name = '' self.cur_func_name = '' ############### Utility Functions ############### def error(self, expected=None): logging.error("Couldn't match: \"%s\" near line: %s, col: %s in %s(). Received %s" % (self.t_lexeme(), self.cur_token.line, self.cur_token.column, inspect.stack()[1][3],self.t_type())) logging.error('Expected tokens: %s' % expected) logging.error("Three level parse tree (stack) trace, most recent call last.\n\t^ %s()\n\t^ %s()\n\t> %s()" % (inspect.stack()[3][3], inspect.stack()[2][3], inspect.stack()[1][3])) exit() def t_type(self): """ So that we don't have to call the line below every time we need a current token type """ return self.cur_token.token_type def t_lexeme(self): """ Same as above - just a wrapper to make code more elegant """ return self.cur_token.token_value @classmethod def print_tree(cls, level): """ A method for printing where we are at in parse tree In case future assignments will require more complexity """ logging.debug(level) def match(self, lexeme): self.cur_token = self.next_token try: self.next_token = self.tokens.next() except StopIteration: pass logging.info("Matched '%s' in %s()" % (lexeme, inspect.stack()[1][3])) return False def print_symbol_table(self, type, table): level = log.getEffectiveLevel() log.setLevel(logging.DEBUG) logging.debug(type + " Symbol Table " + table.name + table.__repr__() + '\n') log.setLevel(level) ############### Rule handling functions ############### def system_goal(self): """ Expanding Rule 1: System Goal -> Program $ """ if self.t_type() == 'MP_PROGRAM': Parser.print_tree('1') self.program() if self.t_type() == 'MP_EOF': self.match('EOF') self.print_symbol_table("Program",self.root_table) self.sem_analyzer.write_IR() return "The input program parses!" exit() else: self.error('MP_PROGRAM') def program(self): """ Expanding Rule 2: Program -> ProgramHeading ";" Block "." """ if self.t_type() == 'MP_PROGRAM': Parser.print_tree('2') self.program_heading() self.match(';') self.root_table.create_root() self.root_table.name = self.program_name self.cur_symbol_table = self.root_table self.sem_analyzer.sym_table = self.cur_symbol_table self.sem_analyzer.gen_begin() self.block() self.sem_analyzer.gen_end() self.match('.') else: self.error('MP_PROGRAM') def program_heading(self): """ Expanding Rule 3: "program" Identifier """ if self.t_type() == 'MP_PROGRAM': Parser.print_tree('3') self.match('program') self.program_identifier() else: self.error('MP_PROGRAM') def block(self): """ Expanding Rule 4: Block -> VariableDeclarationPart ProcedureAndFunctionDeclarationPart StatementPart """ accepted_list = ['MP_VAR', 'MP_PROCEDURE', 'MP_BEGIN', 'MP_FUNCTION'] if self.t_type() in accepted_list: Parser.print_tree('4') self.variable_declaration_part() self.procedure_and_function_declaration_part() self.statement_part() else: self.error(accepted_list) def variable_declaration_part(self): """ Expanding Rules 5, 6: VariableDeclarationPart -> "var" VariableDeclaration ";" VariableDeclarationTail -> e """ eps_list = ['MP_BEGIN', 'MP_FUNCTION', 'MP_PROCEDURE'] if self.t_type() == 'MP_VAR': Parser.print_tree('5') self.match('var') self.variable_declaration() self.match(';') self.variable_declaration_tail() elif self.t_type() in eps_list: Parser.print_tree('6') self.epsilon() else: self.error(eps_list.append('MP_VAR')) self.sem_analyzer.gen_add_sp() def epsilon(self): """ Branch went to epsilon - pass """ pass def variable_declaration_tail(self): """ Expanding Rules 7, 8: VariableDeclarationTail -> VariableDeclaration ";" VariableDeclarationTail -> e """ eps_list = ['MP_BEGIN', 'MP_FUNCTION', 'MP_PROCEDURE'] if self.t_type() == 'MP_IDENTIFIER': Parser.print_tree('7') self.variable_declaration() self.match(';') self.variable_declaration_tail() elif self.t_type() in eps_list: Parser.print_tree('8') self.epsilon() else: self.error(eps_list.append('MP_IDENTIFIER')) def variable_declaration(self): """ Expanding Rule 9: VariableDeclaration -> IdentifierList ":" Type """ if self.t_type() == 'MP_IDENTIFIER': Parser.print_tree('9') var_list = self.identifier_list([]) self.match(':') type = self.type() #iterate through the list of vars for var in var_list: record = SemanticRecord() record.type = type record.lexeme = var record.set_size(type) record.kind = "var" record.depth = self.cur_symbol_table.cur_depth self.cur_symbol_table.insert(record) else: self.error('MP_IDENTIFIER') def type(self): """ Expanding Rules 10, 11: Type -> "Integer" -> "Float" """ lexeme = '' if self.t_type() == 'MP_FLOAT': Parser.print_tree('11') lexeme = self.t_lexeme() self.match(lexeme) elif self.t_type() == 'MP_INTEGER': Parser.print_tree('10') lexeme = self.t_lexeme() self.match(lexeme) else: self.error(['MP_FLOAT', 'MP_INTEGER']) return lexeme def procedure_and_function_declaration_part(self): """ Expanding Rules 12, 13, 14: ProcedureAndFunctionDeclarationPart -> ProcedureDeclaration ProcedureAndFunctionDeclarationPart -> FunctionDeclaration ProcedureAndFunctionDeclarationPart -> epsilon """ if self.t_type() == 'MP_PROCEDURE': Parser.print_tree('12') self.procedure_declaration() self.procedure_and_function_declaration_part() elif self.t_type() == 'MP_FUNCTION': Parser.print_tree('13') self.function_declaration() self.procedure_and_function_declaration_part() elif self.t_type() == 'MP_BEGIN': Parser.print_tree('14') self.epsilon() else: self.error(['MP_PROCEDURE', 'MP_FUNCTION', 'MP_BEGIN']) def procedure_declaration(self): """ Expanding Rule 15: ProcedureDeclaration -> ProcedureHeading ";" Block ";" """ if self.t_type() == 'MP_PROCEDURE': old_proc_name = self.cur_proc_name proc_sym_table = SymbolTable(self.cur_symbol_table) proc_sym_table.create() self.cur_symbol_table = proc_sym_table self.sem_analyzer.sym_table = self.cur_symbol_table Parser.print_tree('15') self.procedure_heading() proc_sym_table.name = self.cur_proc_name self.match(';') self.block() self.match(';') self.print_symbol_table("Procedure", proc_sym_table) self.cur_symbol_table = self.cur_symbol_table.parent_table self.cur_proc_name = old_proc_name proc_sym_table.destroy() else: self.error('MP_PROCEDURE') def function_declaration(self): """ Expanding Rule 16: FunctionDeclaration -> FunctionHeading ";" Block ";" """ if self.t_type() == 'MP_FUNCTION': old_func_name = self.cur_func_name func_sym_table = SymbolTable(self.cur_symbol_table) func_sym_table.create() self.cur_symbol_table = func_sym_table self.sem_analyzer.sym_table = self.cur_symbol_table Parser.print_tree('16') self.function_heading() func_sym_table.name = self.cur_func_name self.match(';') self.block() self.match(';') self.print_symbol_table("Function",func_sym_table) self.cur_func_name = old_func_name self.cur_symbol_table = self.cur_symbol_table.parent_table func_sym_table.destroy() else: self.error('MP_FUNCTION') def procedure_heading(self): """ Expanding Rule 17: ProcedureHeading -> "procedure" procedureIdentifier OptionalFormalParameterList """ if self.t_type() == 'MP_PROCEDURE': Parser.print_tree('17') self.match('procedure') self.procedure_identifier() self.optional_formal_parameter_list() else: self.error('MP_PROCEDURE') def function_heading(self): """ Expanding Rule 18: FunctionHeading -> "function" functionIdentifier OptionalFormalParameterList ":" Type """ if self.t_type() == 'MP_FUNCTION': Parser.print_tree('18') self.match('function') self.function_identifier() self.optional_formal_parameter_list() self.match(':') type = self.type() return type else: self.error('MP_FUNCTION') def optional_formal_parameter_list(self): """ Expanding Rules 19, 20: OptionalFormalParameterList -> "(" FormalParameterSection FormalParameterSectionTail ")" -> epsilon """ eps_list = ['MP_FLOAT', 'MP_INTEGER', 'MP_SCOLON'] if self.t_type() == 'MP_LPAREN': Parser.print_tree('19') self.match('(') self.formal_parameter_section() self.formal_parameter_section_tail() self.match(')') elif self.t_type() in eps_list: Parser.print_tree('20') self.epsilon() else: self.error(eps_list.append('MP_LPAREN')) def formal_parameter_section_tail(self): """ Expanding Rules 21, 22: FormalParameterSectionTail -> ";" FormalParameterSection FormalParameterSectionTail -> epsilon """ if self.t_type() == 'MP_SCOLON': Parser.print_tree('21') self.match(';') self.formal_parameter_section() self.formal_parameter_section_tail() elif self.t_type() == 'MP_RPAREN': Parser.print_tree('22') self.epsilon() else: self.error(['MP_SCOLON', 'MP_RPAREN']) def formal_parameter_section(self): """ Expanding Rules 23, 24: FormalParameterSection -> ValueParameterSection -> VariableParameterSection """ if self.t_type() == 'MP_IDENTIFIER': Parser.print_tree('23') self.value_parameter_section() elif self.t_type() == 'MP_VAR': Parser.print_tree('24') self.variable_parameter_section() else: self.error(['MP_IDENTIFIER', 'MP_VAR']) def value_parameter_section(self): """ Expanding Rule 25: ValueParameterSection -> IdentifierList ":" Type """ if self.t_type() == 'MP_IDENTIFIER': Parser.print_tree('25') val_param_list = self.identifier_list([]) self.match(':') type = self.type() for var in val_param_list: record = SemanticRecord() record.type = type record.lexeme = var record.set_size(type) record.kind = "var" record.depth = self.cur_symbol_table.cur_depth self.cur_symbol_table.insert(record) else: self.error('MP_IDENTIFIER') def variable_parameter_section(self): """ Expanding Rule 26: VariableParameterSection -> "var" IdentifierList ":" Type """ if self.t_type() == 'MP_VAR': Parser.print_tree('26') self.match(self.t_type()) var_param_list = self.identifier_list([]) self.match(':') type = self.type() #iterate through the list of vars for var in var_param_list: record = SemanticRecord() record.type = type record.lexeme = var record.set_size(type) record.kind = "var" record.depth = self.cur_symbol_table.cur_depth self.cur_symbol_table.insert(record) else: self.error('MP_VAR') def statement_part(self): """ Expanding Rule 27: StatementPart -> CompoundStatement """ if self.t_type() == 'MP_BEGIN': Parser.print_tree('27') self.compound_statement() else: self.error('MP_BEGIN') def compound_statement(self): """ Expanding Rule 28: CompoundStatement -> "begin" StatementSequence "end" """ if self.t_type() == 'MP_BEGIN': Parser.print_tree('28') self.match('begin') self.statement_sequence() self.match('end') else: self.error('MP_BEGIN') def statement_sequence(self): """ Expanding Rule 29: StatementSequence -> Statement StatementTail """ accepted_list = ['MP_BEGIN', 'MP_END', 'MP_READ', 'MP_WRITE', 'MP_IF', 'MP_WHILE', 'MP_REPEAT', 'MP_FOR', 'MP_IDENTIFIER'] if self.t_type() in accepted_list: Parser.print_tree('29') self.statement() self.statement_tail() else: self.error(accepted_list) def statement_tail(self): """ Expanding Rules 30, 31 : StatementTail -> ";" Statement StatementTail -> epsilon """ eps_list = [ 'MP_END', 'MP_UNTIL'] if self.t_type() == 'MP_SCOLON': Parser.print_tree('30') self.match(';') self.statement() self.statement_tail() elif self.t_type() in eps_list: Parser.print_tree('31') self.epsilon() else: self.error(eps_list.append('MP_SCOLON')) def statement(self): """ Expanding Rule 32 - 41 : Statement -> EmptyStatement -> CompoundStatement -> ReadStatement -> WriteStatement -> AssignmentStatement -> IfStatement -> WhileStatement -> RepeatStatement -> ForStatement -> ProcedureStatement """ if self.t_type() == 'MP_END': Parser.print_tree('32') self.empty_statement() elif self.t_type() == 'MP_BEGIN': Parser.print_tree('33') self.compound_statement() elif self.t_type() == 'MP_READ': Parser.print_tree('34') self.read_statement() elif self.t_type() == 'MP_WRITE': Parser.print_tree('35') self.write_statement() elif self.t_type() == 'MP_IDENTIFIER': Parser.print_tree('36') procedure_list = ['MP_END', 'MP_SCOLON', 'MP_LPAREN'] procedure_list_2 = ['MP_COLON', 'MP_ASSIGN'] if self.next_token.token_type in procedure_list: self.procedure_statement() elif self.next_token.token_type in procedure_list_2: self.assignment_statement() else: self.error(['MP_END', 'MP_SCOLON', 'MP_LPAREN', 'MP_COLON', 'MP_ASSIGN']) elif self.t_type() == 'MP_IF': Parser.print_tree('37') self.if_statement() elif self.t_type() == 'MP_WHILE': Parser.print_tree('38') self.while_statement() elif self.t_type() == 'MP_REPEAT': Parser.print_tree('39') self.repeat_statement() elif self.t_type() == 'MP_FOR': Parser.print_tree('40') self.for_statement() elif self.t_type() == 'MP_UNTIL': pass elif self.t_type() == 'MP_ELSE': pass else: self.error(['MP_END', 'MP_BEGIN', 'MP_WRITE', 'MP_IDENTIFIER', 'MP_IF', 'MP_WHILE', 'MP_REPEAT', 'MP_FOR']) def empty_statement(self): """ Expanding Rule 42: EmptyStatement -> epsilon """ accepted_list = ['MP_SCOLON', 'MP_ELSE', 'MP_END', 'MP_UNTIL'] if self.t_type() in accepted_list: Parser.print_tree('42') self.epsilon() else: self.error(accepted_list) def read_statement(self): """ Expanding Rule 43: ReadStatement -> "read" "(" ReadParameter ReadParameterTail ")" """ if self.t_type() == 'MP_READ': Parser.print_tree('43') self.match('read') self.match('(') self.read_parameter() self.read_parameter_tail() self.match(')') else: self.error('MP_READ') def read_parameter_tail(self): """ Expanding Rules 44, 45 : ReadParameterTail -> "," ReadParameter ReadParameterTail -> epsilon """ if self.t_type() == 'MP_COMMA': Parser.print_tree('44') self.match(',') self.read_parameter() self.read_parameter_tail() elif self.t_type() == 'MP_RPAREN': Parser.print_tree('45') self.epsilon() else: self.error(['MP_COMMA', 'MP_RPAREN']) def read_parameter(self): """ Expanding Rule 46 : ReadParameter -> VariableIdentifier """ read_param_rec = SemanticRecord() if self.t_type() == 'MP_IDENTIFIER': Parser.print_tree('46') self.variable_identifier(read_param_rec) self.sem_analyzer.gen_read(read_param_rec) else: self.error('MP_IDENTIFIER') def write_statement(self): #AAA """ Expanding Rule 47: WriteStatement -> "write" "(" WriteParameter WriteParameterTail ")" """ write_param_rec = SemanticRecord() if self.t_type() == 'MP_WRITE': Parser.print_tree('47') self.match('write') self.match('(') self.write_parameter() # this is an expression self.write_parameter_tail() # this too is an expression of some sort self.match(')') # todo: handle combining the two returns from param and param_tail, push on the stack else: self.error('MP_WRITE') def write_parameter_tail(self): """ Expanding Rules 48, 49 : WriteParameterTail -> "," WriteParameter WriteParameterTail -> epsilon """ if self.t_type() == 'MP_COMMA': Parser.print_tree('48') self.match(',') self.write_parameter() self.write_parameter_tail() elif self.t_type() == 'MP_RPAREN': Parser.print_tree('49') self.epsilon() else: self.error(['MP_COMMA', 'MP_PAREN']) def write_parameter(self): """ Expanding Rule 50 : WriteParameter -> OrdinalExpression """ write_param_rec = SemanticRecord() accepted_list = ['MP_LPAREN','MP_PLUS','MP_MINUS','MP_IDENTIFIER', 'MP_INTEGER','MP_NOT'] if self.t_type() in accepted_list: Parser.print_tree('50') self.ordinal_expression(write_param_rec) self.sem_analyzer.gen_write(write_param_rec) else: self.error(accepted_list) def assignment_statement(self): """ Expanding Rules 51, 52: AssignmentStatement -> VariableIdentifier ":=" Expression -> FunctionIdentifier ":=" Expression """ # the conflict here should be considered resolved, because in the end #both those guys lead to identifier ident_rec = SemanticRecord() express_rec = SemanticRecord() if self.t_type() == 'MP_IDENTIFIER': Parser.print_tree('51') self.variable_identifier(ident_rec) self.match(':=') self.expression(express_rec) self.sem_analyzer.gen_ass_statement(ident_rec, express_rec) else: self.error('MP_IDENTIFIER') def if_statement(self): """ Expanding Rule 53: IfStatement -> "if" BooleanExpression "then" Statement OptionalElsePart """ if_rec = SemanticRecord() if self.t_type() == 'MP_IF': Parser.print_tree('53') self.match('if') self.boolean_expression(if_rec) self.sem_analyzer.begin_if(if_rec) self.match('then') self.statement() self.optional_else_part(if_rec) self.sem_analyzer.end_if(if_rec) else: self.error('MP_IF') def optional_else_part(self, if_rec): """ Expanding Rule 54: OptionalElsePart -> "else" Statement """ eps_list = ['MP_SCOLON', 'MP_END', 'MP_UNTIL'] self.sem_analyzer.opt_else(if_rec) if self.t_type() == 'MP_ELSE': Parser.print_tree('54') self.match('else') self.statement() elif self.t_type() in eps_list: Parser.print_tree('55') self.epsilon() else: self.error(eps_list.extend('MP_ELSE')) def repeat_statement(self): """ Expanding Rule 56: RepeatStatement -> "repeat" StatementSequence "until" BooleanExpression """ rep_rec = SemanticRecord() if self.t_type() == 'MP_REPEAT': Parser.print_tree('56') self.match('repeat') self.sem_analyzer.begin_repeat(rep_rec) self.statement_sequence() self.match('until') self.boolean_expression(rep_rec) self.sem_analyzer.end_repeat(rep_rec) else: self.error('MP_REPEAT') def while_statement(self): """ Expanding Rule 57: WhileStatement -> "while" BooleanExpression "do" Statement """ while_rec = SemanticRecord() expr_rec = SemanticRecord() if self.t_type() == 'MP_WHILE': Parser.print_tree('57') self.match('while') self.sem_analyzer.begin_while(while_rec) self.boolean_expression(expr_rec) self.sem_analyzer.gen_while(while_rec, expr_rec) self.match('do') self.statement() self.sem_analyzer.end_while(while_rec) else: self.error('MP_WHILE') def for_statement(self): """ Expanding Rule 58: ForStatement -> "for" ControlVariable ":=" InitialValue StepValue FinalValue "do" Statement """ control_var_rec = SemanticRecord() initial_rec = SemanticRecord() final_rec = SemanticRecord() for_rec = SemanticRecord() if self.t_type() == 'MP_FOR': Parser.print_tree('58') self.match('for') self.control_variable(control_var_rec) self.match(':=') self.initial_value(initial_rec) self.step_value(for_rec) self.final_value(final_rec) self.match('do') self.sem_analyzer.begin_for(for_rec) self.sem_analyzer.gen_for(for_rec, control_var_rec, initial_rec) self.statement() self.sem_analyzer.end_for(for_rec, control_var_rec, final_rec) else: self.error('MP_FOR') def control_variable(self, control_var_rec): """ Expanding Rule 59: ControlVariable -> VariableIdentifier """ if self.t_type() == 'MP_IDENTIFIER': Parser.print_tree('59') self.variable_identifier(control_var_rec) else: self.error('MP_IDENTIFIER') def initial_value(self, initial_rec): """ Expanding Rule 60: InitialValue -> OrdinalExpression """ accepted_list = ['MP_LPAREN','MP_PLUS','MP_MINUS','MP_IDENTIFIER', 'MP_INTEGER','MP_NOT'] if self.t_type() in accepted_list: Parser.print_tree('60') self.ordinal_expression(initial_rec) else: self.error(accepted_list) def step_value(self, step_rec): """ Expanding Rules 61, 62 : StepValue -> "to" -> "downto" """ if self.t_type() == 'MP_TO': Parser.print_tree('61') self.match(self.t_lexeme()) step_rec.lexeme = 'lte' elif self.t_type() == 'MP_DOWNTO': Parser.print_tree('62') self.match(self.t_lexeme()) step_rec.lexeme = 'gte' else: self.error(['MP_TO', 'MP_DOWNTO']) def final_value(self, final_rec): """ Expanding Rule 63: FinalValue -> OrdinalExpression """ accepted_list = ['MP_LPAREN','MP_PLUS','MP_MINUS','MP_IDENTIFIER', 'MP_INTEGER','MP_NOT'] if self.t_type() in accepted_list: Parser.print_tree('63') self.ordinal_expression(final_rec) else: self.error(accepted_list) def procedure_statement(self): """ Expanding Rule 64: ProcedureStatement -> ProcedureIdentifier OptionalActualParameterList """ if self.t_type() == 'MP_IDENTIFIER': Parser.print_tree('64') self.procedure_identifier() self.optional_actual_parameter_list() else: self.error('MP_IDENTIFIER') def optional_actual_parameter_list(self): """ Expanding Rules 65, 66 : OptionalActualParameterList -> "(" ActualParameter ActualParameterTail ")" """ eps_list = ['MP_TIMES', 'MP_RPAREN', 'MP_PLUS', 'MP_COMMA', 'MP_MINUS', 'MP_SCOLON', 'MP_LTHAN', 'MP_LEQUAL', 'MP_GTHAN', 'MP_GEQUAL', 'MP_EQUAL', 'MP_NEQUAL', 'MP_AND', 'MP_DIV', 'MP_DO', 'MP_DOWNTO', 'MP_ELSE', 'MP_END', 'MP_MOD', 'MP_OR', 'MP_THEN', 'MP_TO', 'MP_UNTIL'] actual_rec = SemanticRecord() if self.t_type() == 'MP_LPAREN': Parser.print_tree('65') self.match('(') self.actual_parameter(actual_rec) self.actual_parameter_tail(actual_rec) self.match(')') elif self.t_type() in eps_list: Parser.print_tree('66') self.epsilon() else: self.error(eps_list.append('MP_LPAREN')) def actual_parameter_tail(self, act_rec): """ Expanding Rules 67, 68: ActualParameterTail -> "," ActualParameter ActualParameterTail -> epsilon """ if self.t_type() == 'MP_COMMA': Parser.print_tree('67') self.match(',') self.actual_parameter(act_rec) self.actual_parameter_tail(act_rec) elif self.t_type() == 'MP_RPAREN': Parser.print_tree('68') self.epsilon() else: self.error(['MP_COMMA', 'MP_RPAREN']) def actual_parameter(self,act_rec): """ Expanding Rule 69: ActualParameter -> OrdinalExpression """ accepted_list = ['MP_LPAREN','MP_PLUS','MP_MINUS','MP_IDENTIFIER', 'MP_INTEGER','MP_NOT'] if self.t_type() in accepted_list: Parser.print_tree('69') self.ordinal_expression(act_rec) else: self.error(accepted_list) def expression(self, sem_rec): """ Expanding Rule 70 : Expression -> SimpleExpression OptionalRelationalPart """ accepted_list = ['MP_LPAREN','MP_PLUS','MP_MINUS','MP_IDENTIFIER', 'MP_INTEGER','MP_NOT'] if self.t_type() in accepted_list: Parser.print_tree('70') self.simple_expression(sem_rec) self.optional_relational_part(sem_rec) else: self.error(accepted_list) def optional_relational_part(self, rel_rec): """ Expanding Rule 71, 72: OptionalRelationalPart -> RelationalOperator SimpleExpression -> epsilon """ accepted_list = ['MP_LTHAN', 'MP_LEQUAL', 'MP_GTHAN', 'MP_GEQUAL', 'MP_EQUAL', 'MP_NEQUAL'] eps_list = ['MP_RPAREN', 'MP_COMMA', 'MP_SCOLON', 'MP_DO', 'MP_DOWNTO', 'MP_ELSE', 'MP_END', 'MP_THEN', 'MP_TO', 'MP_UNTIL'] if self.t_type() in accepted_list: Parser.print_tree('71') self.relational_operator(rel_rec) self.simple_expression(sem_rec = SemanticRecord()) elif self.t_type() in eps_list: Parser.print_tree('72') self.epsilon() else: self.error(accepted_list.extend(eps_list)) def relational_operator(self, expr_rec): """ Expanding Rules 73 - 78: RelationalOperator -> "=" -> "<" -> ">" -> "<=" -> ">=" -> "<>" """ if self.t_type() == 'MP_EQUAL': Parser.print_tree('73') self.match(self.t_lexeme()) expr_rec.lexeme = 'eq' elif self.t_type() == 'MP_LTHAN': Parser.print_tree('74') self.match(self.t_lexeme()) expr_rec.lexeme = 'lt' elif self.t_type() == 'MP_GTHAN': Parser.print_tree('75') self.match(self.t_lexeme()) expr_rec.lexeme = 'gt' elif self.t_type() == 'MP_LEQUAL': Parser.print_tree('76') self.match(self.t_lexeme()) expr_rec.lexeme = 'lte' elif self.t_type() == 'MP_GEQUAL': Parser.print_tree('77') self.match(self.t_lexeme()) expr_rec.lexeme = 'gte' elif self.t_type() == 'MP_NEQUAL': Parser.print_tree('78') self.match(self.t_lexeme()) expr_rec.lexeme = 'ne' else: self.error(['MP_EQUAL', 'MP_LTHAN', 'MP_GTHAN', 'MP_LEQUAL', 'MP_GEQUAL', 'MP_NEQUAL']) def simple_expression(self, sem_rec): """ Expanding Rule 79 : SimpleExpression -> OptionalSign Term TermTail """ accepted_list = ['MP_LPAREN', 'MP_PLUS', 'MP_MINUS', 'MP_IDENTIFIER', 'MP_INTEGER', 'MP_NOT'] if self.t_type() in accepted_list: Parser.print_tree('79') self.optional_sign(sem_rec) self.term(sem_rec) self.term_tail(sem_rec) else: self.error(accepted_list) def term_tail(self, term_tail_rec): # term_tail_rec contains information about the left operand of the expression """ Expanding Rule 80,81 : TermTail -> AddingOperator Term TermTail TermTail -> ? """ result_sem_rec = SemanticRecord() term_sem_rec = SemanticRecord() add_op_sem_rec = SemanticRecord() eps_list = ['MP_RPAREN', 'MP_COMMA', 'MP_SCOLON', 'MP_LTHAN', 'MP_LEQUAL', 'MP_NEQUAL', 'MP_EQUAL', 'MP_GTHAN', 'MP_GEQUAL', 'MP_DO', 'MP_DOWNTO', 'MP_ELSE', 'MP_TO', 'MP_UNTIL'] accepted_list = ['MP_PLUS', 'MP_MINUS', 'MP_OR'] if self.t_type() in accepted_list: Parser.print_tree('80') #self.optional_sign() self.adding_operator(add_op_sem_rec) self.term(term_sem_rec) self.sem_analyzer.gen_arithmetic(term_tail_rec, add_op_sem_rec, term_sem_rec, result_sem_rec) self.term_tail(result_sem_rec) elif self.t_type() in eps_list: Parser.print_tree('81') self.epsilon() else: self.error(accepted_list.extend(eps_list)) def optional_sign(self, sem_rec): """ Expanding Rule 82,83,84: OptionalSign -> "+" OptionalSign -> "-" OptionalSign -> ? """ eps_list = ['MP_IDENTIFIER', 'MP_INTEGER','MP_NOT', 'MP_LPAREN'] if self.t_type() == 'MP_PLUS': Parser.print_tree('82') self.match(self.t_lexeme()) elif self.t_type() == 'MP_MINUS': Parser.print_tree('83') self.match(self.t_lexeme()) sem_rec.negative = 1 elif self.t_type() in eps_list: Parser.print_tree('84') self.epsilon() else: self.error(eps_list.extend(['MP_PLUS','MP_MINUS'])) def adding_operator(self, sem_rec): """ Expanding Rule 85,86,87: AddingOperator -> "+" AddingOperator -> "-" AddingOperator -> "or" """ accepted_list = ['MP_PLUS','MP_MINUS','MP_OR'] if self.t_type() in accepted_list: in_lexeme = self.t_lexeme() self.match(in_lexeme) sem_rec.lexeme = in_lexeme else: self.error(accepted_list) def term(self, sem_rec): """ Expanding Rule 88: Term -> Factor FactorTail """ accepted_list = ['MP_LPAREN', 'MP_IDENTIFIER', 'MP_INTEGER', 'MP_NOT'] if self.t_type() in accepted_list: Parser.print_tree('88') self.factor(sem_rec) self.factor_tail(sem_rec) else: self.error(accepted_list) def factor_tail(self, sem_rec): """ Expanding Rule 89,90: FactorTail -> MultiplyingOperator Factor FactorTail FactorTail -> ? """ result_sem_rec = SemanticRecord() factor_sem_rec = SemanticRecord() mul_op_sem_rec = SemanticRecord() accepted_list = ['MP_TIMES', 'MP_AND', 'MP_DIV', 'MP_MOD'] eps_list = ['MP_RPAREN', 'MP_PLUS', 'MP_COMMA', 'MP_MINUS', 'MP_SCOLON', 'MP_LTHAN', 'MP_LEQUAL', 'MP_NEQUAL', 'MP_EQUAL', 'MP_GTHAN', 'MP_GEQUAL', 'MP_DO', 'MP_DOWNTO', 'MP_ELSE', 'MP_END', 'MP_OR', 'MP_THEN', 'MP_TO', 'MP_UNTIL'] if self.t_type() in accepted_list: Parser.print_tree('89') self.multiplying_operator(mul_op_sem_rec) self.factor(factor_sem_rec) self.sem_analyzer.gen_arithmetic(sem_rec, mul_op_sem_rec, factor_sem_rec, result_sem_rec) self.factor_tail(result_sem_rec) elif self.t_type() in eps_list: Parser.print_tree('90') self.epsilon() else: self.error(accepted_list.extend(eps_list)) def multiplying_operator(self, mul_op_sem_rec): """ Expanding Rule 91,92,93,94: MultiplyingOperator -> "*" MultiplyingOperator -> "div" MultiplyingOperator -> "mod" MultiplyingOperator -> "and" """ if self.t_type() == 'MP_TIMES': Parser.print_tree('91') self.match(self.t_lexeme()) mul_op_sem_rec.lexeme = '*' elif self.t_type() == 'MP_DIV': Parser.print_tree('92') self.match(self.t_lexeme()) mul_op_sem_rec.lexeme = 'div' elif self.t_type() == 'MP_MOD': Parser.print_tree('93') self.match(self.t_lexeme()) mul_op_sem_rec.lexeme = 'mod' elif self.t_type() == 'MP_AND': Parser.print_tree('94') self.match(self.t_lexeme()) mul_op_sem_rec.lexeme = 'and' else: self.error(['MP_TIMES', 'MP_DIV', 'MP_MOD', 'MP_AND']) def factor(self, sem_rec): #AAA """ Expanding Rule 95,96,97,98,99: Factor -> UnsignedInteger Factor -> VariableIdentifier Factor -> "not" Factor Factor -> "(" Expression ")" Factor -> FunctionIdentifier OptionalActualParameterList """ if self.t_type() == 'MP_INTEGER': Parser.print_tree('95') sem_rec.lexeme = self.t_lexeme() sem_rec.type = 'Integer' self.sem_analyzer.gen_push_int(sem_rec) self.match(self.t_lexeme()) elif self.t_type() == 'MP_IDENTIFIER': Parser.print_tree('96') sem_rec.lexeme = self.t_lexeme() self.match(self.t_lexeme()) self.sem_analyzer.gen_push_id(sem_rec, SemanticRecord()) elif self.t_type() == 'MP_NOT': Parser.print_tree('97') self.match(self.t_lexeme()) self.factor(sem_rec) elif self.t_type() == 'MP_LPAREN': Parser.print_tree('98') self.match(self.t_lexeme()) # if self.t_type() == 'MP_LPAREN': # self.match('(') # self.expression(sem_rec) # self.match(')') # else: self.expression(sem_rec) if self.t_type() == 'MP_RPAREN': self.match(self.t_lexeme()) else: self.error('MP_RPAREN') else: self.error(['MP_INTEGER', 'MP_IDENTIFIER', 'MP_NOT', 'MP_LPAREN']) return sem_rec def program_identifier(self): """ Expanding Rule 100: ProgramIdentifier -> Identifier """ if self.t_type() == 'MP_IDENTIFIER': Parser.print_tree('100') self.program_name = self.t_lexeme() self.match(self.program_name) else: self.error('MP_IDENTIFIER') def variable_identifier(self, sem_rec): """ Expanding Rule 101: VariableIdentifier -> Identifier """ if self.t_type() == 'MP_IDENTIFIER': Parser.print_tree('101') in_lexeme = self.t_lexeme() self.match(in_lexeme) sem_rec.lexeme = in_lexeme sem_rec.type = 'Integer' else: self.error('MP_IDENTIFIER') def procedure_identifier(self): """ Expanding Rule 102: ProcedureIdentifier -> Identifier """ if self.t_type() == 'MP_IDENTIFIER': Parser.print_tree('102') self.cur_proc_name = self.t_lexeme() self.match(self.cur_proc_name) else: self.error('MP_IDENTIFIER') def function_identifier(self): """ Expanding Rule 103: ProgramIdentifier -> Identifier """ if self.t_type() == 'MP_IDENTIFIER': Parser.print_tree('103') self.cur_func_name = self.t_lexeme() self.match(self.cur_func_name) else: self.error('MP_IDENTIFIER') def boolean_expression(self, expr_rec): """ Expanding Rule 104: BooleanExpression -> Expression """ accepted_list = ['MP_LPAREN', 'MP_PLUS', 'MP_MINUS', 'MP_IDENTIFIER', 'MP_INTEGER', 'MP_NOT'] if self.t_type() in accepted_list: Parser.print_tree('104') self.match(self.t_lexeme()) self.expression(expr_rec) self.match(self.t_lexeme()) else: self.error(accepted_list) def ordinal_expression(self, sem_rec): """ Expanding Rule 105: OrdinalExpression -> Expression """ accepted_list = ['MP_LPAREN', 'MP_PLUS', 'MP_MINUS', 'MP_IDENTIFIER', 'MP_INTEGER', 'MP_NOT'] if self.t_type() in accepted_list: Parser.print_tree('105') self.expression(sem_rec) else: self.error(accepted_list) def identifier_list(self, id_list): """ Expanding Rule 106: IdentifierList -> Identifier IdentifierTail """ if self.t_type() == 'MP_IDENTIFIER': Parser.print_tree('106') id_list.append(self.identifier()) self.identifier_tail(id_list) else: self.error() return id_list def identifier_tail(self, id_list): """ Expanding Rule 107,108: IdentifierTail -> "," Identifier IdentifierTail IdentifierTail -> ? """ if self.t_type() == 'MP_COMMA': Parser.print_tree('107') self.match(',') id_list.append(self.identifier()) self.identifier_tail(id_list) elif self.t_type() == 'MP_COLON': Parser.print_tree('108') self.epsilon() else: self.error(['MP_COMMMA', 'MP_COLON']) return id_list def identifier(self): id = self.t_lexeme() self.match(id) return id