Ejemplo n.º 1
0
    def __init__(self, AcceptanceF=False, CloneF=False):
        """Contructor of a State, i.e. a aggregation of transitions.
        """
        if CloneF: return

        self.__target_map = TargetMap()
        self.__single_entry = SingleEntry()
        if AcceptanceF: self.set_acceptance()
Ejemplo n.º 2
0
 def from_state_iterable(StateList):
     """Does not set '.__target_map'
     """
     result = DFA_State()
     result.__target_map   = TargetMap()
     result.__single_entry = SingleEntry() 
     result.__single_entry.merge_list(state.single_entry for state in StateList)
     return result
Ejemplo n.º 3
0
class State:
    """A state consisting of ONE entry and multiple transitions to other
    states.  One entry means that the exact same actions are applied upon state
    entry, independent from where the state is entered.

           ...   ----->---.                               .--->   ...
                           \                     .-----.-'
           ...   ----->-----+--->[ StateOp ]----( State )----->   ...
                           /                     '-----'
           ...   ----->---'        

    Transitions are of two types:
    
     -- normal transitions: Happen when an input character fits a trigger set.
     -- epsilon transition: Happen without any input.
    
    Collections of states connected by transitions build a StateMachine. States 
    may be used in NFA-s (non-deterministic finite state automatons) and DFA-s
    (deterministic finite state automatons). Where NFA-s put no restrictions on
    transitions, DFA-s do. A state in a DFA has the following properties:
    
       -- Trigger sets of normal transitions do not intersect.
       -- There are no epsilon transitions. 

    Whether or not a state complies to the requirements of a DFA can be checked
    by '.is_DFA_compliant()'.
    """
    @typed(AcceptanceF=bool, CloneF=bool)
    def __init__(self, AcceptanceF=False, CloneF=False):
        """Contructor of a State, i.e. a aggregation of transitions.
        """
        if CloneF: return

        self.__target_map = TargetMap()
        self.__single_entry = SingleEntry()
        if AcceptanceF: self.set_acceptance()

    def clone(self,
              ReplDbStateIndex=None,
              ReplDbPreContext=None,
              ReplDbAcceptance=None):
        """Creates a copy of all transitions, but replaces any state index with the ones 
           determined in the ReplDbStateIndex."""
        assert ReplDbStateIndex is None or isinstance(ReplDbStateIndex, dict)
        result = State(CloneF=True)
        result.__target_map = self.__target_map.clone(ReplDbStateIndex)
        result.__single_entry = self.__single_entry.clone(
            ReplDbPreContext=ReplDbPreContext,
            ReplDbAcceptance=ReplDbAcceptance)

        return result

    @staticmethod
    def from_state_iterable(StateList):
        """Does not set '.__target_map'
        """
        result = State()
        result.__target_map = TargetMap()
        result.__single_entry = SingleEntry()
        result.__single_entry.merge_list(state.single_entry
                                         for state in StateList)
        return result

    @property
    def single_entry(self):
        return self.__single_entry

    @property
    def target_map(self):
        return self.__target_map

    def is_acceptance(self):
        return self.single_entry.find(SeAccept) is not None

    def input_position_store_f(self):
        return self.single_entry.find(SeStoreInputPosition) is not None

    def input_position_restore_f(self):
        for cmd in self.single_entry:
            if cmd.__class__ != SeAccept: continue
            elif cmd.restore_position_register_f(): return True
        return False

    def pre_context_id(self):
        cmd = self.single_entry.find(SeAccept)
        if cmd is None: return E_PreContextIDs.NONE
        else: return cmd.pre_context_id()

    def set_pre_context_id(self, Value=True):
        accept_cmd = self.single_entry.find(SeAccept)
        assert accept_cmd is not None
        accept_cmd.set_pre_context_id(Value)

    def set_acceptance(self, Value=True):
        if Value: self.single_entry.add_Op(SeAccept)
        else: self.single_entry.remove_Op(SeAccept)

    def mark_acceptance_id(self, AcceptanceID):
        for cmd in self.single_entry:
            if not hasattr(cmd, "set_acceptance_id"): continue
            cmd.set_acceptance_id(AcceptanceID)

    def set_input_position_restore_f(self, Value=True):
        accept_cmd = self.single_entry.find(SeAccept)
        assert accept_cmd is not None
        accept_cmd.set_restore_position_register_f()

    def set_input_position_store_f(self, Value=True):
        if Value: self.single_entry.add_Op(SeStoreInputPosition)
        else: self.single_entry.remove_Op(SeStoreInputPosition)

    def add_transition(self, Trigger, TargetStateIdx):
        self.__target_map.add_transition(Trigger, TargetStateIdx)

    def get_string(self,
                   StateIndexMap=None,
                   Option="utf8",
                   OriginalStatesF=True):
        # if information about origins of the state is present, then print
        se_str = self.single_entry.get_string(OriginalStatesF)
        # print out transitionts
        tm_str = self.target_map.get_string("    ", StateIndexMap, Option)
        return " %s%s" % (se_str, tm_str)

    def get_graphviz_string(self, OwnStateIdx, StateIndexMap, Option):
        assert Option in ["hex", "utf8"]
        return self.target_map.get_graphviz_string(OwnStateIdx, StateIndexMap,
                                                   Option)

    def __repr__(self):
        return self.get_string()
Ejemplo n.º 4
0
 def from_TargetMap(Db):
     result = DFA_State(CloneF=True)
     result.__target_map   = TargetMap(Db)
     result.__single_entry = SingleEntry()
     return result
Ejemplo n.º 5
0
class DFA_State:
    """A state consisting of ONE entry and multiple transitions to other
    states.  One entry means that the exact same actions are applied upon state
    entry, independent from where the state is entered.

           ...   ----->---.                               .--->   ...
                           \                     .-----.-'
           ...   ----->-----+--->[ StateOp ]----( State )----->   ...
                           /                     '-----'
           ...   ----->---'        

    Transitions are of two types:
    
     -- normal transitions: Happen when an input character fits a trigger set.
     -- epsilon transition: Happen without any input.
    
    Collections of states connected by transitions build a DFA. States 
    may be used in NFA-s (non-deterministic finite state automatons) and DFA-s
    (deterministic finite state automatons). Where NFA-s put no restrictions on
    transitions, DFA-s do. A state in a DFA has the following properties:
    
       -- Trigger sets of normal transitions do not intersect.
       -- There are no epsilon transitions. 

    Whether or not a state complies to the requirements of a DFA can be checked
    by '.is_DFA_compliant()'.
    """
    @typed(AcceptanceF=bool, CloneF=bool)
    def __init__(self, AcceptanceF=False, CloneF=False):
        """Contructor of a DFA_State, i.e. a aggregation of transitions.
        """
        if CloneF: return

        self.__target_map   = TargetMap()
        self.__single_entry = SingleEntry()
        if AcceptanceF: self.set_acceptance()

    def clone(self, ReplDbStateIndex=None, ReplDbPreContext=None, ReplDbAcceptance=None):
        """Creates a copy of all transitions, but replaces any state index with the ones 
        determined in the ReplDbStateIndex.
           
        ONLY THOSE TRANSITIONS ARE CLONED, which have a target state index from 
        the 'ReplDbStateIndex'.
        """
        assert ReplDbStateIndex is None or isinstance(ReplDbStateIndex, dict)
        result = DFA_State(CloneF=True)
        result.__target_map   = self.__target_map.clone(ReplDbStateIndex)
        result.__single_entry = self.__single_entry.clone(ReplDbPreContext=ReplDbPreContext,
                                                          ReplDbAcceptance=ReplDbAcceptance)

        return result

    @staticmethod
    def from_state_iterable(StateList):
        """Does not set '.__target_map'
        """
        result = DFA_State()
        result.__target_map   = TargetMap()
        result.__single_entry = SingleEntry() 
        result.__single_entry.merge_list(state.single_entry for state in StateList)
        return result

    @staticmethod
    def from_TargetMap(Db):
        result = DFA_State(CloneF=True)
        result.__target_map   = TargetMap(Db)
        result.__single_entry = SingleEntry()
        return result

    @property
    def single_entry(self):
        return self.__single_entry

    def set_single_entry(self, Other):
        self.__single_entry = Other

    @property
    def target_map(self):
        return self.__target_map

    @staticmethod
    def interference(StateList):
        """RETURNS: True, if either the single_entry objects differ.
                          Or, if the transition maps intersect.
                    False, else.
        """
        if len(StateList) < 1: 
            return False
        prototype = StateList[0]
        for s in StateList[1:]:
            if not s.__single_entry.is_equal(prototype.__single_entry):
                return True

        prototype_tsu = prototype.target_map.get_trigger_set_union()
        for s in StateList[1:]:
            tsu = s.target_map.get_trigger_set_union()
            if tsu.has_intersection(prototype_tsu):
                return True
            prototype_tsu.unite_with(tsu)
        
        # All single_entry operations are equal.
        # No transition trigger set intersects.
        # => no interference!
        return False

    def has_transitions(self):
        return not self.target_map.is_empty()

    def is_bad_lexatom_detector(self):
        return any(cmd.acceptance_id() == E_IncidenceIDs.BAD_LEXATOM for cmd in self.single_entry)

    def is_acceptance(self):
        """Acceptance of 'BAD_LEXATOM' is not really an acceptance!"""
        cmd = self.single_entry.find(SeAccept) 
        if cmd is None: return False 
        return not any(cmd.acceptance_id() == E_IncidenceIDs.BAD_LEXATOM for cmd in self.single_entry)

    def acceptance_id_set(self):
        return [
            cmd.acceptance_id() 
            for cmd in self.single_entry.get_iterable(SeAccept)
            if cmd.acceptance_id() != E_IncidenceIDs.BAD_LEXATOM
        ]

    def get_highest_precedence_acceptance_id(self):
        """RETURNS: incidence_id of the highest non-E_IncidenceIDs pattern
                                 that matches in this state.
                    None, else.
        """
        return self.single_entry.get_highest_precedence_acceptance_id()

    def input_position_store_f(self):
        return self.single_entry.find(SeStoreInputPosition) is not None

    def input_position_restore_f(self):
        for cmd in self.single_entry:
            if cmd.__class__ != SeAccept: continue
            elif cmd.restore_position_register_f(): return True
        return False

    def acceptance_condition_set(self):
        cmd = self.single_entry.find(SeAccept)
        if cmd is None: return set()
        else:           return cmd.acceptance_condition_set()

    def set_acceptance_condition_id(self, Value=True):
        accept_cmd = self.single_entry.find(SeAccept)
        assert accept_cmd is not None
        accept_cmd.set_acceptance_condition_id(Value)

    def set_acceptance(self, Value=True):
        if Value: self.single_entry.add_Op(SeAccept)
        else:     self.single_entry.remove_Op(SeAccept)

    def has_specific_acceptance_id(self):
        return any(cmd.acceptance_id() != E_IncidenceIDs.MATCH_FAILURE 
                   for cmd in self.single_entry)

    def set_specific_acceptance_id(self, AcceptanceID):
        """Sets a specific acceptance id, but does not modify the 'store input
        position' behavior. 
        """
        accept_cmd = self.single_entry.find(SeAccept)
        if accept_cmd is None:
            self.single_entry.add_Op(SeAccept)
            accept_cmd = self.single_entry.find(SeAccept)
        accept_cmd.set_acceptance_id(AcceptanceID)

    def mark_acceptance_id(self, AcceptanceID):
        for cmd in self.single_entry:
            if not hasattr(cmd, "set_acceptance_id"): continue
            # 'BAD_LEXATOM' must not be outruled, ever!
            if cmd.acceptance_id() == E_IncidenceIDs.BAD_LEXATOM: continue
            cmd.set_acceptance_id(AcceptanceID)

    def has_acceptance_id(self, AcceptanceID):
        return any(cmd.acceptance_id() == AcceptanceID 
                   for cmd in self.single_entry)

    def set_read_position_restore_f(self, Value=True):
        accept_cmd = self.single_entry.find(SeAccept)
        assert accept_cmd is not None
        accept_cmd.set_restore_position_register_f()

    def set_read_position_store_f(self, Value=True):
        if Value: self.single_entry.add_Op(SeStoreInputPosition)
        else:     self.single_entry.remove_Op(SeStoreInputPosition)

    def add_transition(self, Trigger, TargetStateIdx): 
        self.__target_map.add_transition(Trigger, TargetStateIdx)

    def get_string(self, StateIndexMap=None, Option="utf8", OriginalStatesF=True):
        # if information about origins of the state is present, then print
        se_str = self.single_entry.get_string(OriginalStatesF)
        # print out transitionts
        tm_str = self.target_map.get_string("    ", StateIndexMap, Option)
        return " %s%s" % (se_str, tm_str)

    def get_graphviz_string(self, OwnStateIdx, StateIndexMap, Option):
        assert Option in ["hex", "utf8"]
        return self.target_map.get_graphviz_string(OwnStateIdx, StateIndexMap, Option)

    def __repr__(self):
        return self.get_string()