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 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