def backward_detector_function_get(self, sm): assert sm.get_orphaned_state_index_list() == [] dsm = StateMachineDecorator(sm, "BACKWARD_DETECTOR_" + repr(sm.get_id()), PostContextSM_ID_List = [], BackwardLexingF = True, BackwardInputPositionDetectionF = True) variable_db.init() init_address_handling(dsm.get_direct_transition_to_terminal_db()) function_body = state_machine_coder.do(dsm) comment = [] if Setup.comment_state_machine_transitions_f: comment = Setup.language_db["$ml-comment"]("BEGIN: BACKWARD DETECTOR STATE MACHINE\n" + \ sm.get_string(NormalizeF=False) + \ "\nEND: BACKWARD DETECTOR STATE MACHINE") comment.append("\n") # -- input position detectors simply the next 'catch' and return terminal = [] terminal.append("\n") terminal.append(" __quex_assert_no_passage();\n") terminal.append(get_label("$terminal-general-bw") + ":\n") terminal.append(" " + self.language_db["$input/seek_position"]("end_of_core_pattern_position") + "\n") terminal.append(" " + self.language_db["$input/increment"] + "\n") terminal.append(" return;\n") routed_address_set = get_address_set_subject_to_routing() state_router_txt = "" if len(routed_address_set) != 0: routed_state_info_list = state_router.get_info(routed_address_set, dsm) state_router_txt = state_router.do(routed_state_info_list) variable_db.require("target_state_index", Condition_ComputedGoto=False) variable_db.require("input") variable_db.require("end_of_core_pattern_position") local_variable_definition = self.language_db["$local-variable-defs"](variable_db.get()) # Put all things together txt = [] txt.append(bwd_prolog.replace("$$ID$$", repr(sm.get_id()).replace("L", ""))) txt.extend(local_variable_definition) txt.extend(comment) txt.extend(function_body) txt.extend(terminal) txt.append(state_router_txt) txt.append(bwd_epilog.replace("$$INIT_STATE_ID$$", get_label_of_address(sm.init_state_index))) return get_plain_strings(txt)
def get_code(self): """Template transition target states. The target state is determined at run-time based on a 'state_key' for the template. NOTE: This handles also the recursive case. """ LanguageDB = Setup.language_db if not self.recursive(): label = "template_%i_target_%i[template_state_key]" % (self.template_index, self.target_index) get_label("$state-router", U=True) # Ensure reference of state router return [ "QUEX_GOTO_STATE(%s);\n" % label ] elif not self.uniform_state_entries_f(): label = "template_%i_map_state_key_to_state_index[template_state_key]" % self.template_index get_label("$state-router", U=True) # Ensure reference of state router return [ "QUEX_GOTO_STATE(%s);\n" % label ] else: return [ "goto %s;" % get_label_of_address(self.template_index, U=True) ]
def get_info(StateIndexList, DSM): LanguageDB = Setup.language_db # In some strange cases, a 'dummy' state router is required so that # 'goto __STATE_ROUTER;' does not reference a non-existing label. Then, # we return an empty text array. if len(StateIndexList) == 0: return [] # Make sure, that for every state the 'drop-out' state is also mentioned result = [None] * len(StateIndexList) for i, index in enumerate(StateIndexList): assert type(index) != str if index >= 0: # Transition to state entry code = "goto %s; " % get_label_of_address(index) result[i] = (index, code) else: # Transition to a templates 'drop-out' code = "goto " + get_label("$drop-out", -index) + "; " result[i] = (get_address("$drop-out", -index), code) return result
def get_info(StateIndexList, DSM): LanguageDB = Setup.language_db # In some strange cases, a 'dummy' state router is required so that # 'goto __STATE_ROUTER;' does not reference a non-existing label. Then, # we return an empty text array. if len(StateIndexList) == 0: return [] # Make sure, that for every state the 'drop-out' state is also mentioned result = [None] * len(StateIndexList) for i, index in enumerate(StateIndexList): assert type(index) != str if index >= 0: # Transition to state entry code = "goto %s; " % get_label_of_address(index) result[i] = (index, code) else: # Transition to a templates 'drop-out' code = "goto " + get_label("$drop-out", - index) + "; " result[i] = (get_address("$drop-out", - index), code) return result
def get_code(self): """Template transition target states. The target state is determined at run-time based on a 'state_key' for the template. NOTE: This handles also the recursive case. """ LanguageDB = Setup.language_db if not self.recursive(): label = "template_%i_target_%i[template_state_key]" % ( self.template_index, self.target_index) get_label("$state-router", U=True) # Ensure reference of state router return ["QUEX_GOTO_STATE(%s);\n" % label] elif not self.uniform_state_entries_f(): label = "template_%i_map_state_key_to_state_index[template_state_key]" % self.template_index get_label("$state-router", U=True) # Ensure reference of state router return ["QUEX_GOTO_STATE(%s);\n" % label] else: return [ "goto %s;" % get_label_of_address(self.template_index, U=True) ]
def __path_walker(txt, PathWalker, SMD): """Generates the path walker, that walks along the character sequence. """ PathList = PathWalker.path_list() Skeleton = PathList[0].skeleton() PathWalkerID = PathWalker.core().state_index if PathWalker.uniform_state_entries_f(): # (1) Input Block (get the new character) txt.extend(input_block.do(PathWalkerID, False, SMD)) # (2) Acceptance information/Store Input positions txt.extend(acceptance_info.do(PathWalker, PathWalkerID, SMD, ForceSaveLastAcceptanceF=True)) else: txt.append(" __quex_assert_no_passage();\n") txt.append(get_label("$entry", PathWalkerID) + ":\n") txt.append(" __quex_debug(\"path walker %i\");\n" % PathWalkerID) # (3) Transition Map # (3.1) The comparison with the path's current character # If terminating zero is reached, the path's end state is entered. if PathWalker.uniform_state_entries_f(): next_state = [ "goto %s;\n" % get_label_of_address(PathWalkerID, U=True) ] end_state = __end_state_router(PathWalker, SMD) else: next_state = [ __state_router(PathWalker, SMD) ] end_state = [" "] + next_state txt.append(" ") txt.append(LanguageDB["$if =="]("*path_iterator")) txt.append(" ") txt.append(LanguageDB["$increment"]("path_iterator")) txt.append("\n") txt.append(" ") txt.extend(next_state) txt.append(" ") txt.append(LanguageDB["$elseif"] \ + LanguageDB["$=="]("*path_iterator", "QUEX_SETTING_PATH_TERMINATION_CODE") \ + LanguageDB["$then"]) txt.extend(end_state) txt.append(" ") txt.append(LanguageDB["$endif"]) txt.append("\n") # (3.2) Transition map of the 'skeleton' trigger_map = PathWalker.transitions().get_trigger_map() if len(trigger_map) == 0: # (This happens, for example, if there are only keywords and no # 'overlaying' identifier pattern.) # Even if the skeleton/trigger map is empty there must be something # that catches the 'buffer limit code'. # => Define an 'all drop out' trigger_map and then, # => Adapt the trigger map, so that the 'buffer limit' is an # isolated single interval. trigger_map = [ (Interval(-sys.maxint, sys.maxint), None) ] state_index_str = None if not PathWalker.uniform_state_entries_f(): state_index_str = "path_walker_%i_state[path_iterator - path_walker_%i_base]" % (PathWalkerID, PathWalkerID) txt.extend(transition_block.do(trigger_map, PathWalkerID, SMD, ReturnToState_Str=state_index_str)) # (4) The drop out (nothing matched) # (Path iterator has not been increased yet) txt.extend(drop_out.do(PathWalker, PathWalkerID, SMD)) return
def __state_entries(txt, PathWalker, SMD): """Defines the entries of the path's states, so that the state key for the template is set, before the jump into the template. E.g. STATE_4711: path_iterator = path_23 + 0; goto PATHWALKER_23; STATE_3123: path_iterator = path_23 + 1; goto PATHWALKER_23; STATE_8912: path_iterator = path_23 + 2; goto PATHWALKER_23; """ sm = SMD.sm() PathN = len(PathWalker.path_list()) require_path_end_state_variable_f = False txt.append("\n") for path in PathWalker.path_list(): prev_state_index = None # Last state of sequence is not in the path, it is the first state after. for i, info in enumerate(path.sequence()[:-1]): state_index = info[0] # No need for state router if: # (i) PathWalker is uniform, because then even after reload no dedicated # state entry is required. # (ii) The state is not entered from any other state except the predecessor # on the path. # But: # The first state always needs an entry. if prev_state_index != None: candidate = sm.get_only_entry_to_state(state_index) if PathWalker.uniform_state_entries_f() and prev_state_index == candidate: prev_state_index = state_index continue state = SMD.sm().states[state_index] entry_txt = [] if PathWalker.uniform_state_entries_f(): # If all state entries are uniform, the entry handling happens uniformly at # the entrance of the template, not each state. label_str = get_label("$entry", state_index) + ":\n" if state_index != SMD.sm().init_state_index: label_str = " __quex_assert_no_passage();\n" + label_str entry_txt.append(label_str) entry_txt.append(" ") entry_txt.append(LanguageDB["$debug-state"](state_index, SMD.forward_lexing_f())) else: entry_txt.extend(input_block.do(state_index, False, SMD)) entry_txt.extend(acceptance_info.do(state, state_index, SMD, ForceSaveLastAcceptanceF=True)) if PathWalker.uniform_state_entries_f() and PathN != 1: require_path_end_state_variable_f = True end_state_index = path.sequence()[-1][0] entry_txt.append(" path_end_state = QUEX_LABEL(%i);\n" \ % get_address("$entry", end_state_index, U=True, R=True)) entry_txt.append(" ") entry_txt.append(LanguageDB["$assignment"]( "path_iterator ", "path_%i + %i" % (path.index(), i))) entry_txt.append("goto %s;\n\n" % get_label_of_address(PathWalker.core().state_index, U=True)) txt.append(Address("$entry", state_index, Code=entry_txt)) prev_state_index = state_index return require_path_end_state_variable_f
def backward_detector_function_get(self, sm): assert sm.get_orphaned_state_index_list() == [] dsm = StateMachineDecorator(sm, "BACKWARD_DETECTOR_" + repr(sm.get_id()), PostContextSM_ID_List=[], BackwardLexingF=True, BackwardInputPositionDetectionF=True) variable_db.init() init_address_handling(dsm.get_direct_transition_to_terminal_db()) function_body = state_machine_coder.do(dsm) comment = [] if Setup.comment_state_machine_transitions_f: comment = Setup.language_db["$ml-comment"]("BEGIN: BACKWARD DETECTOR STATE MACHINE\n" + \ sm.get_string(NormalizeF=False) + \ "\nEND: BACKWARD DETECTOR STATE MACHINE") comment.append("\n") # -- input position detectors simply the next 'catch' and return terminal = [] terminal.append("\n") terminal.append(" __quex_assert_no_passage();\n") terminal.append(get_label("$terminal-general-bw") + ":\n") terminal.append(" " + self.language_db["$input/seek_position"] ("end_of_core_pattern_position") + "\n") terminal.append(" " + self.language_db["$input/increment"] + "\n") terminal.append(" return;\n") routed_address_set = get_address_set_subject_to_routing() state_router_txt = "" if len(routed_address_set) != 0: routed_state_info_list = state_router.get_info( routed_address_set, dsm) state_router_txt = state_router.do(routed_state_info_list) variable_db.require("target_state_index", Condition_ComputedGoto=False) variable_db.require("input") variable_db.require("end_of_core_pattern_position") local_variable_definition = self.language_db["$local-variable-defs"]( variable_db.get()) # Put all things together txt = [] txt.append( bwd_prolog.replace("$$ID$$", repr(sm.get_id()).replace("L", ""))) txt.extend(local_variable_definition) txt.extend(comment) txt.extend(function_body) txt.extend(terminal) txt.append(state_router_txt) txt.append( bwd_epilog.replace("$$INIT_STATE_ID$$", get_label_of_address(sm.init_state_index))) return get_plain_strings(txt)