diff pyrect/regexp/nfa.py @ 98:4d498b002de5

refactor for data-structure (dict -> Transition).
author Ryoma SHINYA <shinya@firefly.cr.ie.u-ryukyu.ac.jp>
date Sun, 12 Dec 2010 23:04:31 +0900
parents 19a88707bd29
children 2632b963e441
line wrap: on
line diff
--- a/pyrect/regexp/nfa.py	Sun Dec 12 19:02:37 2010 +0900
+++ b/pyrect/regexp/nfa.py	Sun Dec 12 23:04:31 2010 +0900
@@ -3,16 +3,20 @@
 import curses.ascii as ascii
 import copy
 import collections
-from pyrect.regexp.fa import FA
+from pyrect.regexp.fa import FA, Transition
 
 class NFAFragment(object):
     def __init__(self):
         self.start   = None    # integer
         self.accepts = set()   # frozenset
-        self.map     = dict()  # transition, char or special -> frozenset([states])
+        self.transition     = Transition()  # transition, char or special -> frozenset([states])
 
     def connect(self, from_, char, to):
-        slot = self.map.setdefault((from_, char), set())
+        if self.transition[from_, char]:
+            slot = self.transition[from_, char]
+        else:
+            slot = set()
+            self.transition[from_, char] = slot
         slot.add(to)
 
     def accept_to(self, from_, char):
@@ -26,46 +30,44 @@
     def new_skelton(self):
         # copy fragment (self), and it return
         newFrag = NFAFragment();
-        newFrag.map = copy.deepcopy(self.map)
+        newFrag.transition = copy.deepcopy(self.transition)
         return newFrag
 
     def __or__(self, frag):
         newFrag = self.new_skelton()
-        for k, v in frag.map.iteritems():
-            newFrag.map[k] = v.copy()
+        for k, v in frag.transition.iterstates():
+            newFrag.transition[k] = copy.deepcopy(v)
         return newFrag
 
     def __str__(self):
         return ("NFA: delta -> %s, start -> %s, accepts -> %s" %
-                (self.map, self.start, self.accepts))
+                (self.transition, self.start, self.accepts))
 
     def build(self):
-        map_ = self.map
-        def transition(state, char):
-            return frozenset(map_.get((state, char), []))
-
         states = set()
-        for (s, _) in self.map.iterkeys():
+        for s in self.transition.iterkeys():
             states.add(s)
 
         return NFA(
-            transition,
+            self.transition,
             self.start,
             self.accepts,
-            self.map,
             sorted(states)
             )
 
 class NFA(FA):
-    def epsilon_expand(self, set_):
-        que = set(set_)
+    def epsilon_expand(self, states):
+        if not isinstance(states, set) and \
+        not isinstance(states, list):
+            states = set([states])
+        states = copy.deepcopy(states)
         done = set()
-        while que:
-            stat = que.pop()
-            nexts = self.transition(stat, "")
+        while states:
+            stat = states.pop()
             done.add(stat)
-            for nextStat in nexts:
-                if not nextStat in done: que.add(nextStat)
+            if self.transition[stat, ""] != None:
+                for n in self.transition[stat, ""]:
+                    if not n in done: states.add(n)
         return frozenset(done)
 
 class SuffixNFA(NFA):
@@ -73,40 +75,36 @@
         self.start = nfa.start
         self.accepts = copy.deepcopy(nfa.accepts)
         self.states = copy.deepcopy(nfa.states)
-        self.map = self.nfa_map(nfa)
+        self.transition = self.nfa_trans(nfa)
         start = set(self.states)-set([self.start])
         if self.map.has_key((self.start, '')):
             self.map[(self.start, '')].add(start)
         else:
             self.map[(self.start, '')] = start
 
-    def nfa_map(self, fa):
+    def nfa_trans(self, fa):
         if type(fa) == NFA:
-            return copy.deepcopy(fa.map)
-        nmap = dict()
-        for k, v in fa.map.items():
-            nmap[k] = set([v])
-        return nmap
-
-    def transition(self, state, char):
-        return frozenset(self.map.get((state, char), []))
+            return copy.deepcopy(fa.transition)
+        ntrans = dict()
+        for k, v in fa.map.itertrans():
+            ntrans[k] = set([v])
+        return ntrans
 
 class SuffixTrieNFA(NFA):
     def __init__(self, dfa):
         self.start = dfa.start
         self.pdfa = dfa
-        self.map = dict()
         self.states = copy.deepcopy(dfa.states)
         self.acceptable = collections.defaultdict(set)
         self.accepts = copy.deepcopy(set(dfa.accepts))
         states = [self.start] + list(set(self.states)-set((self.start,)))
-        self.make_trie_map(states)
+        self.make_trie_trans(states)
 
-    def make_trie_map(self, states):
+    def make_trie_trans(self, states):
         add_states = set()
         offset = [x * len(states) for x in range(len(states))]
         for s, ind in zip(states, offset):
-            for (s_, i), n in self.pdfa.map.iteritems():
+            for (s_, i), n in self.pdfa.trans.itertrans():
                 sind = s_ + ind
                 nind = n + ind
                 add_states.add((sind, nind))
@@ -120,7 +118,4 @@
             starts.add(self.start + i + offset[i])
 
         self.states = list(add_states)
-        self.map[(self.start, '')] = starts
-
-    def transition(self, state, char):
-        return frozenset(self.map.get((state, char), []))
+        self.trans[(self.start, '')] = starts