name -> nonterminal

This commit is contained in:
Dave Halter
2018-06-17 23:10:27 +02:00
parent 73ce57428b
commit a06c3a3129
+19 -19
View File
@@ -32,21 +32,21 @@ class ParserGenerator(object):
# Map from grammar rule (nonterminal) name to a set of tokens. # Map from grammar rule (nonterminal) name to a set of tokens.
self._first_terminals = {} self._first_terminals = {}
names = list(self._nonterminal_to_dfas.keys()) nonterminals = list(self._nonterminal_to_dfas.keys())
names.sort() nonterminals.sort()
for name in names: for nonterminal in nonterminals:
if name not in self._first_terminals: if nonterminal not in self._first_terminals:
self._calculate_first_terminals(name) self._calculate_first_terminals(nonterminal)
i = 256 + len(grammar.nonterminal2number) i = 256 + len(grammar.nonterminal2number)
grammar.nonterminal2number[name] = i grammar.nonterminal2number[nonterminal] = i
grammar.number2nonterminal[i] = name grammar.number2nonterminal[i] = nonterminal
# Now that we have calculated the first terminals, we are sure that # Now that we have calculated the first terminals, we are sure that
# there is no left recursion or ambiguities. # there is no left recursion or ambiguities.
for name in names: for nonterminal in nonterminals:
dfas = self._nonterminal_to_dfas[name] dfas = self._nonterminal_to_dfas[nonterminal]
states = [] states = []
for state in dfas: for state in dfas:
arcs = [] arcs = []
@@ -56,11 +56,11 @@ class ParserGenerator(object):
arcs.append((0, dfas.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.nonterminal2number[name]] = (states, self._make_first(grammar, name)) grammar.dfas[grammar.nonterminal2number[nonterminal]] = (states, self._make_first(grammar, nonterminal))
return grammar return grammar
def _make_first(self, grammar, name): def _make_first(self, grammar, nonterminal):
rawfirst = self._first_terminals[name] rawfirst = self._first_terminals[nonterminal]
first = set() first = set()
for label in rawfirst: for label in rawfirst:
ilabel = self._make_label(grammar, label) ilabel = self._make_label(grammar, label)
@@ -74,7 +74,7 @@ class ParserGenerator(object):
if label[0].isalpha(): if label[0].isalpha():
# Either a nonterminal name or a named token # Either a nonterminal name or a named token
if label in grammar.nonterminal2number: if label in grammar.nonterminal2number:
# A nonterminal name (a non-terminal) # A nonterminal name
if label in grammar.nonterminal2label: if label in grammar.nonterminal2label:
return grammar.nonterminal2label[label] return grammar.nonterminal2label[label]
else: else:
@@ -114,9 +114,9 @@ class ParserGenerator(object):
grammar.tokens[itoken] = ilabel grammar.tokens[itoken] = ilabel
return ilabel return ilabel
def _calculate_first_terminals(self, name): def _calculate_first_terminals(self, nonterminal):
dfas = self._nonterminal_to_dfas[name] dfas = self._nonterminal_to_dfas[nonterminal]
self._first_terminals[name] = None # dummy to detect left recursion self._first_terminals[nonterminal] = None # dummy to detect left recursion
# We only need to check the first dfa. All the following ones are not # We only need to check the first dfa. All the following ones are not
# interesting to find first terminals. # interesting to find first terminals.
state = dfas[0] state = dfas[0]
@@ -133,7 +133,7 @@ class ParserGenerator(object):
fset = self._first_terminals[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" % nonterminal)
totalset.update(fset) totalset.update(fset)
overlapcheck[nonterminal_or_string] = fset overlapcheck[nonterminal_or_string] = fset
else: else:
@@ -147,9 +147,9 @@ class ParserGenerator(object):
if terminal in inverse: if terminal 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" %
(name, terminal, nonterminal_or_string, inverse[terminal])) (nonterminal, terminal, nonterminal_or_string, inverse[terminal]))
inverse[terminal] = nonterminal_or_string inverse[terminal] = nonterminal_or_string
self._first_terminals[name] = totalset self._first_terminals[nonterminal] = totalset
class DFAState(object): class DFAState(object):