def parse_while(self, pos: int): ''' Логика обработки директивы while ''' return_pos = pos + 1 if len(self.all_file[pos].arguments) != 1: raise Exception('invalid num params') expr_str = ParserTool.parse_assembly_string(self.__check_defines(pos)).arguments[0][:] expr_result = bool(eval_expr(expr_str)) cycle_pred = True # устанавливается в True при первом проходе по тексту while cycle_pred == True: while return_pos < len(self.all_file) and self.all_file[return_pos].code != ENDW_TOKEN: if expr_result: return_pos = MacroAssembly.statement(self, return_pos) else: return_pos += 1 if return_pos == len(self.all_file): raise Exception('endw not found') if expr_result == False: cycle_pred = expr_result else: expr_str = ParserTool.parse_assembly_string(self.__check_defines(pos)).arguments[0][:] cycle_pred = expr_result = bool(eval_expr(expr_str)) if expr_result != False: return_pos = pos + 1 return return_pos
def parse_include(self, pos: int): ''' Логика обработки include -- удаляем ''' if len(self.all_file[pos].arguments) != 1: raise Exception('invalid num params') filename = str(eval_expr(ParserTool.parse_assembly_string(self.__check_defines(pos)).arguments[0])) self.all_file = self.all_file[:pos] + [ParserTool.parse_assembly_string(s) for s in open(filename).readlines()] + self.all_file[pos + 1:] return pos - 1
def parse_rept(self, pos: int): ''' Логика обработки директивы rept rept (целое значение) -- выполнение n раз ''' return_pos = pos + 1 if len(self.all_file[pos].arguments) != 1: raise Exception('invalid num params') expr_str = ParserTool.parse_assembly_string(self.__check_defines(pos)).arguments[0][:] n = int(eval_expr(expr_str)) while n: while return_pos < len(self.all_file) and self.all_file[return_pos].code != ENDR_TOKEN: return_pos = MacroAssembly.statement(self, return_pos) if return_pos == len(self.all_file): raise Exception('endr not found') n -= 1 if n: # переходим только если не прошли n раз return_pos = pos + 1 return return_pos
def parse_if(self, pos: int): ''' Обработка конструкции if грамматика вида ifndef <expr> <statements> <else> <statements> endif ветка else не обязательна ''' return_pos = pos + 1 if len(self.all_file[pos].arguments) != 1: raise Exception('invalid num params') expr_result = bool(eval_expr(ParserTool.parse_assembly_string(self.__check_defines(pos)).arguments[0])) while return_pos < len(self.all_file) and self.all_file[return_pos].code != ENDIF_TOKEN: if self.all_file[return_pos].code == ELSE_TOKEN: expr_result = not expr_result return_pos += 1 continue if expr_result: # если true -- то обрабатываем return_pos = MacroAssembly.statement(self, return_pos) else: # иначе обходим return_pos += 1 if return_pos == len(self.all_file): raise Exception('endif not found') return return_pos
def statement(self, pos: int): ''' Обработка конструкции statement ''' # обработка подстановок для строк (переменных) # обработка макроподстановок #print(self.variables) #print(self.all_file[pos].source) work_str = copy.deepcopy(self.all_file[pos]) work_str.source = self.__check_defines(pos) work_str = ParserTool.parse_assembly_string(work_str.source) return_pos = pos if work_str.code == IFDEF_TOKEN: return_pos = self.parse_ifdef(pos) elif work_str.code == IF_TOKEN: return_pos = self.parse_if(pos) elif work_str.code == IFNDEF_TOKEN: return_pos = self.parse_ifndef(pos) elif work_str.code == MACRO_TOKEN: return_pos = self.parse_macro(pos) elif work_str.code == DEFINE_TOKEN: return_pos = self.parse_define(pos) elif work_str.code == SET_TOKEN: return_pos = self.parse_set(pos) elif work_str.code == WHILE_TOKEN: return_pos = self.parse_while(pos) elif work_str.code == REPT_TOKEN: return_pos = self.parse_rept(pos) elif work_str.code == INCLUDE_TOKEN: return_pos = self.parse_include(pos) elif work_str.code in self.macro_table.keys(): self.output_file += MacroAssembly.evaluate([ParserTool.parse_assembly_string(asm_op) for asm_op in self.macro_table[work_str.code] .execute(work_str.arguments)], self.macro_table, self.variables) else: self.output_file.append(work_str.source) return return_pos + 1
def parse_set(self, pos: int): ''' Логика обработки директивы set ''' label: str = self.all_file[pos].label if label in self.variables.keys(): if len(self.all_file[pos].arguments) == 1: self.variables[label] = eval_expr(ParserTool.parse_assembly_string(self.__check_defines(pos)).arguments[0]) else: raise Exception("Invalid number of params") else: raise Exception(f"variable {label} has never defined") return pos
def __open_file(self): ''' Инициализация файла с кодом ''' with open(self.filename, 'r') as fs: self.all_file = [ParserTool.parse_assembly_string(asm_str) for asm_str in fs.readlines()]