def __init__(self, CoreSM, PreContextSM=None, PostContextSM=None, BeginOfLineF=False, EndOfLineF=False, AllowStateMachineTrafoF=None, fh=-1): assert AllowStateMachineTrafoF is not None pre_context = PreContextSM core_sm = CoreSM post_context = PostContextSM # (1) Character/Newline counting # # !! BEFORE Transformation !! # # Currently 'transition number' is equal to 'character number'. After # transformation a transition may represent a byte or whatever the codec # does to the state machine. self.__newline_n, self.__character_n = character_counter.do(CoreSM) # (2) [Optional] Transformation according to Codec Information # # !! BEFORE Pre- and Post-Context Setup !! # # Because pre-context state machines and pseudo-ambiguous state machines # are inverted. They need to be inverted according to the transformed codec. # !! AVOID Double Transformation !! # The transformation should actually only be allowed during the pattern-action # definition inside a mode --> flag 'AllowStateMachineTrafoF' if AllowStateMachineTrafoF \ and Setup.buffer_codec_transformation_info is not None: sm = transformation.try_this(pre_context, fh) if sm is not None: pre_context = sm sm = transformation.try_this(core_sm, fh) if sm is not None: core_sm = sm sm = transformation.try_this(post_context, fh) if sm is not None: post_context = sm self.__sm = core_sm # (3) Pre- and Post-Context Setup self.__post_context_f = (post_context is not None) self.__sm, \ self.__input_position_search_backward_sm = setup_post_context.do(self.__sm, post_context, EndOfLineF, fh=fh) self.__pre_context_sm_inverse = setup_pre_context.do( self.__sm, pre_context, BeginOfLineF) self.__pre_context_trivial_begin_of_line_f = ( BeginOfLineF and self.__pre_context_sm_inverse is None) self.__validate(fh)
def __init__(self, CoreSM, PreContextSM=None, PostContextSM=None, BeginOfLineF=False, EndOfLineF=False, AllowStateMachineTrafoF=None, fh=-1): assert AllowStateMachineTrafoF is not None pre_context = PreContextSM core_sm = CoreSM post_context = PostContextSM # (1) Character/Newline counting # # !! BEFORE Transformation !! # # Currently 'transition number' is equal to 'character number'. After # transformation a transition may represent a byte or whatever the codec # does to the state machine. self.__newline_n, self.__character_n = character_counter.do(CoreSM) # (2) [Optional] Transformation according to Codec Information # # !! BEFORE Pre- and Post-Context Setup !! # # Because pre-context state machines and pseudo-ambiguous state machines # are inverted. They need to be inverted according to the transformed codec. # !! AVOID Double Transformation !! # The transformation should actually only be allowed during the pattern-action # definition inside a mode --> flag 'AllowStateMachineTrafoF' if AllowStateMachineTrafoF \ and Setup.buffer_codec_transformation_info is not None: sm = transformation.try_this(pre_context, fh) if sm is not None: pre_context = sm sm = transformation.try_this(core_sm, fh) if sm is not None: core_sm = sm sm = transformation.try_this(post_context, fh) if sm is not None: post_context = sm self.__sm = core_sm # (3) Pre- and Post-Context Setup self.__post_context_f = (post_context is not None) self.__sm, \ self.__input_position_search_backward_sm = setup_post_context.do(self.__sm, post_context, EndOfLineF, fh=fh) self.__pre_context_sm_inverse = setup_pre_context.do(self.__sm, pre_context, BeginOfLineF) self.__pre_context_trivial_begin_of_line_f = (BeginOfLineF and self.__pre_context_sm_inverse is None) self.__validate(fh)
def do(A, B): """RETURNS: True - if A == SUPERSET of B False - if not """ if isinstance(A, StateMachine): assert isinstance(B, StateMachine) return Checker(A, B).do() assert not isinstance(B, StateMachine) # (*) Core Pattern ________________________________________________________ # # (including the mounted post context, if there is one). # # NOTE: Post-conditions do not change anything, since they match only when # the whole lexeme has matched (from begin to end of post condition). # Post-conditions only tell something about the place where the # analyzer returns after the match. superset_f = Checker(A.sm, B.sm).do() if not superset_f: return False # NOW: For the core state machines it holds: # # 'core(A)' matches a super set of 'core(B)'. # # (*) Pre-Condition _______________________________________________________ # if not A.has_pre_context(): # core(A) is a superset of core(B). # A is not restricted. B may be (who cares). # => A can match more than B. return True # NOW: Acceptance of A is restricted by a pre-context. # if not B.has_pre_context(): # A is restricted by pre-context, B is not. # => B can match things that A cannot. return False # NOW: A is restricted by pre-context. # B is restricted by pre-context. # # For A to be a superset of B, A must be less or equally restricted than B. # # pre(B) is a superset of pre(A) # # if B.pre_context_trivial_begin_of_line_f: if not A.pre_context_trivial_begin_of_line_f: # pre(A) can never be a subset of pre(B) return False else: # pre(A) = pre(B) which fulfills the condition return True # NOW: B is a 'real' pre-context not only a 'begin-of-line' # # Decision about "pre(A) is subset of pre(B)" done by Checker if not A.pre_context_trivial_begin_of_line_f: A_pre_sm = A.inverse_pre_context_sm else: # A contains only 'begin-of-line'. Note, however, that # -- newline definition may include '\r\n' so inversion is # required. # -- at this point in time we are dealing with transformed # machines. So this has also to be transformed. A_pre_sm = StateMachine.from_sequence("\n").get_inverse() A_pre_sm = transformation.try_this(A_pre_sm, fh=-1) return Checker(B.inverse_pre_context_sm, A_pre_sm).do()