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)
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
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))
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))
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)
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
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)
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 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 __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
def _command(self, CC_Type, Parameter): if self.column_count_per_chunk is None: if CC_Type == E_CharacterCountType.BAD: return [Op.GotoDoorId(self.door_id_on_bad_indentation)] elif CC_Type == E_CharacterCountType.COLUMN: return [ Op.ColumnCountAdd(Parameter), ] elif CC_Type == E_CharacterCountType.GRID: return [ Op.ColumnCountGridAdd(Parameter), ] elif CC_Type == E_CharacterCountType.LINE: return [ Op.LineCountAdd(Parameter), Op.AssignConstant(E_R.Column, 1), ] else: if CC_Type == E_CharacterCountType.BAD: return [ Op.ColumnCountReferencePDeltaAdd( E_R.InputP, self.column_count_per_chunk, False), Op.ColumnCountReferencePSet(E_R.InputP), Op.GotoDoorId(self.door_id_on_bad_indentation) ] elif CC_Type == E_CharacterCountType.COLUMN: return [] elif CC_Type == E_CharacterCountType.GRID: return [ Op.ColumnCountReferencePDeltaAdd( E_R.InputP, self.column_count_per_chunk, True), Op.ColumnCountGridAdd(Parameter), Op.ColumnCountReferencePSet(E_R.InputP) ] elif CC_Type == E_CharacterCountType.LINE: return [ Op.LineCountAdd(Parameter), Op.AssignConstant(E_R.Column, 1), Op.ColumnCountReferencePSet(E_R.InputP) ]
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
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
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
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
def get_skipper(TheAnalyzer, CloserSequence, CloserPattern, ModeName, OnSkipRangeOpen, DoorIdAfter, CounterDb): """ .---<---+----------<------+ | | | | | not | .------. | Closer[0] | ------------------------------>| Loop +--' | | | | no | | | | | .-------------. | +----->----| Closer[1-N] |------------> RESTART | | | ? | yes | | '-------------' | | | BLC +-->-. .->-| | \ Reload State .-DoorID(S, 1)--./ '------' \ .-----------------. .----| after_reload | \ .---------------. | | '---------------' '---------| before_reload | | | '---------------' | '-----------------------------------------------------| | success '------------------' | failure | .---------------. | SkipRangeOpen | '---------------' """ psml = _get_state_machine_vs_terminal_list(CloserSequence, CounterDb) count_op_factory = CountInfoMap.from_LineColumnCount( CounterDb, NumberSet_All(), Lng.INPUT_P()) result, \ door_id_beyond = loop.do(count_op_factory, OnLoopExit = [ Op.GotoDoorId(DoorID.continue_without_on_after_match()) ], LexemeEndCheckF = False, LexemeMaintainedF = False, EngineType = engine.FORWARD, ReloadStateExtern = TheAnalyzer.reload_state, ParallelSmTerminalPairList = psml) return result
def __init__(self, ColumnNPerCodeUnit, UserBeforeEntryOpList, UserOnLoopExitDoorId): # Counting Actions upon: loop entry/exit; before/after reload # on_loop_entry_count, \ on_loop_exit_count, \ on_before_reload_count, \ on_after_reload_count = self.__prepare_count_actions(ColumnNPerCodeUnit) # Input pointer positioning: loop entry/exit; before/after reload # on_loop_entry, \ on_loop_reentry_pos, \ on_loop_exit_pos = self.__prepare_positioning_at_loop_begin_and_exit(ColumnNPerCodeUnit) on_before_reload_pos, \ on_after_reload_pos = self.__prepare_positioning_before_and_after_reload() on_before_reload_pos_apx, \ on_after_reload_pos_apx = self.__prepare_positioning_before_and_after_reload(AppendixSmF=True) # _____________________________________________________________________ # if UserBeforeEntryOpList is None: UserBeforeEntryOpList = [] self.on_loop_entry = OpList.concatinate(on_loop_entry, on_loop_reentry_pos, on_loop_entry_count, UserBeforeEntryOpList) self.on_loop_reentry = OpList.from_iterable(on_loop_reentry_pos) self.on_loop_exit = OpList.concatinate( on_loop_exit_pos, on_loop_exit_count, [Op.GotoDoorId(UserOnLoopExitDoorId)]) self.on_before_reload = OpList.concatinate(on_before_reload_pos, on_before_reload_count) self.on_before_reload_in_appendix = OpList.from_iterable( on_before_reload_pos_apx) self.on_after_reload = OpList.concatinate(on_after_reload_pos, on_after_reload_count) self.on_after_reload_in_appendix = OpList.from_iterable( on_after_reload_pos_apx)
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
def create_DropOut(self, SM_State): return OpList(Op.GotoDoorId(DoorID.global_end_of_pre_context_check()))
"space": E_CharacterCountType.COLUMN, "grid": E_CharacterCountType.GRID, "newline": E_CharacterCountType.LINE, "begin(newline suppressor)": E_CharacterCountType.BEGIN_NEWLINE_SUPPRESSOR, "begin(newline)": E_CharacterCountType.BEGIN_NEWLINE, "begin(comment to newline)": E_CharacterCountType.BEGIN_COMMENT_TO_NEWLINE, "end(newline)": E_CharacterCountType.END_NEWLINE, "bad": E_CharacterCountType.BAD, "whitespace": E_CharacterCountType.WHITESPACE, } cc_type_name_db = dict((value, key) for key, value in cc_type_db.iteritems()) count_operation_db_without_reference = { E_CharacterCountType.BAD: lambda Parameter, Dummy=None: [Op.GotoDoorId(Parameter)], E_CharacterCountType.COLUMN: lambda Parameter, Dummy=None: [Op.ColumnCountAdd(Parameter)], E_CharacterCountType.GRID: lambda Parameter, Dummy=None: [Op.ColumnCountGridAdd(Parameter)], E_CharacterCountType.LINE: lambda Parameter, Dummy=None: [ Op.LineCountAdd(Parameter), Op.AssignConstant(E_R.Column, 1), ], E_CharacterCountType.LOOP_ENTRY: lambda Parameter, Dummy=None: [], E_CharacterCountType.LOOP_EXIT: lambda Parameter, Dummy=None: [], E_CharacterCountType.BEFORE_RELOAD: lambda Parameter, Dummy=None: [],
"grid": E_CharacterCountType.GRID, "newline": E_CharacterCountType.LINE, "bad": E_CharacterCountType.BAD, "whitespace": E_CharacterCountType.WHITESPACE, # Following are only webbed into the 'CA_Map' to detect overlaps: "begin(newline suppressor)": E_CharacterCountType.X_BEGIN_NEWLINE_SUPPRESSOR, "begin(newline)": E_CharacterCountType.X_BEGIN_NEWLINE, "begin(comment to newline)": E_CharacterCountType.X_BEGIN_COMMENT_TO_NEWLINE, "end(newline)": E_CharacterCountType.X_END_NEWLINE, } cc_type_name_db = dict((value, key) for key, value in cc_type_db.iteritems()) count_operation_db_without_reference = { E_CharacterCountType.BAD: lambda Parameter, Dummy=None, Dummy2=None: [ Op.GotoDoorId(Parameter) ], E_CharacterCountType.COLUMN: lambda Parameter, Dummy=None, Dummy2=None: [ Op.ColumnCountAdd(Parameter) ], E_CharacterCountType.GRID: lambda Parameter, Dummy=None, Dummy2=None: [ Op.ColumnCountGridAdd(Parameter) ], E_CharacterCountType.LINE: lambda Parameter, Dummy=None, Dummy2=None: [ Op.LineCountAdd(Parameter), Op.AssignConstant(E_R.Column, 1), ], E_CharacterCountType.LOOP_ENTRY: lambda Parameter, Dummy=None, Dummy2=None: [ ], E_CharacterCountType.LOOP_EXIT: lambda Parameter, Dummy=None, Dummy2=None: [ ],
def do(Data, TheAnalyzer): """________________________________________________________________________ Counting whitespace at the beginning of a line. .-----<----+----------<--------------+--<----. | | count | | count = 0 | | whitespace | | .---------. | | | --------->| +--' | | | | | | | | | | | | .------------. | | | +----->----| suppressor |----' | | | | + newline | | | COUNTER | '------------' | | | .---------. | | +----->----| newline |---------------' | | '---------' | | .----------------. | |----->----| on_indentation |---------> RESTART '---------' else '----------------' Generate an indentation counter. An indentation counter is entered upon the detection of a newline (which is not followed by a newline suppressor). Indentation Counter: indentation = 0 column = 0 | |<------------------------. .-------------. | | INDENTATION | indentation += count | COUNTER | column += count '-------------' | | | +-------- whitspace -->---' | Re-Enter Analyzer An indentation counter is a single state that iterates to itself as long as whitespace occurs. During that iteration the column counter is adapted. There are two types of adaption: -- 'normal' adaption by a fixed delta. This adaption happens upon normal space characters. -- 'grid' adaption. When a grid character occurs, the column number snaps to a value given by a grid size parameter. When a newline occurs the indentation counter exits and restarts the lexical analysis. If the newline is not followed by a newline suppressor the analyzer will immediately be back to the indentation counter state. ___________________________________________________________________________ """ counter_db = Data["counter_db"] isetup = Data["indentation_setup"] incidence_db = Data["incidence_db"] default_ih_f = Data["default_indentation_handler_f"] mode_name = Data["mode_name"] sm_suppressed_newline = Data["sm_suppressed_newline"] sm_newline = isetup.sm_newline.get() sm_comment = isetup.sm_comment.get() assert sm_suppressed_newline is None or sm_suppressed_newline.is_DFA_compliant( ) assert sm_newline is None or sm_newline.is_DFA_compliant() assert sm_comment is None or sm_comment.is_DFA_compliant() # -- 'on_indentation' == 'on_beyond': # A handler is called as soon as an indentation has been detected. after_beyond = [ Op.IndentationHandlerCall(default_ih_f, mode_name), Op.GotoDoorId(DoorID.continue_without_on_after_match()) ] # -- 'on_bad_indentation' is invoked if a character appeared that has been # explicitly disallowed to be used as indentation. bad_indentation_iid = dial_db.new_incidence_id() if Setup.buffer_based_analyzis_f: reload_state = None else: reload_state = TheAnalyzer.reload_state sm_terminal_list = _get_state_machine_vs_terminal_list( sm_suppressed_newline, isetup.sm_newline.get(), isetup.sm_comment.get(), counter_db) # 'whitespace' --> normal counting # 'bad' --> goto bad character indentation handler # else --> non-whitespace detected => handle indentation ccfactory = CountOpFactory.from_ParserDataIndentation( isetup, counter_db, Lng.INPUT_P(), DoorID.incidence(bad_indentation_iid)) # (*) Generate Code code, \ door_id_beyond = loop.do(ccfactory, AfterBeyond = after_beyond, EngineType = TheAnalyzer.engine_type, ReloadStateExtern = reload_state, LexemeMaintainedF = True, ParallelSmTerminalPairList = sm_terminal_list) _code_terminal_on_bad_indentation_character(code, isetup, mode_name, incidence_db, bad_indentation_iid) return code
def do(ModeName, CaMap, OpenerPattern, CloserPattern, DoorIdExit, ReloadState, dial_db): """ .---<---+----------<------+------------------. | | | | | | 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, \ iid_aux_reentry = _get_state_machine_vs_terminal_list(CloserPattern, OpenerPattern, DoorIdExit, dial_db) if ReloadState: engine_type = ReloadState.engine_type else: engine_type = None # The first opening pattern must have matched --> counter = 1 entry_op_list = OpList(Op.AssignConstant(E_R.Counter, 1)) analyzer_list, \ terminal_list, \ loop_map, \ door_id_loop, \ required_register_set, \ run_time_counter_f = loop.do(CaMap, BeforeEntryOpList = entry_op_list, OnLoopExitDoorId = DoorIdExit, EngineType = engine_type, ReloadStateExtern = ReloadState, ParallelSmTerminalPairList = psml, dial_db = dial_db, ModeName = ModeName) reentry_op_list = [Op.GotoDoorId(door_id_loop)] terminal_list.append( Terminal(CodeTerminal(Lng.COMMAND_LIST(reentry_op_list, dial_db)), Name="<SKIP NESTED RANGE REENTRY>", IncidenceId=iid_aux_reentry, dial_db=dial_db)) required_register_set.add(E_R.Counter) return analyzer_list, \ terminal_list, \ required_register_set, \ run_time_counter_f
def on_loop_after_appendix_drop_out(self, DoorIdLoop): # 'CharacterBeginP' has been assigned in the 'Couple Terminal'. # (see ".get_loop_terminal_code()"). return Lng.COMMAND_LIST( [Op.Assign(E_R.InputP, E_R.ReferenceP), Op.GotoDoorId(DoorIdLoop)])
def do(Data, TheAnalyzer): """Fast implementation of character set skipping machine. ________________________________________________________________________ As long as characters of a given character set appears it iterates: input in Set .--<---. | | .-------. | --------->( SKIPPER )--+----->------> RESTART '-------' input not in Set ___________________________________________________________________________ NOTE: The 'TerminalSkipRange' takes care that it transits immediately to the indentation handler, if it ends on 'newline'. This is not necessary for 'TerminalSkipCharacterSet'. Quex refuses to work on 'skip sets' when they match common lexemes with the indentation handler. ___________________________________________________________________________ Precisely, i.e. including counter and reload actions: START | | .----------------------------------------------. | |.-------------------------------------------. | | ||.----------------------------------------. | | | ||| | | | | ||| .-DoorID(S, a)--. transition | | | | || '-| gridstep(cn) | map | | | | || '---------------'\ .------. | | | | || .-DoorID(S, b)--. '->-| | | | | | |'---| ln += 1 |--->-| '\t' +-->-----' | | | | '---------------' | | | | | | .-DoorID(S, c)--. | ' ' +-->-------' | | '----| cn += 1 |--->-| | | | '---------------' | '\n' +-->---------' | | | .-DropOut ------. | .-DoorID(S, 0)--. | else +-->---------------| on_exit | '------>--| on_entry |--->-| | '---------------' '---------------' | BLC +-->-. .->-| | \ Reload State .-DoorID(S, 1)--./ '------' \ .-----------------. .----| after_reload | \ .---------------. | | '---------------' '---------| before_reload | | | '---------------' | '-----------------------------------------------------| | success '------------------' | failure | .---------------. | End of Stream | '---------------' NOTE: If dynamic character size codings, such as UTF8, are used as engine codecs, then the single state may actually be split into a real state machine of states. """ counter_db = Data["counter_db"] character_set = Data["character_set"] if Setup.buffer_based_analyzis_f: reload_state = None else: reload_state = TheAnalyzer.reload_state result, \ door_id_beyond = loop.do(CountOpFactory.from_ParserDataLineColumn(counter_db, character_set, Lng.INPUT_P()), AfterBeyond = [ Op.GotoDoorId(DoorID.continue_without_on_after_match()) ], LexemeEndCheckF = False, LexemeMaintainedF = False, EngineType = engine.FORWARD, ReloadStateExtern = reload_state) assert isinstance(result, list) return result