def prepare_state(self, OldState, StateIndex): """REQUIRES: 'self.init_state_forward_f', 'self.engine_type', 'self.__from_db'. """ state = AnalyzerState.from_State(OldState, StateIndex, self.engine_type) cmd_list = [] if self.engine_type.is_BACKWARD_PRE_CONTEXT(): cmd_list.extend( Op.PreContextOK(cmd.acceptance_id()) for cmd in OldState.single_entry.get_iterable(SeAccept) ) if state.transition_map is None and False: # NOTE: We need a way to disable this exception for PathWalkerState-s(!) # It's safe, not to allow it, in general. #------------------------------------------------------------------------ # If the state has no further transitions then the input character does # not have to be read. This is so, since without a transition map, the # state immediately drops out. The drop out transits to a terminal. # Then, the next action will happen from the init state where we work # on the same position. If required the reload happens at that moment, # NOT before the empty transition block. # # This is not true for Path Walker States, so we offer the option # 'ForceInputDereferencingF' assert StateIndex != self.init_state_index # Empty state machine! --> impossible if self.engine_type.is_FORWARD(): cmd_list.append(Op.InputPIncrement()) else: cmd_list.append(Op.InputPDecrement()) else: if self.engine_type.is_FORWARD(): cmd_list.extend([Op.InputPIncrement(), Op.InputPDereference()]) else: cmd_list.extend([Op.InputPDecrement(), Op.InputPDereference()]) ta = TransitionAction(OpList.from_iterable(cmd_list)) # NOTE: The 'from reload transition' is implemented by 'prepare_for_reload()' for source_state_index in self.__from_db[StateIndex]: assert source_state_index != E_StateIndices.BEFORE_ENTRY state.entry.enter(StateIndex, source_state_index, ta.clone()) if StateIndex == self.init_state_index: if self.engine_type.is_FORWARD(): ta = TransitionAction(OpList(Op.InputPDereference())) state.entry.enter_state_machine_entry(self.__state_machine_id, StateIndex, ta) return state
def __prepare_begin_and_putback(self, OnBegin, OnEnd): """If we deal with variable character sizes, the begin of the letter is stored in 'character_begin_p'. To reset the input pointer 'input_p = character_begin_p' is applied. """ if not Setup.buffer_codec.variable_character_sizes_f(): # 1 character == 1 chunk # => rest to last character: 'input_p = input_p - 1' self.on_step = [] self.on_putback = [ Op.InputPDecrement() ] else: # 1 character == variable number of chunks # => store begin of character in 'lexeme_start_p' # => rest to last character: 'input_p = lexeme_start_p' self.on_step = [ Op.Assign(E_R.CharacterBeginP, E_R.InputP) ] self.on_putback = [ Op.Assign(E_R.InputP, E_R.CharacterBeginP) ] self.on_begin = concatinate(self.on_step, OnBegin) self.on_end = concatinate(self.on_putback, OnEnd)
def prepare_for_reload(self, TheAnalyzer, BeforeReloadOpList=None, AfterReloadOpList=None): """Prepares state for reload. Reload procedure .- State 'X' ---. | | .-- Reloader------. | BUFFER LIMIT | .----------------. | | CODE detected ------->-------| Door from X: | | | | | Actions before | | | | | reload. | | | | '----------------' | | | | | | | | | reload buffer> | | .----------------. | | | | | Door for |---<-------(good)--* | | | RELOAD SUCCESS:| | | | | | Actions after | | (bad) | | | Reload. | '------- |--------' | '----------------' | | | .----------------. '---------------' | Door for | | RELOAD FAILURE | '----------------' (1) Create 'Door for RELOAD SUCCESS'. (2) Determine 'Door for RELOAD FAILURE'. (3) Create 'Door from X' in Reloader. (4) Adapt state X's transition map, so that: BUFFER LIMIT CODE --> reload procedure. """ assert self.transition_map is not None assert BeforeReloadOpList is None or isinstance(BeforeReloadOpList, OpList) assert AfterReloadOpList is None or isinstance(AfterReloadOpList, OpList) if not TheAnalyzer.engine_type.subject_to_reload(): # Engine type does not require reload => no reload. return elif self.transition_map.is_only_drop_out(): # If the state drops out anyway, then there is no need to reload. # -- The transition map is not adapted. # -- The reloader is not instrumented to reload for that state. return assert self.index in TheAnalyzer.state_db reload_state = TheAnalyzer.reload_state assert reload_state.index in (E_StateIndices.RELOAD_FORWARD, E_StateIndices.RELOAD_BACKWARD) # (1) Door for RELOAD SUCCESS # after_cl = [] if TheAnalyzer.engine_type.is_FORWARD(): after_cl.append(Op.InputPIncrement()) else: after_cl.append(Op.InputPDecrement()) after_cl.append(Op.InputPDereference()) if AfterReloadOpList is not None: after_cl.extend(AfterReloadOpList) self.entry.enter_OpList(self.index, reload_state.index, OpList.from_iterable(after_cl)) self.entry.categorize(self.index) # Categorize => DoorID is available. on_success_door_id = self.entry.get_door_id(self.index, reload_state.index) # (2) Determin Door for RELOAD FAILURE # if TheAnalyzer.is_init_state_forward(self.index): on_failure_door_id = DoorID.incidence(E_IncidenceIDs.END_OF_STREAM) else: on_failure_door_id = TheAnalyzer.drop_out_DoorID(self.index) # (3) Create 'Door from X' in Reloader assert on_failure_door_id != on_success_door_id reload_door_id = reload_state.add_state(self.index, on_success_door_id, on_failure_door_id, BeforeReloadOpList) # (4) Adapt transition map: BUFFER LIMIT CODE --> reload_door_id # self.transition_map.set_target(Setup.buffer_limit_code, reload_door_id) return
if "0" in sys.argv: analyzer, a, b = basic_setup( [10, 10]) # Recursion on trigger = 10 in both states elif "0b" in sys.argv: analyzer, a, b = basic_setup( [10, 11]) # Recursion on trigger = 10 in a, trigger = 11 in b elif "1" in sys.argv: analyzer, a, b = basic_setup( [10, 10]) # Recursion on trigger = 10 in both states print "NOTE: Set SAME command list in recursion." set_recursive_command_list(a, [Op.InputPIncrement()]) set_recursive_command_list(b, [Op.InputPIncrement()]) elif "1b" in sys.argv: analyzer, a, b = basic_setup( [10, 10]) # Recursion on trigger = 10 in both states print "NOTE: Set DIFFERENT command list in recursion." set_recursive_command_list(a, [Op.InputPIncrement()]) set_recursive_command_list(b, [Op.InputPDecrement()]) elif "1c" in sys.argv: analyzer, a, b = basic_setup( [10, 11]) # Recursion on trigger = 10 in both states print "NOTE: Set SAME command list in recursion ON DIFFERENT triggers." set_recursive_command_list(a, [Op.InputPIncrement()]) set_recursive_command_list(b, [Op.InputPIncrement()]) test(analyzer, a, b)