def reentry_preparation(Lng, PreConditionIDList, OnAfterMatchCode, dial_db): """Reentry preperation (without returning from the function.""" # (*) Unset all pre-context flags which may have possibly been set unset_pre_context_flags_str = Lng.PRE_CONTEXT_RESET(PreConditionIDList) on_after_match_str = Lng.SOURCE_REFERENCED(OnAfterMatchCode) return [ "\n%s\n" % Lng.LABEL(DoorID.return_with_on_after_match(dial_db)), Lng.COMMENT("RETURN -- after executing 'on_after_match' code."), on_after_match_str, " %s\n\n" % Lng.PURE_RETURN, # "\n%s\n" % Lng.LABEL(DoorID.continue_with_on_after_match(dial_db)), Lng.COMMENT("CONTINUE -- after executing 'on_after_match' code."), on_after_match_str, # "\n%s\n" % Lng.LABEL(DoorID.continue_without_on_after_match(dial_db)), Lng.COMMENT( "CONTINUE -- without executing 'on_after_match' (e.g. on FAILURE)." ), "\n", # __assert_no_mode_change, "\n", __return_if_queue_full_or_simple_analyzer, "\n", unset_pre_context_flags_str, "\n%s\n" % Lng.GOTO(DoorID.global_reentry(dial_db), dial_db), ]
def reentry_preparation(Lng, PreConditionIDList, OnAfterMatchCode): """Reentry preperation (without returning from the function.""" # (*) Unset all pre-context flags which may have possibly been set unset_pre_context_flags_str = Lng.PRE_CONTEXT_RESET(PreConditionIDList) if OnAfterMatchCode is not None: on_after_match_str = Lng.SOURCE_REFERENCED(OnAfterMatchCode) else: on_after_match_str = "" txt = [ "\n%s\n" % Lng.LABEL(DoorID.return_with_on_after_match()), Lng.COMMENT("RETURN -- after executing 'on_after_match' code."), on_after_match_str, " %s\n\n" % Lng.PURE_RETURN, # "\n%s\n" % Lng.LABEL(DoorID.continue_with_on_after_match()), Lng.COMMENT("CONTINUE -- after executing 'on_after_match' code."), on_after_match_str, # "\n%s\n" % Lng.LABEL(DoorID.continue_without_on_after_match()), Lng.COMMENT("CONTINUE -- without executing 'on_after_match' (e.g. on FAILURE)."), "\n", # __return_if_queue_full_or_simple_analyzer, "\n", __return_if_mode_changed, "\n", # unset_pre_context_flags_str, "\n%s\n" % Lng.GOTO(DoorID.global_reentry()), ] return txt
def _code_terminal_on_bad_indentation_character(code, ISetup, ModeName, incidence_db, BadIndentationIid): if ISetup.bad_character_set.get() is None: return on_bad_indentation_txt = Lng.SOURCE_REFERENCED(incidence_db[E_IncidenceIDs.INDENTATION_BAD]) code.extend([ "%s\n" % Lng.LABEL(DoorID.incidence(BadIndentationIid)), "#define BadCharacter (me->buffer._input_p[-1])\n", "%s\n" % on_bad_indentation_txt, "#undef BadCharacter\n", "%s\n" % Lng.GOTO(DoorID.global_reentry()) ])
def _code_terminal_on_bad_indentation_character(code, ISetup, ModeName, incidence_db, BadIndentationIid): if ISetup.bad_character_set.get() is None: return on_bad_indentation_txt = Lng.SOURCE_REFERENCED( incidence_db[E_IncidenceIDs.INDENTATION_BAD]) code.extend([ "%s\n" % Lng.LABEL(DoorID.incidence(BadIndentationIid)), "#define BadCharacter (me->buffer._input_p[-1])\n", "%s\n" % on_bad_indentation_txt, "#undef BadCharacter\n", "%s\n" % Lng.GOTO(DoorID.global_reentry()) ])
def PPT_indentation_handler_suppressed_newline(MHI, SmSuppressedNewline): """Generate a PPT for suppressed newline, that is: -- its PatternPriority. -- the Pattern object. -- the Terminal object. The terminal simply jumpts to the re-entry of the lexical analyzer. """ assert SmSuppressedNewline is not None pattern = Pattern(SmSuppressedNewline, PatternString="<indentation suppressed newline>") code = CodeTerminal([Lng.GOTO(DoorID.global_reentry())]) # terminal = terminal_factory.do(E_TerminalType.PLAIN, code) # terminal.set_name("INDENTATION COUNTER: SUPPRESSED_NEWLINE") return PPT(PatternPriority(MHI, 1), pattern, code)
def _analyzer_function(StateMachineName, Setup, variable_definitions, function_body, ModeNameList=[]): """EngineClassName = name of the structure that contains the engine state. if a mode of a complete quex environment is created, this is the mode name. otherwise, any name can be chosen. SingleModeAnalyzerF = False if a mode for a quex engine is to be created. True if a stand-alone lexical engine is required (without the complete mode-handling framework of quex). """ Lng = Setup.language_db SingleModeAnalyzerF = Setup.single_mode_analyzer_f mode_definition_str = "" mode_undefinition_str = "" if len(ModeNameList) != 0 and not SingleModeAnalyzerF: L = max(map(lambda name: len(name), ModeNameList)) mode_definition_str = "".join( "# define %s%s (QUEX_NAME(%s))\n" % (name, " " * (L- len(name)), name) for name in ModeNameList ) mode_undefinition_str = "".join( "# undef %s\n" % name for name in ModeNameList ) function_signature_str = __function_signature.replace("$$STATE_MACHINE_NAME$$", StateMachineName) txt = [ "#include <quex/code_base/temporary_macros_on>\n", function_signature_str, # # Macro definitions # "# ifdef self\n", "# undef self\n", "# endif\n", "# define self (*((QUEX_TYPE_ANALYZER*)me))\n", "/* 'QUEX_GOTO_STATE' requires 'QUEX_LABEL_STATE_ROUTER' */\n", "# define QUEX_LABEL_STATE_ROUTER %s\n" % dial_db.get_label_by_door_id(DoorID.global_state_router()), mode_definition_str, Lng.LEXEME_MACRO_SETUP(), # variable_definitions, # comment_on_post_context_position_init_str, "# if defined(QUEX_OPTION_AUTOMATIC_ANALYSIS_CONTINUATION_ON_MODE_CHANGE) \\\n", " || defined(QUEX_OPTION_ASSERTS)\n", " me->DEBUG_analyzer_function_at_entry = me->current_analyzer_function;\n", "# endif\n", # # Entry to the actual function body # "%s\n" % Lng.LABEL(DoorID.global_reentry()), " %s\n" % Lng.LEXEME_START_SET(), " QUEX_LEXEME_TERMINATING_ZERO_UNDO(&me->buffer);\n", ] txt.extend(function_body) # -- prevent the warning 'unused variable' txt.extend([ "\n", " __quex_assert_no_passage();\n", "\n", " /* Following labels are referenced in macros. It cannot be detected\n" " * whether the macros are applied in user code or not. To avoid compiler.\n" " * warnings of unused labels, they are referenced in unreachable code. */\n" " %s /* in RETURN */\n" % Lng.GOTO(DoorID.return_with_on_after_match()), " %s /* in CONTINUE */\n" % Lng.GOTO(DoorID.continue_with_on_after_match()), " %s /* in CONTINUE and skippers */\n" % Lng.GOTO(DoorID.continue_without_on_after_match()), "# if ! defined(QUEX_OPTION_COMPUTED_GOTOS)\n", " %s /* in QUEX_GOTO_STATE */\n" % Lng.GOTO(DoorID.global_state_router()), "# endif\n", "\n", " /* Prevent compiler warning 'unused variable'. */\n", " (void)QUEX_LEXEME_NULL;\n", " (void)QUEX_NAME_TOKEN(DumpedTokenIdObject);\n", " /* target_state_index and target_state_else_index appear when \n", " * QUEX_GOTO_STATE is used without computed goto-s. */\n", " (void)target_state_index;\n", " (void)target_state_else_index;\n", # # Macro undefinitions # lexeme_macro_clean_up, mode_undefinition_str, "# undef self\n", "# undef QUEX_LABEL_STATE_ROUTER\n", "}\n", "#include <quex/code_base/temporary_macros_off>\n", ]) return txt
def _analyzer_function(StateMachineName, Setup, variable_definitions, function_body, dial_db, ModeNameList): """EngineClassName = name of the structure that contains the engine state. if a mode of a complete quex environment is created, this is the mode name. otherwise, any name can be chosen. """ Lng = Setup.language_db function_signature_str = __function_signature.replace( "$$STATE_MACHINE_NAME$$", StateMachineName) state_router_adr = DoorID.global_state_router(dial_db).related_address txt = [ function_signature_str, # Macro definitions # Lng.DEFINE_SELF("me"), Lng.MODE_DEFINITION(ModeNameList), "/* 'QUEX_GOTO_STATE' requires 'QUEX_LABEL_STATE_ROUTER' */\n", "# define QUEX_LABEL_STATE_ROUTER %s\n" % Lng.LABEL_STR_BY_ADR(state_router_adr), Lng.DEFINE_LEXEME_VARIABLES(), # variable_definitions, # comment_on_post_context_position_init_str, "# if defined(QUEX_OPTION_ASSERTS)\n", " me->DEBUG_analyzer_function_at_entry = me->current_analyzer_function;\n", "# endif\n", # # Entry to the actual function body # "%s\n" % Lng.LABEL(DoorID.global_reentry(dial_db)), " %s\n" % Lng.LEXEME_START_SET(), " QUEX_LEXEME_TERMINATING_ZERO_UNDO(&me->buffer);\n", ] txt.extend(function_body) # -- prevent the warning 'unused variable' txt.extend([ "\n", " __quex_assert_no_passage();\n", "\n", " /* Following labels are referenced in macros. It cannot be detected\n" " * whether the macros are applied in user code or not. To avoid compiler.\n" " * warnings of unused labels, they are referenced in unreachable code. */\n" " %s /* in RETURN */\n" % Lng.GOTO(DoorID.return_with_on_after_match(dial_db), dial_db), " %s /* in CONTINUE */\n" % Lng.GOTO(DoorID.continue_with_on_after_match(dial_db), dial_db), " %s /* in CONTINUE and skippers */\n" % Lng.GOTO(DoorID.continue_without_on_after_match(dial_db), dial_db), "$$<not-computed-gotos>----------------------------------------------\n", " %s /* in QUEX_GOTO_STATE */\n" % Lng.GOTO(DoorID.global_state_router(dial_db), dial_db), "$$------------------------------------------------------------------\n", "\n", " /* Prevent compiler warning 'unused variable'. */\n", " (void)QUEX_NAME(LexemeNull);\n", " /* target_state_index and target_state_else_index appear when \n", " * QUEX_GOTO_STATE is used without computed goto-s. */\n", " (void)target_state_index;\n", " (void)target_state_else_index;\n", # # Macro undefinitions # Lng.UNDEFINE_LEXEME_VARIABLES(), Lng.MODE_UNDEFINITION(ModeNameList), "# undef self\n", "# undef QUEX_LABEL_STATE_ROUTER\n", "}\n", ]) return txt
def _prepare_indentation_counter(self, MHI, Loopers, CaMap, ReloadState): """Prepare indentation counter. An indentation counter is implemented by the following: 'newline' pattern --> triggers as soon as an UNSUPPRESSED newline occurs. --> entry to the INDENTATION COUNTER. 'suppressed newline' --> INDENTATION COUNTER is NOT triggered. The supressed newline pattern is longer (and has precedence) over the newline pattern. With the suppressed newline it is possible to write lines which overstep the newline (see backslahs in Python, for example). RETURNS: List of: [0] newline PPT and [1] optionally the PPT of the newline suppressor. The primary pattern action pair list is to be the head of all pattern action pairs. MHI = Mode hierarchie index defining the priority of the current mode. """ ISetup = Loopers.indentation_handler if ISetup is None: return [], [], [] check_indentation_setup(ISetup) # Isolate the pattern objects, so alternatively, # they may be treated in 'indentation_counter'. pattern_newline = ISetup.pattern_newline.clone() if ISetup.pattern_suppressed_newline: pattern_suppressed_newline = ISetup.pattern_suppressed_newline.clone( ) else: pattern_suppressed_newline = None new_analyzer_list, \ new_terminal_list, \ required_register_set, \ run_time_counter_f = indentation_counter.do(self.terminal_factory.mode_name, CaMap, ISetup, self.terminal_factory.incidence_db, ReloadState, self.terminal_factory.dial_db) self.terminal_factory.run_time_counter_required_f |= run_time_counter_f self.required_register_set.update(required_register_set) # 'newline' triggers --> indentation counter pattern = pattern_newline.finalize(CaMap) pattern = pattern.clone_with_new_incidence_id( E_IncidenceIDs.INDENTATION_HANDLER) terminal = self._terminal_goto_to_looper(new_analyzer_list, None, "<indentation handler>", required_register_set, Pattern=pattern) new_ppt_list = [PPT(PatternPriority(MHI, 0), pattern, terminal)] if pattern_suppressed_newline is not None: # 'newline-suppressor' causes following 'newline' to be ignored. # => next line not subject to new indentation counting. new_incidence_id = dial.new_incidence_id() pattern = pattern_suppressed_newline.finalize(CaMap) pattern = pattern.clone_with_new_incidence_id(new_incidence_id) door_id = DoorID.global_reentry(self.terminal_factory.dial_db) code = CodeTerminal( [Lng.GOTO(door_id, self.terminal_factory.dial_db)]) new_ppt_list.append( PPT( PatternPriority(MHI, 1), pattern, self.terminal_factory.do_plain( code, pattern, "INDENTATION COUNTER SUPPRESSED_NEWLINE: "))) return new_ppt_list, new_analyzer_list, new_terminal_list