def prepare_state(self, OldState, StateIndex, OnBeforeEntry): """Prepares states to increment the input/read pointer and dereferences it to access the lexatom for the state transition triggering. REQUIRES: 'self.init_state_forward_f', 'self.engine_type', 'self.__from_db'. """ state = FSM_State.from_State(OldState, StateIndex, self.engine_type, self.dial_db) 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_ext = [Op.Increment(E_R.InputP)] else: cmd_ext = [Op.Decrement(E_R.InputP)] else: if self.engine_type.is_FORWARD(): cmd_ext = [Op.Increment(E_R.InputP), Op.InputPDereference()] else: cmd_ext = [Op.Decrement(E_R.InputP), Op.InputPDereference()] cmd_list.extend(cmd_ext) 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(): on_entry_op_list = OnBeforeEntry.clone() on_entry_op_list.append(Op.InputPDereference()) ta = TransitionAction(on_entry_op_list) state.entry.enter_state_machine_entry(self.__state_machine_id, StateIndex, ta) return state
def _get_state_machine_vs_terminal_list(CloserSequence, OpenerSequence, CounterDb, DoorIdAfter): """Additionally to all characters, the loop shall walk along the 'closer'. If the closer matches, the range skipping exits. Characters need to be counted properly. RETURNS: list(state machine, terminal) The list contains only one single element. """ # Opener Sequence Reaction opener_op_list = [Op.Increment(E_R.Counter)] # 'Goto loop entry' is added later (loop id unknown, yet). # Closer Sequence Reaction closer_op_list = [ Op.Decrement(E_R.Counter), Op.GotoDoorIdIfCounterEqualZero(DoorIdAfter) ] # 'Goto loop entry' is added later (loop id unknown, yet). return [ _get_state_machine_and_terminal(OpenerSequence, "<SKIP NESTED RANGE OPENER>", opener_op_list), _get_state_machine_and_terminal(CloserSequence, "<SKIP NESTED RANGE OPENER>", closer_op_list) ]
def create_DropOut(self, SM_State): if SM_State.is_acceptance(): incidence_id = self.__incidence_id_of_bipd return OpList( Op.QuexDebug( 'pattern %i: backward input position detected\\n' % incidence_id), Op.Increment(E_R.InputP), Op.GotoDoorId(DoorID.bipd_return(incidence_id))) else: return OpList(Op.QuexAssertNoPassage())
def _get_state_machine_vs_terminal_list(CloserPattern, OpenerPattern, DoorIdExit, dial_db): """Additionally to all characters, the loop shall walk along the 'closer'. If the closer matches, the range skipping exits. Characters need to be counted properly. RETURNS: [0] list(state machine, terminal) [1] incidence id of auxiliary terminal that goto-s to the loop entry. The auxiliary terminal is necessary since the DoorID of the loop entry cannot be known beforehand. """ # DoorID of loop entry cannot be known beforehand. # => generate an intermediate door_id from where the loop is entered. iid_aux_reentry = dial.new_incidence_id() door_id_aux_reentry = dial.DoorID.incidence(iid_aux_reentry, dial_db) # Opener Pattern Reaction opener_op_list = [ Op.Increment(E_R.Counter), Op.GotoDoorId(door_id_aux_reentry) ] # Closer Pattern Reaction closer_op_list = [ Op.Decrement(E_R.Counter), Op.GotoDoorIdIfCounterEqualZero(DoorIdExit), Op.GotoDoorId(door_id_aux_reentry) ] def sm_terminal_pair(Pattern, Name, OpList, dial_db): sm = Pattern.get_cloned_sm(StateMachineId=dial.new_incidence_id()) terminal = loop.MiniTerminal(Lng.COMMAND_LIST(OpList, dial_db), Name, sm.get_id()) return sm, terminal smt_list = [ sm_terminal_pair(OpenerPattern, "<SKIP NESTED RANGE OPENER>", opener_op_list, dial_db), sm_terminal_pair(CloserPattern, "<SKIP NESTED RANGE CLOSER>", closer_op_list, dial_db) ] return smt_list, iid_aux_reentry
analyzer.state_db[state_index_list[1]] def set_recursive_command_list(State, TheOpList): State.entry.enter_OpList(State.index, State.index, OpList.from_iterable(TheOpList)) State.entry.categorize(State.index) 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.Increment(E_R.InputP) ]) set_recursive_command_list(b, [ Op.Increment(E_R.InputP) ]) 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.Increment(E_R.InputP) ]) set_recursive_command_list(b, [ Op.Decrement(E_R.InputP) ]) 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.Increment(E_R.InputP) ]) set_recursive_command_list(b, [ Op.Increment(E_R.InputP) ]) test(analyzer, a, b)