Use NFAArc as a class

This commit is contained in:
Dave Halter
2018-06-14 10:29:19 +02:00
parent a277ccf288
commit 8c348aee6f
2 changed files with 33 additions and 27 deletions

View File

@@ -133,15 +133,21 @@ class GrammarParser():
self.begin[1], line)) self.begin[1], line))
class NFAArc(object):
def __init__(self, next_, label_or_string):
self.next = next_
self.label_or_string = label_or_string
class NFAState(object): class NFAState(object):
def __init__(self, from_rule): def __init__(self, from_rule):
self.from_rule = from_rule self.from_rule = from_rule
self.arcs = [] # list of (label, NFAState) pairs self.arcs = [] # list of (label, NFAState) pairs
def add_arc(self, next, label=None): def add_arc(self, next_, label=None):
assert label is None or isinstance(label, str) assert label is None or isinstance(label, str)
assert isinstance(next, NFAState) assert isinstance(next_, NFAState)
self.arcs.append((label, next)) self.arcs.append(NFAArc(next_, label))
def __repr__(self): def __repr__(self):
return '<%s: from %s>' % (self.__class__.__name__, self.from_rule) return '<%s: from %s>' % (self.__class__.__name__, self.from_rule)

View File

@@ -39,14 +39,14 @@ class ParserGenerator(object):
grammar.symbol2number[name] = i grammar.symbol2number[name] = i
grammar.number2symbol[i] = name grammar.number2symbol[i] = name
for name in names: for name in names:
dfa = self._rule_to_dfas[name] dfas = self._rule_to_dfas[name]
states = [] states = []
for state in dfa: for state in dfas:
arcs = [] arcs = []
for label, next in state.arcs.items(): for label, next in state.arcs.items():
arcs.append((self._make_label(grammar, label), dfa.index(next))) arcs.append((self._make_label(grammar, label), dfas.index(next)))
if state.isfinal: if state.isfinal:
arcs.append((0, dfa.index(state))) arcs.append((0, dfas.index(state)))
states.append(arcs) states.append(arcs)
grammar.states.append(states) grammar.states.append(states)
grammar.dfas[grammar.symbol2number[name]] = (states, self._make_first(grammar, name)) grammar.dfas[grammar.symbol2number[name]] = (states, self._make_first(grammar, name))
@@ -148,19 +148,19 @@ class ParserGenerator(object):
class DFAState(object): class DFAState(object):
def __init__(self, nfaset, final): def __init__(self, nfa_set, final):
assert isinstance(nfaset, dict) assert isinstance(nfa_set, dict)
assert isinstance(next(iter(nfaset)), NFAState) assert isinstance(next(iter(nfa_set)), NFAState)
assert isinstance(final, NFAState) assert isinstance(final, NFAState)
self.nfaset = nfaset self.nfa_set = nfa_set
self.isfinal = final in nfaset self.isfinal = final in nfa_set
self.arcs = {} # map from label to DFAState self.arcs = {} # map from label to DFAState
def add_arc(self, next, label): def add_arc(self, next_, label):
assert isinstance(label, str) assert isinstance(label, str)
assert label not in self.arcs assert label not in self.arcs
assert isinstance(next, DFAState) assert isinstance(next_, DFAState)
self.arcs[label] = next self.arcs[label] = next_
def unifystate(self, old, new): def unifystate(self, old, new):
for label, next in self.arcs.items(): for label, next in self.arcs.items():
@@ -168,7 +168,7 @@ class DFAState(object):
self.arcs[label] = new self.arcs[label] = new
def __eq__(self, other): def __eq__(self, other):
# Equality test -- ignore the nfaset instance variable # Equality test -- ignore the nfa_set instance variable
assert isinstance(other, DFAState) assert isinstance(other, DFAState)
if self.isfinal != other.isfinal: if self.isfinal != other.isfinal:
return False return False
@@ -219,27 +219,27 @@ def _make_dfas(start, finish):
if state in base: if state in base:
return return
base[state] = 1 base[state] = 1
for label, next_ in state.arcs: for nfa_arc in state.arcs:
if label is None: if nfa_arc.label_or_string is None:
addclosure(next_, base) addclosure(nfa_arc.next, base)
base = {} base = {}
addclosure(start, base) addclosure(start, base)
states = [DFAState(base, finish)] states = [DFAState(base, finish)]
for state in states: # NB states grows while we're iterating for state in states: # NB states grows while we're iterating
arcs = {} arcs = {}
for nfastate in state.nfaset: for nfa_state in state.nfa_set:
for label, next_ in nfastate.arcs: for nfa_arc in nfa_state.arcs:
if label is not None: if nfa_arc.label_or_string is not None:
addclosure(next_, arcs.setdefault(label, {})) addclosure(nfa_arc.next, arcs.setdefault(nfa_arc.label_or_string, {}))
for label, nfaset in arcs.items(): for label_or_string, nfa_set in arcs.items():
for st in states: for st in states:
if st.nfaset == nfaset: if st.nfa_set == nfa_set:
break break
else: else:
st = DFAState(nfaset, finish) st = DFAState(nfa_set, finish)
states.append(st) states.append(st)
state.add_arc(st, label) state.add_arc(st, label_or_string)
return states # List of DFAState instances; first one is start return states # List of DFAState instances; first one is start