Пример #1
0
 def get_LexemeEndCheck_appendix(ccfactory, CC_Type):
     if not LexemeEndCheckF:
         return [Op.GotoDoorId(door_id_loop)]
     #
     #       .---------------.        ,----------.   no
     #   --->| Count Op |-------< LexemeEnd? >------> DoorIdOk
     #       '---------------'        '----+-----'
     #                                     | yes
     #                              .---------------.
     #                              |  Lexeme End   |
     #                              | Count Op |----> DoorIdOnLexemeEnd
     #                              '---------------'
     #
     elif ccfactory.requires_reference_p(
     ) and CC_Type == E_CharacterCountType.COLUMN:
         return [
             Op.GotoDoorIdIfInputPNotEqualPointer(door_id_loop,
                                                  E_R.LexemeEnd),
             Op.ColumnCountReferencePDeltaAdd(
                 E_R.InputP, ccfactory.column_count_per_chunk, False),
         ] + AfterBeyond
     else:
         return [
             Op.GotoDoorIdIfInputPNotEqualPointer(door_id_loop,
                                                  E_R.LexemeEnd),
         ] + AfterBeyond
Пример #2
0
def _add_comment(psml, SmCommentOriginal, CounterDb):
    """On matching the comment state machine goto a terminal that does the 
    following:
    """
    if SmCommentOriginal is None: return

    comment_skip_iid = dial_db.new_incidence_id()

    # Disconnect from machines being used elsewhere.
    SmComment = SmCommentOriginal.clone()
    SmComment.set_id(comment_skip_iid)

    if SmComment.last_character_set().contains_only(ord('\n')):
        code = Lng.COMMAND_LIST([
            LineCountAdd(1),
            Op.AssignConstant(E_R.Column, 1),
        ])
    else:
        count_info = CountInfo.from_StateMachine(
            SmComment, CounterDb, CodecTrafoInfo=Setup.buffer_codec)
        code = [
            Lng.COMMAND(Op.Assign(E_R.ReferenceP, E_R.LexemeStartP)),
            CounterDb.do_CountInfo(count_info),
            Lng.COMMAND(Op.Assign(E_R.LexemeStartP, E_R.ReferenceP))
        ]

    code.append(Lng.GOTO(DoorID.incidence(E_IncidenceIDs.INDENTATION_HANDLER)))

    terminal = Terminal(CodeTerminal(code), "INDENTATION COMMENT")
    terminal.set_incidence_id(comment_skip_iid)

    psml.append((SmComment, terminal))
Пример #3
0
def _add_suppressed_newline(psml, SmSuppressedNewlineOriginal):
    """Add a pair (suppressed newline, terminal on suppressed newline to 'psml'.

    A suppresed newline is not like a newline--the next line is considered as 
    being appended to the current line. Nevertheless the line number needs to
    incremented, just the column number is not reset to 1. Then, it continues
    with indentation counting.
    """
    if SmSuppressedNewlineOriginal is None:
        return

    # Disconnect from machines being used elsewhere.
    SmSuppressedNewline = SmSuppressedNewlineOriginal.clone()
    SmSuppressedNewline.set_id(dial_db.new_incidence_id())

    # The parser MUST ensure that if there is a newline suppressor, there MUST
    # be a newline being defined.

    cl = [
        Op.LineCountAdd(1),
        Op.AssignConstant(E_R.Column, 1),
        Op.GotoDoorId(DoorID.incidence(E_IncidenceIDs.INDENTATION_HANDLER)),
    ]
    terminal = Terminal(CodeTerminal(Lng.COMMAND_LIST(cl)),
                        "<INDENTATION SUPPRESSED NEWLINE>")
    terminal.set_incidence_id(SmSuppressedNewline.get_id())

    psml.append((SmSuppressedNewline, terminal))
Пример #4
0
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)
    ]
Пример #5
0
    def __prepare_before_and_after_reload(self, OnBeforeReload, OnAfterReload):
        """The 'lexeme_start_p' restricts the amount of data which is loaded 
        into the buffer upon reload--if the lexeme needs to be maintained. If 
        the lexeme does not need to be maintained, then the whole buffer can 
        be refilled.
        
        For this, the 'lexeme_start_p' is set to the input pointer. 
        
        EXCEPTION: Variable character sizes. There, the 'lexeme_start_p' is used
        to mark the begin of the current letter. However, letters are short, so 
        the drawback is tiny.

        RETURNS: [0] on_before_reload
                 [1] on_after_reload
        """
        if Setup.buffer_codec.variable_character_sizes_f():
            if not self.maintain_lexeme_f:
                on_before_reload = [ Op.Assign(E_R.LexemeStartP, E_R.CharacterBeginP) ]
                on_after_reload  = [ Op.Assign(E_R.CharacterBeginP, E_R.LexemeStartP) ]
            else:
                assert False
                # Here, the character begin p needs to be adapted to what has been reloaded.
                on_before_reload = [ ] # LexemeBegin is enough.
                on_after_reload  = [ ]
        else:
            on_before_reload = [ Op.Assign(E_R.LexemeStartP, E_R.InputP) ] 
            on_after_reload  = [ ] # Op.Assign(E_R.InputP, E_R.LexemeStartP) ]

        self.on_before_reload = concatinate(on_before_reload,OnBeforeReload)
        self.on_after_reload  = concatinate(on_after_reload, OnAfterReload)
Пример #6
0
    def __prepare_positioning_before_and_after_reload(MaintainLexemeF):
        """The 'lexeme_start_p' restricts the amount of data which is loaded 
        into the buffer upon reload--if the lexeme needs to be maintained. If 
        the lexeme does not need to be maintained, then the whole buffer can 
        be refilled.
        
        For this, the 'lexeme_start_p' is set to the input pointer. 
        
        EXCEPTION: Variable character sizes. There, the 'lexeme_start_p' is used
        to mark the begin of the current letter. However, letters are short, so 
        the drawback is tiny.

        RETURNS: [0] on_before_reload
                 [1] on_after_reload
        """
        if Setup.buffer_codec.variable_character_sizes_f():
            if MaintainLexemeF:
                on_before_reload = [
                    Op.Assign(E_R.LexemeStartP, E_R.CharacterBeginP)
                ]
                on_after_reload = [
                    Op.Assign(E_R.CharacterBeginP, E_R.LexemeStartP)
                ]
            else:
                # Here, the character begin p needs to be adapted to what has been reloaded.
                on_before_reload = []  # Begin of lexeme is enough.
                on_after_reload = []
        else:
            on_before_reload = [Op.Assign(E_R.LexemeStartP, E_R.InputP)]
            on_after_reload = []  # Op.Assign(E_R.InputP, E_R.LexemeStartP) ]

        return on_before_reload, on_after_reload
Пример #7
0
def _add_newline(psml, SmNewlineOriginal):
    """Add a pair (newline state machine, terminal on newline) to 'psml'.

    When a newline occurs, the column count can be set to 1 and the line number
    is incremented. Then the indentation counting restarts.
    """
    assert SmNewlineOriginal is not None

    # Disconnect from machines being used elsewhere.
    SmNewline = SmNewlineOriginal.clone()
    SmNewline.set_id(dial_db.new_incidence_id())

    # The SmNewline has been used before in the main state machine with a
    # different incidence id. It is essential to clone!

    cl = [
        Op.LineCountAdd(1),
        Op.AssignConstant(E_R.Column, 1),
        Op.GotoDoorId(DoorID.incidence(E_IncidenceIDs.INDENTATION_HANDLER))
    ]
    terminal = Terminal(CodeTerminal(Lng.COMMAND_LIST(cl)),
                        "<INDENTATION NEWLINE>")
    terminal.set_incidence_id(SmNewline.get_id())

    psml.append((SmNewline, terminal))
Пример #8
0
 def __replace_Lazy_DoorIdLoop(self, cmd, DoorIdLoop):
     if cmd.id == E_Op.GotoDoorId:
         if cmd.content.door_id != self.Lazy_DoorIdLoop: return cmd
         return Op.GotoDoorId(DoorIdLoop)
     elif cmd.id == E_Op.GotoDoorIdIfInputPNotEqualPointer:
         if cmd.content.door_id != self.Lazy_DoorIdLoop: return cmd
         return Op.GotoDoorIdIfInputPNotEqualPointer(
             DoorIdLoop, cmd.content.pointer)
     else:
         return cmd
Пример #9
0
 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())
Пример #10
0
def _get_indentation_handler_terminal(ModeName, dial_db):
    code = Lng.COMMAND_LIST([
        Op.IndentationHandlerCall(ModeName),
        Op.GotoDoorId(DoorID.continue_without_on_after_match(dial_db))
    ], dial_db)
    incidence_id = dial.new_incidence_id()
    terminal = Terminal(CodeTerminal(code),
                        "<CALL INDENTATION HANDLER>",
                        incidence_id,
                        dial_db=dial_db)

    return DoorID.incidence(incidence_id, dial_db), terminal
Пример #11
0
 def _cmd_list_CA_LexemeEndCheck_GotoLoopEntry(self, CA):
     # Check Terminal: check against lexeme end before re-entering loop.
     cmd_list = [
         Op.GotoDoorIdIfInputPNotEqualPointer(self.Lazy_DoorIdLoop,
                                              E_R.LexemeEnd)
     ]
     if     self.column_number_per_code_unit is not None \
        and CA is not None and CA.cc_type == E_CharacterCountType.COLUMN:
         # With reference counting, no column counting while looping.
         # => Do it now, before leaving.
         cmd_list.append(
             Op.ColumnCountReferencePDeltaAdd(
                 E_R.InputP, self.column_number_per_code_unit, False))
     target_door_id = self.door_id_on_loop_exit_user_code
     return self._cmd_list_Frame(CA, cmd_list, target_door_id)
Пример #12
0
    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
Пример #13
0
    def _finalize_entry_OpLists(self):
        """If a state is entered from outside the path walker, then the 'state_key',
        respectively, the 'path_iterator' needs to be set. During the walk along
        a path, the 'path_iterator' is simply incremented--and this happens in the
        code generated for the path walker (later on).

        NOTE: Here, it must be ensured that the DoorID-s for entries from 
              outside remain the same! This way, any external transition map
              may remain the same.
        """
        # Entries along the path: PathIterator Increment
        #                         ... but this is handled better by the code generator.
        # Entries from outside:   PathIteratorSet
        for path_id, step_list in enumerate(self.__path_list):
            prev_state_index = None
            # Terminal is not element of path => consider only 'step_list[:-1]'
            for offset, step in enumerate(step_list[:-1]):
                # Inside transition:     'prev_state.index --> step.state_index'
                # All other transitions: '       *         --> step.state_index'
                # are transitions from states outside the path.
                state_key = offset
                # Update sets inside transition's 'door_id = None' and adds
                # the transition to 'transition_reassignment_candidate_list'.
                self.entry.action_db_update(From           = prev_state_index, 
                                            To             = step.state_index, 
                                            FromOutsideOp = Op.PathIteratorSet(self.index, path_id, state_key),
                                            FromInsideOp  = None)

                prev_state_index = step.state_index

        # Make sure, that the OpList-s on the paths are organized and
        # assigned with new DoorID-s. 
        assert len(self.entry.transition_reassignment_candidate_list) > 0
Пример #14
0
    def _terminal_goto_to_looper(self,
                                 analyzer_list,
                                 IncidenceId,
                                 Name,
                                 required_register_set,
                                 Pattern=None):
        """Generate terminal that jumps to a 'looper'.
        """
        door_id = DoorID.state_machine_entry(analyzer_list[0].state_machine_id,
                                             self.terminal_factory.dial_db)
        goto_op = Op.GotoDoorId(door_id)
        goto_code = [Lng.COMMAND(goto_op, self.terminal_factory.dial_db)]

        if Pattern is None:
            return Terminal(CodeTerminal(goto_code),
                            Name,
                            IncidenceId,
                            RequiredRegisterSet=required_register_set,
                            dial_db=self.terminal_factory.dial_db)
        else:
            return self.terminal_factory.do_plain(
                CodeTerminal(goto_code),
                Pattern,
                Name,
                RequiredRegisterSet=required_register_set)
Пример #15
0
    def _finalize_configure_global_drop_out(self, CompressionType, TheAnalyzer):
        """Upon 'drop-out', or when the reload fails the MegaState's drop-out
        section is entered. Then, it must be routed to the represented state
        based upon the state key. The routing command is setup in the MegaState-s
        drop-out. That is,
                        
                        Global Drop-Out
                       .--------------------------------- - -  -
                     .---------------.       on state-key
        drop-out --->| MegaState's   |       .---.
                     | DropOut-Door  |------>| 0 |-----> Drop-out of state[0]
                     '---------------'       | 1 |-----> Drop-out of state[1]
                       |                     | : |
                       :                     '---'
                       '--------------------------------- - -  -

        The Op, which does that is the RouterOnStateKey. It contains the 
        'StateKeyRegister' which tells the code generator which state key to
        take as a basis for routing.
        """
        if not self.transition_map.has_drop_out():
            return

        cmd = Op.RouterOnStateKey(CompressionType, self.index,
                               self.ski_db.iterable_state_key_state_index_pairs(),
                               lambda state_index: TheAnalyzer.drop_out_DoorID(state_index))
        TheAnalyzer.drop_out.entry.enter_OpList(E_StateIndices.DROP_OUT, self.index, 
                                                     OpList(cmd))
        TheAnalyzer.drop_out.entry.categorize(E_StateIndices.DROP_OUT)
Пример #16
0
    def add_state(self, StateIndex, OnSuccessDoorId, OnFailureDoorId, BeforeReload=None):
        """Adds a state from where the reload state is entered. When reload is
        done it jumps to 'OnFailureDoorId' if the reload failed and to 'OnSuccessDoorId'
        if the reload succeeded.

        RETURNS: DoorID into the reload state. Jump to this DoorID in order
                 to trigger the reload for the state given by 'StateIndex'.
        """
        assert BeforeReload is None or isinstance(BeforeReload, OpList) 
        # Before reload: prepare after reload, the jump back to the reloading state.
        before_cl = OpList(Op.PrepareAfterReload(OnSuccessDoorId, OnFailureDoorId))
        if BeforeReload is not None:
            # May be, add additional commands
            before_cl = before_cl.concatinate(BeforeReload)

        # No two transitions into the reload state have the same OpList!
        # No two transitions can have the same DoorID!
        # => it is safe to assign a new DoorID withouth .categorize()
        ta         = TransitionAction(before_cl)
        # Assign a DoorID (without categorization) knowing that no such entry
        # into this state existed before.
        ta.door_id = dial_db.new_door_id(self.index)

        assert not self.entry.has_transition(self.index, StateIndex) # Cannot be in there twice!
        self.entry.enter(self.index, StateIndex, ta)

        return ta.door_id
Пример #17
0
 def _cmd_list_Frame(self, TheCountAction, CmdList, DoorIdTarget):
     cmd_list = []
     if TheCountAction is not None:
         cmd_list.extend(
             TheCountAction.get_OpList(self.column_number_per_code_unit))
     cmd_list.extend(CmdList)
     cmd_list.append(Op.GotoDoorId(DoorIdTarget))
     return cmd_list
Пример #18
0
    def on_loop_after_appendix_drop_out(self, DoorIdLoop, ColumnNPerCodeUnit):
        # Upon drop-out, the input position is set to where the apendix
        # started. Then, the loop is re-entered.
        op_list = []

        if ColumnNPerCodeUnit is not None:
            op_list.append(
                Op.Assign(E_R.CountReferenceP,
                          E_R.LoopRestartP,
                          Condition="COLUMN"))

        op_list.extend([
            Op.Assign(E_R.InputP, E_R.LoopRestartP),
            Op.GotoDoorId(DoorIdLoop)
        ])

        return op_list
Пример #19
0
 def prepare(AppendixSm, OriginalIidDb):
     lcci = SmLineColumnCountInfo.from_DFA(CaMap, AppendixSm, False,
                                           Setup.buffer_encoding)
     cmd_list = self.get_count_code(lcci)
     target_door_id = DoorID.incidence(
         OriginalIidDb[AppendixSm.get_id()], self.dial_db)
     cmd_list.append(Op.GotoDoorId(target_door_id))
     return (AppendixSm.get_id(), cmd_list)
Пример #20
0
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
Пример #21
0
    def __prepare_positioning_at_loop_begin_and_exit():
        """With codecs of dynamic character sizes (UTF8), the pointer to the 
        first letter is stored in 'lexatom_begin_p'. To reset the input 
        pointer 'input_p = lexatom_begin_p' is applied.  
        """
        if not Setup.buffer_codec.variable_character_sizes_f():
            # 1 character == 1 code unit
            # => reset to last character: 'input_p = input_p - 1'
            on_loop_exit = []  # Op.Decrement(E_R.InputP) ]
            on_loop_reentry = []
        else:
            # 1 character == variable number of code units
            # => store begin of character in 'lexeme_start_p'
            # => reset to last character: 'input_p = lexeme_start_p'
            on_loop_exit = [Op.Assign(E_R.InputP, E_R.CharacterBeginP)]
            on_loop_reentry = [Op.Assign(E_R.CharacterBeginP, E_R.InputP)]

        return on_loop_reentry, on_loop_exit
Пример #22
0
 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)
Пример #23
0
    def __prepare(ColumnNPerChunk):
        """BEFORE RELOAD:
                                                           input_p
                                                           |
                [ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ]
                                            |
                                            reference_p
             
                     column_n += (input_p - reference_p) * C

              where C = ColumnNPerChunk

           AFTER RELOAD:

                 input_p
                 |
                [ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ]
                 |
                 reference_p
        """
        if ColumnNPerChunk is None:
            return [], [], [], []

        # When there is more than one chunk possibly involved, then it is
        # possible that reload happens in between one character. I such cases
        # the 'input_p' cannot be used as reference for delta-add. Here,
        # we must rely on the 'character begin_p'.
        if Setup.buffer_codec.variable_character_sizes_f():
            pointer = E_R.CharacterBeginP
        else:
            pointer = E_R.InputP

        on_begin = [Op.ColumnCountReferencePSet(pointer)]
        on_after_reload = [Op.ColumnCountReferencePSet(pointer)]
        on_end = [
            Op.ColumnCountReferencePDeltaAdd(pointer, ColumnNPerChunk, False)
        ]
        on_before_reload = [
            Op.ColumnCountReferencePDeltaAdd(pointer, ColumnNPerChunk, False)
        ]

        return on_begin, on_end, on_before_reload, on_after_reload
Пример #24
0
    def get_couple_terminal_cmd_list(self, CA, CombinedAppendixSm,
                                     OriginalIidDb):
        """CA:                 Count action for the character set of the loop 
                               entry.
           CombinedAppendixSm: (combined) appendix sm where to jump upon 
                               triggering of the character set.
           OriginalIidDb:      Appendix sm id --> original iid of the state machine
                                                  where it came from.

        RETURNS: [0] CmdList -- for loop count action and transition to appendix
                                state machine or entry into according terminal.
                 [1] True, if there is a transition to an appendix state machine
                     False, if not
                 
        """
        transition_to_appendix_f = CombinedAppendixSm.get_init_state(
        ).has_transitions()
        acceptance_id_set = CombinedAppendixSm.acceptance_id_set()
        combined_appendix_sm_id = CombinedAppendixSm.get_id()

        cmd_list = []
        if CA is not None:
            cmd_list.extend(CA.get_OpList(self.column_number_per_code_unit))

        if not transition_to_appendix_f:
            # NO appendix after first transition => jump to appendix terminal.
            assert len(acceptance_id_set) == 1
            iid_original = OriginalIidDb[acceptance_id_set.pop()]
            target_door_id = DoorID.incidence(iid_original, self.dial_db)
            transition_to_appendix_f = False
        else:
            # appendix after first transition. => jump to appendix state machine.
            self.__appendix_dfa_present_f = True
            cmd_list.extend([
                Op.Assign(E_R.LoopRestartP, E_R.InputP),
                Op.Assign(E_R.LexemeStartP, E_R.InputP)
            ])
            target_door_id = DoorID.state_machine_entry(
                combined_appendix_sm_id, self.dial_db)
        cmd_list.append(Op.GotoDoorId(target_door_id))
        return cmd_list, transition_to_appendix_f
Пример #25
0
    def get_count_code(self, LCCI):
        if LCCI is None: return []

        run_time_counter_required_f, \
        cmd_list                     = SmLineColumnCountInfo.get_OpList(LCCI, ModeName=self.mode_name)

        if run_time_counter_required_f:
            self.__run_time_counter_required_f = True
            # The content to be counted starts where the appendix started.
            # * Begin of counting at 'loop restart pointer'.
            # * Run-time counting can ONLY work, if the lexeme start pointer
            #   is at position of appendix begin.
            cmd_list[:0] = [Op.Assign(E_R.LexemeStartP, E_R.LoopRestartP)]

        if self.column_number_per_code_unit is not None:
            # If the reference counting is applied, the reference pointer
            # must be set right behind the last counted character.
            cmd_list.append(
                Op.Assign(E_R.CountReferenceP, E_R.InputP, Condition="COLUMN"))

        return cmd_list
Пример #26
0
def get_skipper(TheAnalyzer, OpenerSequence, CloserSequence, OnSkipRangeOpen,
                DoorIdAfter, CounterDb):
    """
                                    .---<---+----------<------+------------------.
                                    |       |                 |                  |
                                    |       | not             | open_n += 1      |  
                                  .------.  | Closer[0]       |                  |
       -------------------------->| Loop +--'                 |                  |
                                  |      |                    | yes              | 
                                  |      |                    |                  |
                                  |      |          .-------------.              |
                                  |      +----->----| Opener[1-N] |              |
                                  |      |          |      ?      |              |
                                  |      |          '-------------'              |
                                  |      |                                       | open_n > 0
                                  |      |          .-------------.              | 
                                  |      +----->----| Closer[1-N] |--------------+------> RESTART
                                  |      |          |      ?      | open_n -= 1    else
                                  |      |          '-------------'             
                                  |      |                             
                                  |  BLC +-->-.  
                              .->-|      |     \                 Reload State 
            .-DoorID(S, 1)--./    '------'      \            .------------------.
         .--| after_reload  |                    \          .---------------.   |
         |  '---------------'                     '---------| before_reload |   |
         |                                                  '---------------'   |
         '---------------------------------------------------|                  |
                                                     success '------------------'     
                                                                     | failure      
                                                                     |            
                                                              .---------------.       
                                                              | SkipRangeOpen |       
                                                              '---------------'                                                                   

    """
    psml = _get_state_machine_vs_terminal_list(CloserSequence, OpenerSequence,
                                               CounterDb, DoorIdAfter)
    count_op_factory = CountInfoMap.from_LineColumnCount(
        CounterDb, NumberSet_All(), Lng.INPUT_P())
    result,          \
    door_id_beyond   = loop.do(count_op_factory,
                               OnLoopExit        = [ Op.GotoDoorId(DoorIdAfter) ],
                               LexemeEndCheckF   = False,
                               LexemeMaintainedF = False,
                               EngineType        = engine.FORWARD,
                               ReloadStateExtern = TheAnalyzer.reload_state,
                               ParallelSmTerminalPairList = psml)

    counter_variable = Lng.REGISTER_NAME(E_R.Counter)
    variable_db.require(counter_variable)
    result[0:0] = "%s = 0;\n" % counter_variable
    return result
Пример #27
0
    def _prepare_skip_character_set(self, MHI, Loopers, CaMap, ReloadState):
        """MHI = Mode hierarchie index."""
        if Loopers.skip is None: return [], [], []

        skipped_character_set, \
        pattern_str,           \
        aux_source_reference   = Loopers.combined_skip(CaMap)

        new_analyzer_list,        \
        new_terminal_list,    \
        loop_map,             \
        required_register_set = skip_character_set.do(self.terminal_factory.mode_name,
                                                      CaMap, skipped_character_set,
                                                      ReloadState,
                                                      self.terminal_factory.dial_db)

        self.required_register_set.update(required_register_set)

        extra_terminal_list = [
            self._terminal_goto_to_looper(new_analyzer_list,
                                          E_IncidenceIDs.SKIP, "<skip>",
                                          required_register_set)
        ]
        extra_terminal_list.extend(t for t in new_terminal_list)

        # Any skipped character must enter the skipper entry.
        goto_code = [
            Op.GotoDoorId(
                DoorID.incidence(E_IncidenceIDs.SKIP,
                                 self.terminal_factory.dial_db))
        ]
        new_ppt_list = []
        for lei in loop_map:
            new_incidence_id = dial.new_incidence_id()
            pattern = Pattern.from_character_set(lei.character_set,
                                                 new_incidence_id,
                                                 PatternString="<skip>",
                                                 Sr=aux_source_reference)
            # There is no reference pointer => Add directly
            count_code = lei.aux_count_action.get_OpList(None)
            code = Lng.COMMAND_LIST(count_code + goto_code,
                                    self.terminal_factory.dial_db)
            terminal = Terminal(CodeTerminal(code),
                                "ENTER SKIP:",
                                new_incidence_id,
                                dial_db=self.terminal_factory.dial_db)

            new_ppt_list.append(
                PPT(PatternPriority(MHI, new_incidence_id), pattern, terminal))

        return new_ppt_list, new_analyzer_list, extra_terminal_list
Пример #28
0
    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
Пример #29
0
 def add_StoreInputPosition(self, StateIndex, FromStateIndex, AccConditionSet, PositionRegister, Offset):
     """Add 'store input position' to specific door. See 'SeStoreInputPosition'
        comment for the reason why we do not store pre-context-id.
     """
     command_list = self.__db[TransitionID(StateIndex, FromStateIndex, 0)].command_list
     cmd          = Op.StoreInputPosition(AccConditionSet, PositionRegister, Offset)
     # Make sure it is the first!
     command_list.insert(0, cmd)
     # Never store twice in the same position register! 
     # => Make sure, that there is no second of the same kind!
     i = len(command_list) - 1
     while i >= 1: # leave 'i=0' which has just been inserted!
         if command_list[i] == cmd:
             del command_list[i]
         i -= 1
Пример #30
0
    def get_loop_terminal_code(self, TheLoopMapEntry, DoorIdLoop,
                               DoorIdLoopExit):
        """RETURNS: A loop terminal. 

        A terminal: (i)    Counts,
                    (ii)   checks possibly for the lexeme end, and
                    (iii)a either re-enters the loop, or
                    (iii)b transits to an appendix state machine (couple terminal).
        """
        IncidenceId = TheLoopMapEntry.incidence_id
        AppendixSmId = TheLoopMapEntry.appendix_sm_id
        TheCountAction = TheLoopMapEntry.count_action

        code = []
        if TheCountAction is not None:
            code.extend(
                TheCountAction.get_OpList(self.column_number_per_code_unit))

        if AppendixSmId is not None:
            if not lei.appendix_sm_has_transitions_f:
                # If there is no appendix, directly goto to the terminal.
                code.extend([Op.GotoDoorId(DoorID.incidence_id(AppendixSmId))])
            else:
                assert not self.lexeme_end_check_f
                # Couple Terminal: transit to appendix state machine.
                code.extend([
                    Op.Assign(E_R.ReferenceP, E_R.InputP),
                    Op.GotoDoorId(DoorID.state_machine_entry(AppendixSmId))
                ])
        elif not self.lexeme_end_check_f:
            # Loop Terminal: directly re-enter loop.
            code.append(Op.GotoDoorId(DoorIdLoop))
        else:
            # Check Terminal: check against lexeme end before re-entering loop.
            code.append(
                Op.GotoDoorIdIfInputPNotEqualPointer(DoorIdLoop,
                                                     E_R.LexemeEnd))
            if     self.column_number_per_code_unit is not None \
               and TheCountAction is not None \
               and TheCountAction.cc_type == E_CharacterCountType.COLUMN:
                # With reference counting, no column counting while looping.
                # => Do it now, before leaving.
                code.append(
                    Op.ColumnCountReferencePDeltaAdd(
                        E_R.InputP, self.column_number_per_code_unit, False))
            code.append(Op.GotoDoorId(DoorIdLoopExit))

        return Terminal(CodeTerminal(Lng.COMMAND_LIST(code)),
                        "<LOOP TERMINAL %i>" % IncidenceId, IncidenceId)