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 _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
def __prepare_positioning_at_loop_begin_and_exit(ColumnNPerCodeUnit): """With encodings of dynamic character sizes (UTF8), the pointer to the first letter is stored in 'character_begin_p'. To reset the input pointer 'input_p = character_begin_p' is applied. """ if Setup.buffer_encoding.variable_character_sizes_f(): # 1 character == variable number of code units # => Begin of character must be stored upon entry # and restored upon exit. entry = [Op.Assign(E_R.LoopRestartP, E_R.InputP)] reentry = [Op.Assign(E_R.LoopRestartP, E_R.InputP)] exit = [Op.Assign(E_R.InputP, E_R.LoopRestartP)] else: # 1 character == 1 code unit # => reset to last character: 'input_p = input_p - 1' entry = [] reentry = [] exit = [Op.Decrement(E_R.InputP)] if ColumnNPerCodeUnit is not None: entry.append( Op.Assign(E_R.CountReferenceP, E_R.InputP, Condition="COLUMN")) return entry, reentry, exit
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)