Beispiel #1
0
def _get_appendix_analyzers(LoopMap, EventHandler, AppendixSmList,
                            IidLoopAfterAppendixDropOut):
    """Parallel state machines are mounted to the loop by cutting the first
    transition and implementing it in the loop. Upon acceptance of the first
    character the according tail (appendix) of the state machine is entered.

    RETURNS: [0] List of appendix state machines in terms of analyzers.
             [1] Appendix terminals.
    """
    # Codec Transformation
    appendix_sm_list = []
    for sm in AppendixSmList:
        if not sm.get_init_state().has_transitions(): continue
        verdict_f, sm = Setup.buffer_codec.do_state_machine(sm, beautifier)
        appendix_sm_list.append(sm)

    # Appendix Sm Drop Out => Restore position of last loop character.
    # (i)  Couple terminal stored input position in 'CharacterBeginP'.
    # (ii) Terminal 'LoopAfterAppendixDropOut' restores that position.
    # Accepting on the initial state of an appendix state machine ensures
    # that any drop-out ends in this restore terminal.
    for init_state in (sm.get_init_state() for sm in appendix_sm_list):
        init_state.set_acceptance()
        init_state.mark_acceptance_id(IidLoopAfterAppendixDropOut)

    # Appendix Analyzer List
    return [
        analyzer_generator.do(sm,
                              EventHandler.engine_type,
                              EventHandler.reload_state_extern,
                              OnBeforeReload=EventHandler.on_before_reload,
                              OnAfterReload=EventHandler.on_after_reload)
        for sm in appendix_sm_list
    ]
Beispiel #2
0
    def __code_pre_context_state_machine(self):
        LanguageDB = self.language_db

        if len(self.pre_context_sm_list) == 0: return []

        assert len(self.pre_context_sm.get_orphaned_state_index_list()) == 0

        txt = []
        if Setup.comment_state_machine_f:
            LanguageDB.ML_COMMENT(txt, 
                                  "BEGIN: PRE-CONTEXT STATE MACHINE\n"             + \
                                  self.pre_context_sm.get_string(NormalizeF=False) + \
                                  "END: PRE-CONTEXT STATE MACHINE") 
            txt.append("\n") # For safety: New content may have to start in a newline, e.g. "#ifdef ..."

        analyzer = analyzer_generator.do(self.pre_context_sm, E_EngineTypes.BACKWARD_PRE_CONTEXT)
        msg      = state_machine_coder.do(analyzer)
        txt.extend(msg)

        txt.append("\n%s" % LanguageDB.LABEL(E_StateIndices.END_OF_PRE_CONTEXT_CHECK))
        # -- set the input stream back to the real current position.
        #    during backward lexing the analyzer went backwards, so it needs to be reset.
        txt.append("    %s\n" % LanguageDB.INPUT_P_TO_LEXEME_START())

        for sm_id in self.pre_context_sm_id_list:
            variable_db.require("pre_context_%i_fulfilled_f", Index = sm_id)

        return txt
Beispiel #3
0
def _get_analyzer_list_for_appendices(AppendixSmList, loop_config,
                                      CutSignalLexatomsF):
    """Parallel state machines are mounted to the loop by cutting the first
    transition and implementing it in the loop. Upon acceptance of the first
    character the according tail (appendix) of the state machine is entered.

    RETURNS: [0] List of appendix state machines in terms of analyzers.
             [1] Appendix terminals.
    """
    # Appendix Sm Drop Out => Restore position of last loop character.
    # (i)  Couple terminal stored input position in 'LoopRestartP'.
    # (ii) Terminal 'LoopAfterAppendixDropOut' restores that position.
    # Accepting on the initial state of an appendix state machine ensures
    # that any drop-out ends in this restore terminal.
    for init_state in (sm.get_init_state() for sm in AppendixSmList):
        if init_state.has_specific_acceptance_id(): continue
        init_state.set_acceptance()
        init_state.set_specific_acceptance_id(
            loop_config.iid_loop_after_appendix_drop_out)

    # Appendix FSM List
    return [
        analyzer_generator.do(
            sm,
            loop_config.engine_type,
            loop_config.reload_state_extern,
            OnBeforeReload=loop_config.events.on_before_reload_in_appendix,
            OnAfterReload=loop_config.events.on_after_reload_in_appendix,
            dial_db=loop_config.dial_db,
            CutF=CutSignalLexatomsF) for sm in AppendixSmList
    ]
Beispiel #4
0
def _get_appendix_analyzers(LoopMap, EventHandler, AppendixSmList, 
                            IidLoopAfterAppendixDropOut): 
    """Parallel state machines are mounted to the loop by cutting the first
    transition and implementing it in the loop. Upon acceptance of the first
    character the according tail (appendix) of the state machine is entered.

    RETURNS: [0] List of appendix state machines in terms of analyzers.
             [1] Appendix terminals.
    """
    # Codec Transformation
    appendix_sm_list = []
    for sm in AppendixSmList:
        if not sm.get_init_state().has_transitions(): continue
        verdict_f, sm = Setup.buffer_codec.do_state_machine(sm, beautifier) 
        appendix_sm_list.append(sm)

    # Appendix Sm Drop Out => Restore position of last loop character.
    # (i)  Couple terminal stored input position in 'CharacterBeginP'.
    # (ii) Terminal 'LoopAfterAppendixDropOut' restores that position.
    # Accepting on the initial state of an appendix state machine ensures
    # that any drop-out ends in this restore terminal.
    for init_state in (sm.get_init_state() for sm in appendix_sm_list):
        init_state.set_acceptance()
        init_state.mark_acceptance_id(IidLoopAfterAppendixDropOut)

    # Appendix Analyzer List
    return [
        analyzer_generator.do(sm, 
                              EventHandler.engine_type, 
                              EventHandler.reload_state_extern, 
                              OnBeforeReload = EventHandler.on_before_reload, 
                              OnAfterReload  = EventHandler.on_after_reload)
        for sm in appendix_sm_list
    ]
Beispiel #5
0
    def __code_pre_context_state_machine(self):
        LanguageDB = self.language_db

        if len(self.pre_context_sm_list) == 0: return []

        assert len(self.pre_context_sm.get_orphaned_state_index_list()) == 0

        txt = []
        if Setup.comment_state_machine_f:
            LanguageDB.ML_COMMENT(txt,
                                  "BEGIN: PRE-CONTEXT STATE MACHINE\n"             + \
                                  self.pre_context_sm.get_string(NormalizeF=False) + \
                                  "END: PRE-CONTEXT STATE MACHINE")
            txt.append(
                "\n"
            )  # For safety: New content may have to start in a newline, e.g. "#ifdef ..."

        analyzer = analyzer_generator.do(self.pre_context_sm,
                                         E_EngineTypes.BACKWARD_PRE_CONTEXT)
        msg = state_machine_coder.do(analyzer)
        txt.extend(msg)

        txt.append("\n%s" %
                   LanguageDB.LABEL(E_StateIndices.END_OF_PRE_CONTEXT_CHECK))
        # -- set the input stream back to the real current position.
        #    during backward lexing the analyzer went backwards, so it needs to be reset.
        txt.append("    %s\n" % LanguageDB.INPUT_P_TO_LEXEME_START())

        for sm_id in self.pre_context_sm_id_list:
            variable_db.require("pre_context_%i_fulfilled_f", Index=sm_id)

        return txt
Beispiel #6
0
def __do_state_machine(SmOrSmList, EngineType, dial_db, ReloadStateForward=None, ReverseF=False): 
    """Generates code for state machine 'sm' and the 'EngineType'.

    RETURNS: list of strings
    """
    assert type(SmOrSmList) == list or len(SmOrSmList.get_orphaned_state_index_list()) == 0

    # -- Analyze state machine --> optimized version
    analyzer = analyzer_generator.do(SmOrSmList, EngineType, 
                                     ReloadStateExtern = ReloadStateForward, 
                                     dial_db           = dial_db,
                                     ReverseF          = ReverseF)

    txt = []
    # -- [optional] comment state machine transitions 
    if Setup.comment_state_machine_f: 
        if type(SmOrSmList) != list: SmOrSmList = [ SmOrSmList ]
        for sm in SmOrSmList:
            Lng.COMMENT_STATE_MACHINE(txt, sm)

    # -- Generate code for analyzer
    txt.extend(
        do_analyzer(analyzer)
    )

    return txt, analyzer
Beispiel #7
0
    def __code_main_state_machine(self):
        assert len(self.sm.get_orphaned_state_index_list()) == 0

        LanguageDB = self.language_db 
        txt        = []

        # -- [optional] comment state machine transitions 
        if Setup.comment_state_machine_f:
            LanguageDB.ML_COMMENT(txt, 
                                  "BEGIN: STATE MACHINE\n"             + \
                                  self.sm.get_string(NormalizeF=False) + \
                                  "END: STATE MACHINE") 
            txt.append("\n") # For safety: New content may have to start in a newline, e.g. "#ifdef ..."

        # -- implement the state machine itself
        analyzer           = analyzer_generator.do(self.sm, E_EngineTypes.FORWARD)
        state_machine_code = state_machine_coder.do(analyzer)
        txt.extend(state_machine_code)

        lexeme_null_object_name = "QUEX_NAME(LexemeNullObject)"
        if Setup.external_lexeme_null_object != "":
            lexeme_null_object_name = Setup.external_lexeme_null_object

        # -- terminal states: execution of pattern actions  
        terminal_code = LanguageDB["$terminal-code"](self.state_machine_name,
                                                     self.action_db, 
                                                     self.on_failure_action, 
                                                     self.on_end_of_stream_action, 
                                                     self.pre_context_sm_id_list,
                                                     self.language_db, 
                                                     variable_db,
                                                     self.on_after_match, 
                                                     lexeme_null_object_name) 
        
        txt.extend(terminal_code)

        N = len(set(analyzer.position_register_map.values()))
        if len(analyzer.position_register_map) == 0:
            variable_db.require("position",          Initial = "(void*)0x0", Type = "void*")
            variable_db.require("PositionRegisterN", Initial = "(size_t)%i" % N)
        else:
            variable_db.require_array("position", ElementN = N,
                                      Initial  = "{ " + ("0, " * (N - 1) + "0") + "}")
            variable_db.require("PositionRegisterN", Initial = "(size_t)%i" % N)
    
        if analyzer.last_acceptance_variable_required():
            variable_db.require("last_acceptance")

        # -- reload definition (forward, backward, init state reload)
        code = LanguageDB.RELOAD()
        txt.extend(code)

        return txt
Beispiel #8
0
    def __code_main_state_machine(self):
        assert len(self.sm.get_orphaned_state_index_list()) == 0

        LanguageDB = self.language_db
        txt = []

        # -- [optional] comment state machine transitions
        if Setup.comment_state_machine_f:
            LanguageDB.ML_COMMENT(txt,
                                  "BEGIN: STATE MACHINE\n"             + \
                                  self.sm.get_string(NormalizeF=False) + \
                                  "END: STATE MACHINE")
            txt.append(
                "\n"
            )  # For safety: New content may have to start in a newline, e.g. "#ifdef ..."

        # -- implement the state machine itself
        analyzer = analyzer_generator.do(self.sm, E_EngineTypes.FORWARD)
        state_machine_code = state_machine_coder.do(analyzer)
        txt.extend(state_machine_code)

        lexeme_null_object_name = "QUEX_NAME(LexemeNullObject)"
        if Setup.external_lexeme_null_object != "":
            lexeme_null_object_name = Setup.external_lexeme_null_object

        # -- terminal states: execution of pattern actions
        terminal_code = LanguageDB["$terminal-code"](
            self.state_machine_name, self.action_db, self.on_failure_action,
            self.on_end_of_stream_action, self.pre_context_sm_id_list,
            self.language_db, variable_db, self.on_after_match,
            lexeme_null_object_name)

        txt.extend(terminal_code)

        N = len(set(analyzer.position_register_map.values()))
        if len(analyzer.position_register_map) == 0:
            variable_db.require("position", Initial="(void*)0x0", Type="void*")
            variable_db.require("PositionRegisterN", Initial="(size_t)%i" % N)
        else:
            variable_db.require_array("position",
                                      ElementN=N,
                                      Initial="{ " + ("0, " * (N - 1) + "0") +
                                      "}")
            variable_db.require("PositionRegisterN", Initial="(size_t)%i" % N)

        if analyzer.last_acceptance_variable_required():
            variable_db.require("last_acceptance")

        # -- reload definition (forward, backward, init state reload)
        code = LanguageDB.RELOAD()
        txt.extend(code)

        return txt
Beispiel #9
0
def _get_loop_analyzer(LoopMap, EventHandler):
    """Construct a state machine that triggers only on one character. Actions
    according the the triggered character are implemented using terminals which
    are entered upon acceptance.

            .------.
       ---->| Loop |
            |      |----> accept A                 (normal loop terminals)
            |      |----> accept B
            |      |----> accept C
            :      :         :
            |      |----> accept CoupleIncidenceA  (couple terminals towards
            |      |----> accept CoupleIncidenceB   appendix state machines)
            |      |----> accept CoupleIncidenceC    
            :______:         :
            | else |----> accept iid_loop_exit
            '------'

    RETURNS: [0] Loop analyzer (prepared state machine)
             [1] DoorID of loop entry
    """
    # Loop StateMachine
    sm            = StateMachine.from_IncidenceIdMap(
                        (lei.character_set, lei.incidence_id) for lei in LoopMap
                    )

    # Code Transformation
    verdict_f, sm = Setup.buffer_codec.do_state_machine(sm, beautifier)

    # Loop Analyzer
    analyzer = analyzer_generator.do(sm, 
                                     EventHandler.engine_type, 
                                     EventHandler.reload_state_extern, 
                                     OnBeforeReload = EventHandler.on_before_reload, 
                                     OnAfterReload  = EventHandler.on_after_reload,
                                     OnBeforeEntry  = EventHandler.on_loop_entry)

    # If reload state is generated 
    # => All other analyzers MUST use the same generated reload state.
    if EventHandler.reload_state_extern is None:
        EventHandler.reload_state_extern = analyzer.reload_state

    # Set the 'Re-Entry' Operations.
    entry       = analyzer.init_state().entry
    tid_reentry = entry.enter_OpList(analyzer.init_state_index, index.get(), 
                                     EventHandler.on_loop_reentry)
    entry.categorize(analyzer.init_state_index)

    return analyzer, entry.get(tid_reentry).door_id
Beispiel #10
0
def _get_loop_analyzer(LoopMap, EventHandler):
    """Construct a state machine that triggers only on one character. Actions
    according the the triggered character are implemented using terminals which
    are entered upon acceptance.

            .------.
       ---->| Loop |
            |      |----> accept A                 (normal loop terminals)
            |      |----> accept B
            |      |----> accept C
            :      :         :
            |      |----> accept CoupleIncidenceA  (couple terminals towards
            |      |----> accept CoupleIncidenceB   appendix state machines)
            |      |----> accept CoupleIncidenceC    
            :______:         :
            | else |----> accept iid_loop_exit
            '------'

    RETURNS: [0] Loop analyzer (prepared state machine)
             [1] DoorID of loop entry
    """
    # Loop StateMachine
    sm = StateMachine.from_IncidenceIdMap(
        (lei.character_set, lei.incidence_id) for lei in LoopMap)

    # Code Transformation
    verdict_f, sm = Setup.buffer_codec.do_state_machine(sm, beautifier)

    # Loop Analyzer
    analyzer = analyzer_generator.do(
        sm,
        EventHandler.engine_type,
        EventHandler.reload_state_extern,
        OnBeforeReload=EventHandler.on_before_reload,
        OnAfterReload=EventHandler.on_after_reload,
        OnBeforeEntry=EventHandler.on_loop_entry)

    # If reload state is generated
    # => All other analyzers MUST use the same generated reload state.
    if EventHandler.reload_state_extern is None:
        EventHandler.reload_state_extern = analyzer.reload_state

    # Set the 'Re-Entry' Operations.
    entry = analyzer.init_state().entry
    tid_reentry = entry.enter_OpList(analyzer.init_state_index, index.get(),
                                     EventHandler.on_loop_reentry)
    entry.categorize(analyzer.init_state_index)

    return analyzer, entry.get(tid_reentry).door_id
def get_transition_function(iid_map, Codec):
    if Codec == "UTF8": Setup.buffer_codec_prepare("utf8", Module=utf8_state_split)
    else:               Setup.buffer_codec_prepare("unicode") 

    cssm     = CharacterSetStateMachine(iid_map, MaintainLexemeF=False)
    analyzer = analyzer_generator.do(cssm.sm, engine.CHARACTER_COUNTER)
    tm_txt   = do_analyzer(analyzer)
    tm_txt   = Lng.GET_PLAIN_STRINGS(tm_txt)
    tm_txt.append("\n")
    label    = dial_db.get_label_by_door_id(DoorID.incidence(E_IncidenceIDs.MATCH_FAILURE))

    for character_set, iid in iid_map:
        tm_txt.append("%s return (int)%s;\n" % (Lng.LABEL(DoorID.incidence(iid)), iid))
    tm_txt.append("%s return (int)-1;\n" % Lng.LABEL(DoorID.drop_out(-1)))

    return "".join(tm_txt)
Beispiel #12
0
    def __code_backward_input_position_detection_core(self, SM):
        assert len(SM.get_orphaned_state_index_list()) == 0
        
        txt = []
        if Setup.comment_state_machine_f: 
            Setup.language_db.ML_COMMENT(txt, 
                                         "BEGIN: BACKWARD DETECTOR STATE MACHINE\n" + \
                                         SM.get_string(NormalizeF=False)            + \
                                         "\nEND: BACKWARD DETECTOR STATE MACHINE")
            txt.append("\n")

        analyzer      = analyzer_generator.do(SM, E_EngineTypes.BACKWARD_INPUT_POSITION)
        function_body = state_machine_coder.do(analyzer)

        txt.extend(function_body)

        return txt
Beispiel #13
0
def _get_analyzer_for_loop(loop_sm, loop_config, CutSignalLexatomsF):
    """Construct a state machine that triggers only on one character. Actions
    according the the triggered character are implemented using terminals which
    are entered upon acceptance.

            .------.
       ---->| Loop |
            |      |----> accept A                 (normal loop terminals)
            |      |----> accept B
            |      |----> accept C
            :      :         :
            |      |----> accept CoupleIncidenceA  (couple terminals towards
            |      |----> accept CoupleIncidenceB   appendix state machines)
            |      |----> accept CoupleIncidenceC    
            :______:         :
            | else |----> accept iid_loop_exit
            '------'

    RETURNS: [0] Loop analyzer (prepared state machine)
             [1] DoorID of loop entry
    """

    # Loop FSM
    analyzer = analyzer_generator.do(
        loop_sm,
        loop_config.engine_type,
        loop_config.reload_state_extern,
        OnBeforeReload=loop_config.events.on_before_reload,
        OnAfterReload=loop_config.events.on_after_reload,
        OnBeforeEntry=loop_config.events.on_loop_entry,
        dial_db=loop_config.dial_db,
        OnReloadFailureDoorId=loop_config.door_id_on_reload_failure,
        CutF=CutSignalLexatomsF)

    # If reload state is generated
    # => All other analyzers MUST use the same generated reload state.
    if loop_config.reload_state_extern is None:
        loop_config.reload_state_extern = analyzer.reload_state

    # Set the 'Re-Entry' Operations.
    entry = analyzer.init_state().entry
    tid_reentry = entry.enter_OpList(analyzer.init_state_index, index.get(),
                                     loop_config.events.on_loop_reentry)
    entry.categorize(analyzer.init_state_index)

    return analyzer, entry.get(tid_reentry).door_id
def get_transition_function(iid_map, Codec):
    if Codec == "UTF8": Setup.buffer_codec_set(bc_factory.do("utf8"), 1)
    else:               Setup.buffer_codec_set(bc_factory.do("unicode"), -1)

    sm        = StateMachine.from_IncidenceIdMap(iid_map)
    dummy, sm = Setup.buffer_codec.do_state_machine(sm, beautifier)
    analyzer  = analyzer_generator.do(sm, engine.CHARACTER_COUNTER)
    tm_txt    = do_analyzer(analyzer)
    tm_txt    = Lng.GET_PLAIN_STRINGS(tm_txt)
    tm_txt.append("\n")
    #label   = dial_db.get_label_by_door_id(DoorID.incidence(E_IncidenceIDs.MATCH_FAILURE))

    for character_set, iid in iid_map:
        tm_txt.append("%s return (int)%s;\n" % (Lng.LABEL(DoorID.incidence(iid)), iid))
    tm_txt.append("%s return (int)-1;\n" % Lng.LABEL(DoorID.drop_out(-1)))

    return "".join(tm_txt)
Beispiel #15
0
    def __code_backward_input_position_detection_core(self, SM):
        assert len(SM.get_orphaned_state_index_list()) == 0

        txt = []
        if Setup.comment_state_machine_f:
            Setup.language_db.ML_COMMENT(txt,
                                         "BEGIN: BACKWARD DETECTOR STATE MACHINE\n" + \
                                         SM.get_string(NormalizeF=False)            + \
                                         "\nEND: BACKWARD DETECTOR STATE MACHINE")
            txt.append("\n")

        analyzer = analyzer_generator.do(SM,
                                         E_EngineTypes.BACKWARD_INPUT_POSITION)
        function_body = state_machine_coder.do(analyzer)

        txt.extend(function_body)

        return txt
Beispiel #16
0
def get_transition_function(iid_map, Codec):
    if Codec == "UTF8": Setup.buffer_codec_set(bc_factory.do("utf8"), 1)
    else: Setup.buffer_codec_set(bc_factory.do("unicode"), -1)

    sm = StateMachine.from_IncidenceIdMap(iid_map)
    dummy, sm = Setup.buffer_codec.do_state_machine(sm, beautifier)
    analyzer = analyzer_generator.do(sm, engine.CHARACTER_COUNTER)
    tm_txt = do_analyzer(analyzer)
    tm_txt = Lng.GET_PLAIN_STRINGS(tm_txt)
    tm_txt.append("\n")
    #label   = dial_db.get_label_by_door_id(DoorID.incidence(E_IncidenceIDs.MATCH_FAILURE))

    for character_set, iid in iid_map:
        tm_txt.append("%s return (int)%s;\n" %
                      (Lng.LABEL(DoorID.incidence(iid)), iid))
    tm_txt.append("%s return (int)-1;\n" % Lng.LABEL(DoorID.drop_out(-1)))

    return "".join(tm_txt)
Beispiel #17
0
def do_state_machine(sm, EngineType):
    """Generates code for state machine 'sm' and the 'EngineType'.

    RETURNS: list of strings
    """
    assert len(sm.get_orphaned_state_index_list()) == 0

    txt = []
    # -- [optional] comment state machine transitions
    if Setup.comment_state_machine_f:
        Lng.COMMENT_STATE_MACHINE(txt, sm)

    # -- Analyze state machine --> optimized version
    analyzer = analyzer_generator.do(sm, EngineType)

    # -- Generate code for analyzer
    txt.extend(do_analyzer(analyzer))

    return txt, analyzer
def get_transition_function(iid_map, Codec):
    if Codec == "UTF8":
        Setup.buffer_codec_prepare("utf8", Module=utf8_state_split)
    else:
        Setup.buffer_codec_prepare("unicode")

    cssm = CharacterSetStateMachine(iid_map, MaintainLexemeF=False)
    analyzer = analyzer_generator.do(cssm.sm, engine.CHARACTER_COUNTER)
    tm_txt = do_analyzer(analyzer)
    tm_txt = Lng.GET_PLAIN_STRINGS(tm_txt)
    tm_txt.append("\n")
    label = dial_db.get_label_by_door_id(
        DoorID.incidence(E_IncidenceIDs.MATCH_FAILURE))

    for character_set, iid in iid_map:
        tm_txt.append("%s return (int)%s;\n" %
                      (Lng.LABEL(DoorID.incidence(iid)), iid))
    tm_txt.append("%s return (int)-1;\n" % Lng.LABEL(DoorID.drop_out(-1)))

    return "".join(tm_txt)
Beispiel #19
0
def do_state_machine(sm, EngineType): 
    """Generates code for state machine 'sm' and the 'EngineType'.

    RETURNS: list of strings
    """
    assert len(sm.get_orphaned_state_index_list()) == 0

    txt = []
    # -- [optional] comment state machine transitions 
    if Setup.comment_state_machine_f: 
        Lng.COMMENT_STATE_MACHINE(txt, sm)

    # -- Analyze state machine --> optimized version
    analyzer = analyzer_generator.do(sm, EngineType)

    # -- Generate code for analyzer
    txt.extend(
        do_analyzer(analyzer)
    )

    return txt, analyzer
def get_transition_function(iid_map, Codec):
    global dial_db
    if Codec == "UTF8": Setup.buffer_setup("uint8_t", 1, "utf8")
    else: Setup.buffer_setup("uint32_t", 4, "none")

    Setup.bad_lexatom_detection_f = False
    sm = DFA.from_IncidenceIdMap(iid_map)
    analyzer = analyzer_generator.do(sm,
                                     engine.CHARACTER_COUNTER,
                                     dial_db=dial_db,
                                     CutF=False)
    tm_txt = do_analyzer(analyzer)
    tm_txt = Lng.GET_PLAIN_STRINGS(tm_txt, dial_db=dial_db)
    tm_txt.append("\n")
    #label   = dial_db.get_label_by_door_id(DoorID.incidence(E_IncidenceIDs.MATCH_FAILURE))

    for character_set, iid in iid_map:
        tm_txt.append("%s return (int)%s;\n" %
                      (Lng.LABEL(DoorID.incidence(iid, dial_db)), iid))
    tm_txt.append("%s return (int)-1;\n" %
                  Lng.LABEL(DoorID.drop_out(-1, dial_db)))

    return "".join(tm_txt)
Beispiel #21
0
def do(CcFactory,
       AfterBeyond,
       LexemeEndCheckF=False,
       EngineType=None,
       ReloadStateExtern=None,
       LexemeMaintainedF=False,
       ParallelSmTerminalPairList=None):
    """Generates a (pseudo-one-state) state machine with the properties:
        
               Buffer Limit Code --> Reload
               Loop Character    --> Loop Entry
               Else              --> Exit Loop

    NOTE: This function does NOT code the FAILURE terminal. The caller needs to 
          do this if required.

    Generate code to iterate over the input stream until

           -- A character occurs not in CharacterSet, or
           -- [optional] the 'LexemeEnd' is reached.

    That is, simplified:
                             input in Set
                             .--<--.
                            |      |  LexemeEnd
                            |      +----->------> (Exit)
                          .----.   |
               --------->( Loop )--+----->------> Exit
                          '----'       input 
                                     not in Set
        
    At the end of the iteration, the 'input_p' points to (the begin of) the
    first character which is not in CharacterSet (or the LexemeEnd).

            [i][i][i]..................[i][i][X][.... 
                                             |
                                          input_p
            
    During the 'loop' possible line/column count commands may be applied. To
    achieve the iteration, a simplified pattern matching engine is implemented:

              transition
              map
              .------.  
              |  i0  |----------> Terminal0: CommandList0   
              +------+
              |  i1  |----------> Terminal1: CommandList1   
              +------+
              |  X2  |----------> Terminal Beyond: input_p--; goto TerminalExit;
              +------+
              |  i2  |----------> Terminal2: CommandList2
              +------+
    """
    assert EngineType is not None
    # NOT: assert (not EngineType.subject_to_reload()) or ReloadStateExtern is None
    # This would mean, that the user has to make these kinds of decisions. But,
    # we are easily able to ignore meaningless ReloadStateExtern objects.

    # (*) Construct State Machine and Terminals _______________________________
    #
    parallel_sm_list = None
    if ParallelSmTerminalPairList is not None:
        parallel_sm_list = [sm for sm, terminal in ParallelSmTerminalPairList]

    CsSm = CharacterSetStateMachine.from_CountCmdFactory(
        CcFactory, LexemeMaintainedF, ParallelSmList=parallel_sm_list)

    analyzer = analyzer_generator.do(
        CsSm.sm,
        EngineType,
        ReloadStateExtern,
        OnBeforeReload=CommandList.from_iterable(CsSm.on_before_reload),
        OnAfterReload=CommandList.from_iterable(CsSm.on_after_reload))

    # -- The terminals
    #
    door_id_loop = _prepare_entry_and_reentry(analyzer, CsSm.on_begin,
                                              CsSm.on_step)

    def get_LexemeEndCheck_appendix(ccfactory, CC_Type):
        if not LexemeEndCheckF:
            return [GotoDoorId(door_id_loop)]
        #
        #       .---------------.        ,----------.   no
        #   --->| Count Command |-------< LexemeEnd? >------> DoorIdOk
        #       '---------------'        '----+-----'
        #                                     | yes
        #                              .---------------.
        #                              |  Lexeme End   |
        #                              | Count Command |----> DoorIdOnLexemeEnd
        #                              '---------------'
        #
        elif ccfactory.requires_reference_p(
        ) and CC_Type == E_CharacterCountType.COLUMN:
            return [
                GotoDoorIdIfInputPNotEqualPointer(door_id_loop, E_R.LexemeEnd),
                ColumnCountReferencePDeltaAdd(
                    E_R.InputP, ccfactory.column_count_per_chunk, False),
            ] + AfterBeyond
        else:
            return [
                GotoDoorIdIfInputPNotEqualPointer(door_id_loop, E_R.LexemeEnd),
            ] + AfterBeyond

    terminal_list = CcFactory.get_terminal_list(CsSm.on_end + AfterBeyond,
                                                CsSm.incidence_id_beyond,
                                                get_LexemeEndCheck_appendix)
    if ParallelSmTerminalPairList is not None:
        terminal_list.extend(terminal
                             for sm, terminal in ParallelSmTerminalPairList)

    # (*) Generate Code _______________________________________________________
    txt = _get_source_code(CcFactory, analyzer, terminal_list)

    return txt, DoorID.incidence(CsSm.incidence_id_beyond)
Beispiel #22
0
def do(CcFactory, AfterBeyond, LexemeEndCheckF=False, EngineType=None, ReloadStateExtern=None, LexemeMaintainedF=False,
       ParallelSmTerminalPairList=None):
    """Generates a (pseudo-one-state) state machine with the properties:
        
               Buffer Limit Code --> Reload
               Loop Character    --> Loop Entry
               Else              --> Exit Loop

    NOTE: This function does NOT code the FAILURE terminal. The caller needs to 
          do this if required.

    Generate code to iterate over the input stream until

           -- A character occurs not in CharacterSet, or
           -- [optional] the 'LexemeEnd' is reached.

    That is, simplified:
                             input in Set
                             .--<--.
                            |      |  LexemeEnd
                            |      +----->------> (Exit)
                          .----.   |
               --------->( Loop )--+----->------> Exit
                          '----'       input 
                                     not in Set
        
    At the end of the iteration, the 'input_p' points to (the begin of) the
    first character which is not in CharacterSet (or the LexemeEnd).

            [i][i][i]..................[i][i][X][.... 
                                             |
                                          input_p
            
    During the 'loop' possible line/column count commands may be applied. To
    achieve the iteration, a simplified pattern matching engine is implemented:

              transition
              map
              .------.  
              |  i0  |----------> Terminal0: OpList0   
              +------+
              |  i1  |----------> Terminal1: OpList1   
              +------+
              |  X2  |----------> Terminal Beyond: input_p--; goto TerminalExit;
              +------+
              |  i2  |----------> Terminal2: OpList2
              +------+
    """
    assert EngineType is not None
    # NOT: assert (not EngineType.subject_to_reload()) or ReloadStateExtern is None
    # This would mean, that the user has to make these kinds of decisions. But, 
    # we are easily able to ignore meaningless ReloadStateExtern objects.

    # (*) Construct State Machine and Terminals _______________________________
    #
    parallel_sm_list = None
    if ParallelSmTerminalPairList is not None:
        parallel_sm_list = [ sm for sm, terminal in ParallelSmTerminalPairList ]

    CsSm = CharacterSetStateMachine.from_CountOpFactory(CcFactory, 
                                                         LexemeMaintainedF,
                                                         ParallelSmList=parallel_sm_list)

    analyzer = analyzer_generator.do(CsSm.sm, EngineType,
                                     ReloadStateExtern,
                                     OnBeforeReload = OpList.from_iterable(CsSm.on_before_reload), 
                                     OnAfterReload  = OpList.from_iterable(CsSm.on_after_reload))

    # -- The terminals 
    #
    door_id_loop = _prepare_entry_and_reentry(analyzer, CsSm.on_begin, CsSm.on_step) 

    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

    terminal_list = CcFactory.get_terminal_list(CsSm.on_end + AfterBeyond,
                                                CsSm.incidence_id_beyond,
                                                get_LexemeEndCheck_appendix)
    if ParallelSmTerminalPairList is not None:
        terminal_list.extend(
            terminal for sm, terminal in ParallelSmTerminalPairList
        )

    # (*) Generate Code _______________________________________________________
    txt = _get_source_code(CcFactory, analyzer, terminal_list)
    
    return txt, DoorID.incidence(CsSm.incidence_id_beyond)