Use the name first_terminals instead of first

This commit is contained in:
Dave Halter
2018-06-17 18:09:12 +02:00
parent 95e4ecf592
commit b6cbf306d7

View File

@@ -29,19 +29,21 @@ class ParserGenerator(object):
self._nonterminal_to_dfas = rule_to_dfas self._nonterminal_to_dfas = rule_to_dfas
def make_grammar(self, grammar): def make_grammar(self, grammar):
self._first = {} # map from symbol name to set of tokens self._first_terminals = {} # map from symbol name to set of tokens
names = list(self._nonterminal_to_dfas.keys()) names = list(self._nonterminal_to_dfas.keys())
names.sort() names.sort()
for name in names: for name in names:
if name not in self._first: if name not in self._first_terminals:
self._calcfirst(name) self._calculate_first_terminals(name)
#print name, self._first[name].keys()
i = 256 + len(grammar.symbol2number) i = 256 + len(grammar.symbol2number)
grammar.symbol2number[name] = i grammar.symbol2number[name] = i
grammar.number2symbol[i] = name grammar.number2symbol[i] = name
# Now that we have calculated the first terminals, we are sure that
# there is no left recursion or ambiguities.
for name in names: for name in names:
dfas = self._nonterminal_to_dfas[name] dfas = self._nonterminal_to_dfas[name]
states = [] states = []
@@ -57,7 +59,7 @@ class ParserGenerator(object):
return grammar return grammar
def _make_first(self, grammar, name): def _make_first(self, grammar, name):
rawfirst = self._first[name] rawfirst = self._first_terminals[name]
first = set() first = set()
for label in rawfirst: for label in rawfirst:
ilabel = self._make_label(grammar, label) ilabel = self._make_label(grammar, label)
@@ -111,9 +113,11 @@ class ParserGenerator(object):
grammar.tokens[itoken] = ilabel grammar.tokens[itoken] = ilabel
return ilabel return ilabel
def _calcfirst(self, name): def _calculate_first_terminals(self, name):
dfas = self._nonterminal_to_dfas[name] dfas = self._nonterminal_to_dfas[name]
self._first[name] = None # dummy to detect left recursion self._first_terminals[name] = None # dummy to detect left recursion
# We only need to check the first dfa. All the following ones are not
# interesting to find first terminals.
state = dfas[0] state = dfas[0]
totalset = set() totalset = set()
overlapcheck = {} overlapcheck = {}
@@ -122,10 +126,10 @@ class ParserGenerator(object):
# It's a nonterminal and we have either a left recursion issue # It's a nonterminal and we have either a left recursion issue
# in the grammare or we have to recurse. # in the grammare or we have to recurse.
try: try:
fset = self._first[nonterminal_or_string] fset = self._first_terminals[nonterminal_or_string]
except KeyError: except KeyError:
self._calcfirst(nonterminal_or_string) self._calculate_first_terminals(nonterminal_or_string)
fset = self._first[nonterminal_or_string] fset = self._first_terminals[nonterminal_or_string]
else: else:
if fset is None: if fset is None:
raise ValueError("left recursion for rule %r" % name) raise ValueError("left recursion for rule %r" % name)
@@ -143,7 +147,7 @@ class ParserGenerator(object):
" first sets of %s as well as %s" % " first sets of %s as well as %s" %
(name, symbol, nonterminal_or_string, inverse[symbol])) (name, symbol, nonterminal_or_string, inverse[symbol]))
inverse[symbol] = nonterminal_or_string inverse[symbol] = nonterminal_or_string
self._first[name] = totalset self._first_terminals[name] = totalset
class DFAState(object): class DFAState(object):