def nfa_to_dfa(old_machine, debug=None): """ Given a nondeterministic Machine, return a new equivalent Machine which is deterministic. """ # We build a new machine whose states correspond to sets of states # in the old machine. Initially we add a new state corresponding to # the epsilon-closure of each initial old state. Then we give transitions # to each new state which are the union of all transitions out of any # of the corresponding old states. The new state reached on a given # character is the one corresponding to the set of states reachable # on that character from any of the old states. As new combinations of # old states are created, new states are added as needed until closure # is reached. new_machine = machines.FastMachine() state_map = StateMap(new_machine) # Seed the process using the initial states of the old machine. # Make the corresponding new states into initial states of the new # machine with the same names. for (key, old_state) in old_machine.initial_states.items(): new_state = state_map.old_to_new(epsilon_closure(old_state)) new_machine.make_initial_state(key, new_state) # Tricky bit here: we add things to the end of this list while we're # iterating over it. The iteration stops when closure is achieved. for new_state in new_machine.states: transitions = TransitionMap() for old_state in state_map.new_to_old(new_state).keys(): for event, old_target_states in old_state.transitions.items(): if event and old_target_states: transitions.add_set(event, set_epsilon_closure(old_target_states)) for event, old_states in transitions.items(): new_machine.add_transitions(new_state, event, state_map.old_to_new(old_states)) if debug: debug.write("\n===== State Mapping =====\n") state_map.dump(debug) return new_machine
def nfa_to_dfa(old_machine, debug=None): """ Given a nondeterministic Machine, return a new equivalent Machine which is deterministic. """ # We build a new machine whose states correspond to sets of states # in the old machine. Initially we add a new state corresponding to # the epsilon-closure of each initial old state. Then we give transitions # to each new state which are the union of all transitions out of any # of the corresponding old states. The new state reached on a given # character is the one corresponding to the set of states reachable # on that character from any of the old states. As new combinations of # old states are created, new states are added as needed until closure # is reached. new_machine = machines.FastMachine() state_map = StateMap(new_machine) # Seed the process using the initial states of the old machine. # Make the corresponding new states into initial states of the new # machine with the same names. for (key, old_state) in old_machine.initial_states.items(): new_state = state_map.old_to_new(epsilon_closure(old_state)) new_machine.make_initial_state(key, new_state) # Tricky bit here: we add things to the end of this list while we're # iterating over it. The iteration stops when closure is achieved. for new_state in new_machine.states: transitions = TransitionMap() for old_state in state_map.new_to_old(new_state).keys(): for event, old_target_states in old_state.transitions.items(): if event and old_target_states: transitions.add_set( event, set_epsilon_closure(old_target_states)) for event, old_states in transitions.items(): new_machine.add_transitions( new_state, event, state_map.old_to_new(old_states)) if debug: debug.write("\n===== State Mapping =====\n") state_map.dump(debug) return new_machine
def __init__(self): # Preinitialise the list of empty transitions, because # the nfa-to-dfa algorithm needs it #self.transitions = {'':[]} self.transitions = TransitionMap() self.action_priority = LOWEST_PRIORITY
class Node: """A state of an NFA or DFA.""" transitions = None # TransitionMap action = None # Action action_priority = None # integer number = 0 # for debug output epsilon_closure = None # used by nfa_to_dfa() def __init__(self): # Preinitialise the list of empty transitions, because # the nfa-to-dfa algorithm needs it #self.transitions = {'':[]} self.transitions = TransitionMap() self.action_priority = LOWEST_PRIORITY def destroy(self): #print "Destroying", self ### self.transitions = None self.action = None self.epsilon_closure = None def add_transition(self, event, new_state): self.transitions.add(event, new_state) def link_to(self, state): """Add an epsilon-move from this state to another state.""" self.add_transition('', state) def set_action(self, action, priority): """Make this an accepting state with the given action. If there is already an action, choose the action with highest priority.""" if priority > self.action_priority: self.action = action self.action_priority = priority def get_action(self): return self.action def get_action_priority(self): return self.action_priority # def merge_actions(self, other_state): # """Merge actions of other state into this state according # to their priorities.""" # action = other_state.get_action() # priority = other_state.get_action_priority() # self.set_action(action, priority) def is_accepting(self): return self.action is not None def __str__(self): return "State %d" % self.number def dump(self, file): import string # Header file.write(" State %d:\n" % self.number) # Transitions # self.dump_transitions(file) self.transitions.dump(file) # Action action = self.action priority = self.action_priority if action is not None: file.write(" %s [priority %d]\n" % (action, priority))