def do(txt, TheState, TheAnalyzer): specific = Handler(TheState) specific.debug_info_map_state_key_to_state_index(txt) # (*) Entry _______________________________________________________________ entry_coder.do(txt, TheState, TheAnalyzer) # (*) Access input character etc. _________________________________________ specific.framework(txt, TheState, TheAnalyzer) # (*) Transition Map ______________________________________________________ prepare_transition_map(TheState, TheAnalyzer, specific.state_key_str) transition_block.do(txt, TheState.transition_map, TheState.index, TheAnalyzer.engine_type, TheState.init_state_f, TheAnalyzer = TheAnalyzer) # (*) Drop Out ____________________________________________________________ drop_out_scheme_implementation(txt, TheState, TheAnalyzer, specific.state_key_str, specific.debug_drop_out_str) # (*) Request necessary variable definition _______________________________ specific.require_data(TheState, TheAnalyzer) specific.debug_info_undo_map_state_key_to_state_index(txt) return
def do(code, TheState, TheAnalyzer): global LanguageDB assert isinstance(TheState, AnalyzerState) assert isinstance(TheAnalyzer, Analyzer) LanguageDB = Setup.language_db txt = [] # (*) Entry _______________________________________________________________ if not TheState.init_state_forward_f: entry.do(txt, TheState, TheAnalyzer) else: # There is something special about the init state in forward direction: # It does not increment the input pointer initially. But when it is entered # from other states, is has to do so. Solution: Implement init state entry # as 'prologue' here (without increment) and epilogue (with increment) after # the state. txt.append(LanguageDB.LABEL_INIT_STATE_TRANSITION_BLOCK()) # (*) Access the triggering character _____________________________________ input_do(txt, TheState, TheAnalyzer) LanguageDB.STATE_DEBUG_INFO(txt, TheState) # (*) Transition Map ______________________________________________________ transition_block.do(txt, TheState.transition_map, TheState.index, TheState.engine_type, TheState.init_state_f, TheAnalyzer=TheAnalyzer) # (*) Drop Out ____________________________________________________________ drop_out.do(txt, TheState, TheAnalyzer) # ( ) Init state prologue (if necessary) if TheState.init_state_forward_f: init_state_forward_epilog(txt, TheState, TheAnalyzer) # (*) Cleaning Up _________________________________________________________ for i, x in enumerate(txt): assert not isinstance(x, list), repr(txt[i - 2:i + 2]) assert not x is None, txt[i - 2:i + 2] code.extend(txt)
def do(code, TheState, TheAnalyzer): global LanguageDB assert isinstance(TheState, AnalyzerState) assert isinstance(TheAnalyzer, Analyzer) LanguageDB = Setup.language_db txt = [] # (*) Entry _______________________________________________________________ if not TheState.init_state_forward_f: entry.do(txt, TheState, TheAnalyzer) else: # There is something special about the init state in forward direction: # It does not increment the input pointer initially. But when it is entered # from other states, is has to do so. Solution: Implement init state entry # as 'prologue' here (without increment) and epilogue (with increment) after # the state. txt.append(LanguageDB.LABEL_INIT_STATE_TRANSITION_BLOCK()) # (*) Access the triggering character _____________________________________ input_do(txt, TheState, TheAnalyzer) LanguageDB.STATE_DEBUG_INFO(txt, TheState) # (*) Transition Map ______________________________________________________ transition_block.do(txt, TheState.transition_map, TheState.index, TheState.engine_type, TheState.init_state_f, TheAnalyzer=TheAnalyzer) # (*) Drop Out ____________________________________________________________ drop_out.do(txt, TheState, TheAnalyzer) # ( ) Init state prologue (if necessary) if TheState.init_state_forward_f: init_state_forward_epilog(txt, TheState, TheAnalyzer) # (*) Cleaning Up _________________________________________________________ for i, x in enumerate(txt): assert not isinstance(x, list), repr(txt[i-2:i+2]) assert not x is None, txt[i-2:i+2] code.extend(txt)
def get_skipper(TriggerSet): """This function implements simple 'skipping' in the sense of passing by characters that belong to a given set of characters--the TriggerSet. """ global template_str assert TriggerSet.__class__.__name__ == "NumberSet" assert not TriggerSet.is_empty() LanguageDB = Setup.language_db skipper_index = sm_index.get() # Mini trigger map: [ trigger set ] --> loop start # That means: As long as characters of the trigger set appear, we go to the loop start. transition_map = TransitionMap( ) # (don't worry about 'drop-out-ranges' etc.) transition_map.add_transition(TriggerSet, skipper_index) # On buffer limit code, the skipper must transit to a dedicated reloader goto_loop_str = [ LanguageDB.INPUT_P_INCREMENT(), " goto _%s_LOOP;\n" % skipper_index ] trigger_map = transition_map.get_trigger_map() for i, info in enumerate(trigger_map): interval, target = info if target == E_StateIndices.DROP_OUT: continue trigger_map[i] = (interval, TextTransitionCode(goto_loop_str)) iteration_code = [] transition_block.do(iteration_code, trigger_map, skipper_index, E_EngineTypes.ELSE, GotoReload_Str="goto %s;" % get_label("$reload", skipper_index)) tmp = [] LanguageDB.COMMENT(tmp, "Skip any character in " + TriggerSet.get_utf8_string()) comment_str = "".join(tmp) # Line and column number counting prolog = __lc_counting_replacements(prolog_txt, TriggerSet) epilog = __lc_counting_replacements(epilog_txt, TriggerSet) prolog = blue_print(prolog, [ ["$$DELIMITER_COMMENT$$", comment_str], ["$$SKIPPER_INDEX$$", "%i" % skipper_index], ["$$INPUT_GET$$", LanguageDB.ACCESS_INPUT()], ]) epilog = blue_print( epilog, [ ["$$INPUT_P_INCREMENT$$", LanguageDB.INPUT_P_INCREMENT()], ["$$INPUT_P_DECREMENT$$", LanguageDB.INPUT_P_DECREMENT()], [ "$$IF_INPUT_EQUAL_DELIMITER_0$$", LanguageDB.IF_INPUT("==", "SkipDelimiter$$SKIPPER_INDEX$$[0]") ], ["$$ENDIF$$", LanguageDB.END_IF()], ["$$LOOP_REENTRANCE$$", LanguageDB.LABEL(skipper_index)], ["$$BUFFER_LIMIT_CODE$$", LanguageDB.BUFFER_LIMIT_CODE], ["$$RELOAD$$", get_label("$reload", skipper_index)], [ "$$DROP_OUT_DIRECT$$", get_label("$drop-out", skipper_index, U=True) ], ["$$SKIPPER_INDEX$$", "%i" % skipper_index], [ "$$LABEL_TERMINAL_EOF$$", "QUEX_LABEL(%i)" % get_address("$terminal-EOF", U=True) ], [ "$$LABEL_REF_AFTER_RELOAD$$", "QUEX_LABEL(%i)" % get_address("$skipper-reload", skipper_index, U=True) ], ["$$GOTO_TERMINAL_EOF$$", get_label("$terminal-EOF", U=True)], [ "$$LABEL_AFTER_RELOAD$$", get_label("$skipper-reload", skipper_index) ], # When things were skipped, no change to acceptance flags or modes has # happend. One can jump immediately to the start without re-entry preparation. ["$$GOTO_START$$", get_label("$start", U=True)], ["$$MARK_LEXEME_START$$", LanguageDB.LEXEME_START_SET()], ]) code = [prolog] code.extend(iteration_code) code.append(epilog) local_variable_db = {} variable_db.enter(local_variable_db, "reference_p", Condition="QUEX_OPTION_COLUMN_NUMBER_COUNTING") return code, local_variable_db
def do(Data): """The generated code is very similar to the 'skipper' code. It is to be executed as soon as a 'real' newline arrived. Then it skips whitespace until the next non-whitepace (also newline may trigger a 'stop'). Dependent on the setup the indentation is determined. """ IndentationSetup = Data["indentation_setup"] assert IndentationSetup.__class__.__name__ == "IndentationSetup" LanguageDB = Setup.language_db Mode = None if IndentationSetup.containing_mode_name() != "": Mode = blackboard.mode_db[IndentationSetup.containing_mode_name()] counter_index = sm_index.get() # Mini trigger map: [ trigger set ] --> loop start # That means: As long as characters of the trigger set appear, we go to the loop start. trigger_map = [] # If the indentation consists only of spaces, than it is 'uniform' ... if IndentationSetup.has_only_single_spaces(): # Count indentation/column at end of run; # simply: current position - reference_p character_set = IndentationSetup.space_db.values()[0] for interval in character_set.get().get_intervals(PromiseToTreatWellF=True): trigger_map.append([interval, counter_index]) # Reference Pointer: Define Variable, Initialize, determine how to subtact. end_procedure = \ " me->counter._indentation = (size_t)(QUEX_NAME(Buffer_tell_memory_adr)(&me->buffer) - reference_p);\n" else: # Count the indentation/column during the 'run' # Add the space counters for count, character_set in IndentationSetup.space_db.items(): for interval in character_set.get().get_intervals(PromiseToTreatWellF=True): trigger_map.append([interval, IndentationCounter("space", count, counter_index)]) # Add the grid counters for count, character_set in IndentationSetup.grid_db.items(): for interval in character_set.get().get_intervals(PromiseToTreatWellF=True): trigger_map.append([interval, IndentationCounter("grid", count, counter_index)]) # Reference Pointer: Not required. # No subtraction 'current_position - reference_p'. # (however, we pass 'reference_p' to indentation handler) end_procedure = "" # Bad character detection if IndentationSetup.bad_character_set.get().is_empty() == False: for interval in IndentationSetup.bad_character_set.get().get_intervals(PromiseToTreatWellF=True): trigger_map.append([interval, IndentationCounter("bad", None, counter_index)]) # Since we do not use a 'TransitionMap', there are some things we need # to do by hand. arrange_trigger_map(trigger_map) local_variable_db = { "reference_p" : Variable("reference_p", "QUEX_TYPE_CHARACTER_POSITION", None, "(QUEX_TYPE_CHARACTER_POSITION)0x0") } init_reference_p = " reference_p = QUEX_NAME(Buffer_tell_memory_adr)(&me->buffer);\n" + \ " me->counter._indentation = (QUEX_TYPE_INDENTATION)0;\n" iteration_code = [] transition_block.do(iteration_code, trigger_map, StateIndex = counter_index, EngineType = E_EngineTypes.INDENTATION_COUNTER, GotoReload_Str = "goto %s;" % get_label("$reload", counter_index)) tmp = [] LanguageDB.COMMENT(tmp, "Skip whitespace at line begin; count indentation.") comment_str = "".join(tmp) # NOTE: Line and column number counting is off # -- No newline can occur # -- column number = indentation at the end of the process end_procedure += " __QUEX_IF_COUNT_COLUMNS_ADD(me->counter._indentation);\n" if Mode is None or Mode.default_indentation_handler_sufficient(): end_procedure += " QUEX_NAME(on_indentation)(me, me->counter._indentation, reference_p);\n" else: # Definition of '%s_on_indentation' in mode_classes.py. end_procedure += " QUEX_NAME(%s_on_indentation)(me, me->counter._indentation, reference_p);\n" \ % Mode.name # The finishing touch prolog = blue_print(prolog_txt, [ ["$$DELIMITER_COMMENT$$", comment_str], ["$$INIT_REFERENCE_POINTER$$", init_reference_p], ["$$COUNTER_INDEX$$", repr(counter_index)], ["$$INPUT_GET$$", LanguageDB.ACCESS_INPUT()], ]) # The finishing touch epilog = blue_print(epilog_txt, [ ["$$INPUT_P_INCREMENT$$", LanguageDB.INPUT_P_INCREMENT()], ["$$INPUT_P_DECREMENT$$", LanguageDB.INPUT_P_DECREMENT()], ["$$IF_INPUT_EQUAL_DELIMITER_0$$", LanguageDB.IF_INPUT("==", "SkipDelimiter$$COUNTER_INDEX$$[0]")], ["$$ENDIF$$", LanguageDB.END_IF()], ["$$LOOP_REENTRANCE$$", LanguageDB.LABEL(counter_index)], ["$$IF_INPUT_EQUAL_BUFFER_LIMIT_CODE$$", LanguageDB.IF_INPUT("==", LanguageDB.BUFFER_LIMIT_CODE)], ["$$RELOAD$$", get_label("$reload", counter_index)], ["$$COUNTER_INDEX$$", repr(counter_index)], ["$$GOTO_TERMINAL_EOF$$", get_label("$terminal-EOF", U=True)], ["$$LEXEME_START_SET_TO_REF$$", LanguageDB.LEXEME_START_SET("reference_p")], # When things were skipped, no change to acceptance flags or modes has # happend. One can jump immediately to the start without re-entry preparation. ["$$GOTO_START$$", get_label("$start", U=True)], ["$$END_PROCEDURE$$", end_procedure], ["$$BAD_CHARACTER_HANDLING$$", get_bad_character_handler(Mode, IndentationSetup, counter_index)], ]) txt = [prolog] txt.extend(iteration_code) # txt.append(Address("$drop-out", counter_index)) txt.append("\n") txt.append(epilog) return txt, local_variable_db
def do(Data): """The generated code is very similar to the 'skipper' code. It is to be executed as soon as a 'real' newline arrived. Then it skips whitespace until the next non-whitepace (also newline may trigger a 'stop'). Dependent on the setup the indentation is determined. """ IndentationSetup = Data["indentation_setup"] assert IndentationSetup.__class__.__name__ == "IndentationSetup" LanguageDB = Setup.language_db Mode = None if IndentationSetup.containing_mode_name() != "": Mode = blackboard.mode_db[IndentationSetup.containing_mode_name()] counter_index = sm_index.get() # Mini trigger map: [ trigger set ] --> loop start # That means: As long as characters of the trigger set appear, we go to the loop start. trigger_map = [] # If the indentation consists only of spaces, than it is 'uniform' ... if IndentationSetup.has_only_single_spaces(): # Count indentation/column at end of run; # simply: current position - reference_p character_set = IndentationSetup.space_db.values()[0] for interval in character_set.get().get_intervals(PromiseToTreatWellF=True): trigger_map.append([interval, counter_index]) # Reference Pointer: Define Variable, Initialize, determine how to subtact. end_procedure = ( " me->counter._indentation = (size_t)(QUEX_NAME(Buffer_tell_memory_adr)(&me->buffer) - reference_p);\n" ) else: # Count the indentation/column during the 'run' # Add the space counters for count, character_set in IndentationSetup.space_db.items(): for interval in character_set.get().get_intervals(PromiseToTreatWellF=True): trigger_map.append([interval, IndentationCounter("space", count, counter_index)]) # Add the grid counters for count, character_set in IndentationSetup.grid_db.items(): for interval in character_set.get().get_intervals(PromiseToTreatWellF=True): trigger_map.append([interval, IndentationCounter("grid", count, counter_index)]) # Reference Pointer: Not required. # No subtraction 'current_position - reference_p'. # (however, we pass 'reference_p' to indentation handler) end_procedure = "" # Bad character detection if IndentationSetup.bad_character_set.get().is_empty() == False: for interval in IndentationSetup.bad_character_set.get().get_intervals(PromiseToTreatWellF=True): trigger_map.append([interval, IndentationCounter("bad", None, counter_index)]) # Since we do not use a 'TransitionMap', there are some things we need # to do by hand. arrange_trigger_map(trigger_map) local_variable_db = { "reference_p": Variable( "reference_p", "QUEX_TYPE_CHARACTER_POSITION", None, "(QUEX_TYPE_CHARACTER_POSITION)0x0" ) } init_reference_p = ( " reference_p = QUEX_NAME(Buffer_tell_memory_adr)(&me->buffer);\n" + " me->counter._indentation = (QUEX_TYPE_INDENTATION)0;\n" ) iteration_code = [] transition_block.do( iteration_code, trigger_map, StateIndex=counter_index, EngineType=E_EngineTypes.INDENTATION_COUNTER, GotoReload_Str="goto %s;" % get_label("$reload", counter_index), ) tmp = [] LanguageDB.COMMENT(tmp, "Skip whitespace at line begin; count indentation.") comment_str = "".join(tmp) # NOTE: Line and column number counting is off # -- No newline can occur # -- column number = indentation at the end of the process end_procedure += " __QUEX_IF_COUNT_COLUMNS_ADD(me->counter._indentation);\n" if Mode is None or Mode.default_indentation_handler_sufficient(): end_procedure += " QUEX_NAME(on_indentation)(me, me->counter._indentation, reference_p);\n" else: # Definition of '%s_on_indentation' in mode_classes.py. end_procedure += " QUEX_NAME(%s_on_indentation)(me, me->counter._indentation, reference_p);\n" % Mode.name # The finishing touch prolog = blue_print( prolog_txt, [ ["$$DELIMITER_COMMENT$$", comment_str], ["$$INIT_REFERENCE_POINTER$$", init_reference_p], ["$$COUNTER_INDEX$$", repr(counter_index)], ["$$INPUT_GET$$", LanguageDB.ACCESS_INPUT()], ], ) # The finishing touch epilog = blue_print( epilog_txt, [ ["$$INPUT_P_INCREMENT$$", LanguageDB.INPUT_P_INCREMENT()], ["$$INPUT_P_DECREMENT$$", LanguageDB.INPUT_P_DECREMENT()], ["$$IF_INPUT_EQUAL_DELIMITER_0$$", LanguageDB.IF_INPUT("==", "SkipDelimiter$$COUNTER_INDEX$$[0]")], ["$$ENDIF$$", LanguageDB.END_IF()], ["$$LOOP_REENTRANCE$$", LanguageDB.LABEL(counter_index)], ["$$IF_INPUT_EQUAL_BUFFER_LIMIT_CODE$$", LanguageDB.IF_INPUT("==", LanguageDB.BUFFER_LIMIT_CODE)], ["$$RELOAD$$", get_label("$reload", counter_index)], ["$$COUNTER_INDEX$$", repr(counter_index)], ["$$GOTO_TERMINAL_EOF$$", get_label("$terminal-EOF", U=True)], ["$$LEXEME_START_SET_TO_REF$$", LanguageDB.LEXEME_START_SET("reference_p")], # When things were skipped, no change to acceptance flags or modes has # happend. One can jump immediately to the start without re-entry preparation. ["$$GOTO_START$$", get_label("$start", U=True)], ["$$END_PROCEDURE$$", end_procedure], ["$$BAD_CHARACTER_HANDLING$$", get_bad_character_handler(Mode, IndentationSetup, counter_index)], ], ) txt = [prolog] txt.extend(iteration_code) # txt.append(Address("$drop-out", counter_index)) txt.append("\n") txt.append(epilog) return txt, local_variable_db
def get_skipper(TriggerSet): """This function implements simple 'skipping' in the sense of passing by characters that belong to a given set of characters--the TriggerSet. """ global template_str assert TriggerSet.__class__.__name__ == "NumberSet" assert not TriggerSet.is_empty() LanguageDB = Setup.language_db skipper_index = sm_index.get() # Mini trigger map: [ trigger set ] --> loop start # That means: As long as characters of the trigger set appear, we go to the loop start. transition_map = TransitionMap() # (don't worry about 'drop-out-ranges' etc.) transition_map.add_transition(TriggerSet, skipper_index) # On buffer limit code, the skipper must transit to a dedicated reloader goto_loop_str = [LanguageDB.INPUT_P_INCREMENT(), " goto _%s_LOOP;\n" % skipper_index] trigger_map = transition_map.get_trigger_map() for i, info in enumerate(trigger_map): interval, target = info if target == E_StateIndices.DROP_OUT: continue trigger_map[i] = (interval, TextTransitionCode(goto_loop_str)) iteration_code = [] transition_block.do(iteration_code, trigger_map, skipper_index, E_EngineTypes.ELSE, GotoReload_Str="goto %s;" % get_label("$reload", skipper_index)) tmp = [] LanguageDB.COMMENT(tmp, "Skip any character in " + TriggerSet.get_utf8_string()) comment_str = "".join(tmp) # Line and column number counting prolog = __lc_counting_replacements(prolog_txt, TriggerSet) epilog = __lc_counting_replacements(epilog_txt, TriggerSet) prolog = blue_print(prolog, [ ["$$DELIMITER_COMMENT$$", comment_str], ["$$SKIPPER_INDEX$$", "%i" % skipper_index], ["$$INPUT_GET$$", LanguageDB.ACCESS_INPUT()], ]) epilog = blue_print(epilog, [ ["$$INPUT_P_INCREMENT$$", LanguageDB.INPUT_P_INCREMENT()], ["$$INPUT_P_DECREMENT$$", LanguageDB.INPUT_P_DECREMENT()], ["$$IF_INPUT_EQUAL_DELIMITER_0$$", LanguageDB.IF_INPUT("==", "SkipDelimiter$$SKIPPER_INDEX$$[0]")], ["$$ENDIF$$", LanguageDB.END_IF()], ["$$LOOP_REENTRANCE$$", LanguageDB.LABEL(skipper_index)], ["$$BUFFER_LIMIT_CODE$$", LanguageDB.BUFFER_LIMIT_CODE], ["$$RELOAD$$", get_label("$reload", skipper_index)], ["$$DROP_OUT_DIRECT$$", get_label("$drop-out", skipper_index, U=True)], ["$$SKIPPER_INDEX$$", "%i" % skipper_index], ["$$LABEL_TERMINAL_EOF$$", "QUEX_LABEL(%i)" % get_address("$terminal-EOF", U=True)], ["$$LABEL_REF_AFTER_RELOAD$$", "QUEX_LABEL(%i)" % get_address("$skipper-reload", skipper_index, U=True)], ["$$GOTO_TERMINAL_EOF$$", get_label("$terminal-EOF", U=True)], ["$$LABEL_AFTER_RELOAD$$", get_label("$skipper-reload", skipper_index)], # When things were skipped, no change to acceptance flags or modes has # happend. One can jump immediately to the start without re-entry preparation. ["$$GOTO_START$$", get_label("$start", U=True)], ["$$MARK_LEXEME_START$$", LanguageDB.LEXEME_START_SET()], ]) code = [ prolog ] code.extend(iteration_code) code.append(epilog) local_variable_db = {} variable_db.enter(local_variable_db, "reference_p", Condition="QUEX_OPTION_COLUMN_NUMBER_COUNTING") return code, local_variable_db