Make grammar generation deterministic.

This commit is contained in:
Valentin Lorentz
2015-08-19 20:33:41 +02:00
parent 78ac97231a
commit 4e770270cf

View File

@@ -4,6 +4,7 @@
from __future__ import print_function from __future__ import print_function
from six import iteritems from six import iteritems
from collections import OrderedDict
# Pgen imports # Pgen imports
@@ -57,7 +58,7 @@ class ParserGenerator(object):
def make_first(self, c, name): def make_first(self, c, name):
rawfirst = self.first[name] rawfirst = self.first[name]
first = {} first = {}
for label in rawfirst: for label in sorted(rawfirst):
ilabel = self.make_label(c, label) ilabel = self.make_label(c, label)
##assert ilabel not in first # X X X failed on <> ... != ##assert ilabel not in first # X X X failed on <> ... !=
first[ilabel] = 1 first[ilabel] = 1
@@ -138,8 +139,8 @@ class ParserGenerator(object):
totalset[label] = 1 totalset[label] = 1
overlapcheck[label] = {label: 1} overlapcheck[label] = {label: 1}
inverse = {} inverse = {}
for label, itsfirst in iteritems(overlapcheck): for label, itsfirst in sorted(overlapcheck.items()):
for symbol in itsfirst: for symbol in sorted(itsfirst):
if symbol in inverse: if symbol in inverse:
raise ValueError("rule %s is ambiguous; %s is in the" raise ValueError("rule %s is ambiguous; %s is in the"
" first sets of %s as well as %s" % " first sets of %s as well as %s" %
@@ -349,6 +350,9 @@ class NFAState(object):
assert isinstance(next, NFAState) assert isinstance(next, NFAState)
self.arcs.append((label, next)) self.arcs.append((label, next))
def __hash__(self):
return hash(tuple(x[0] for x in self.arcs))
class DFAState(object): class DFAState(object):
def __init__(self, nfaset, final): def __init__(self, nfaset, final):
@@ -357,7 +361,10 @@ class DFAState(object):
assert isinstance(final, NFAState) assert isinstance(final, NFAState)
self.nfaset = nfaset self.nfaset = nfaset
self.isfinal = final in nfaset self.isfinal = final in nfaset
self.arcs = {} # map from label to DFAState self.arcs = OrderedDict() # map from label to DFAState
def __hash__(self):
return hash(tuple(self.arcs))
def addarc(self, next, label): def addarc(self, next, label):
assert isinstance(label, str) assert isinstance(label, str)