mirror of
https://github.com/davidhalter/parso.git
synced 2026-11-05 02:02:49 +08:00
Try to completely remove the word symbol and use nonterminal
The ones that we could not remove are in grammar.py, because that's the public documented API.
This commit is contained in:
1 parent
640f544af9
commit
73ce57428b
7 files changed
+89
-86
No files matched your search
+19
-17
@@ -28,12 +28,14 @@ class Grammar(object):
|
||||
|
||||
The instance variables are as follows:
|
||||
|
||||
symbol2number -- a dict mapping symbol names to numbers. Symbol
|
||||
numbers are always 256 or higher, to distinguish
|
||||
them from token numbers, which are between 0 and
|
||||
255 (inclusive).
|
||||
nonterminal2number --
|
||||
A dict mapping nonterminal names to numbers.
|
||||
Nonterminal numbers are always 256 or higher, to
|
||||
distinguish them from token numbers, which are between 0
|
||||
and 255 (inclusive).
|
||||
|
||||
number2symbol -- a dict mapping numbers to symbol names;
|
||||
number2nonterminal --
|
||||
A dict mapping numbers to nonterminal names;
|
||||
these two are each other's inverse.
|
||||
|
||||
states -- a list of DFAs, where each DFA is a list of
|
||||
@@ -44,20 +46,20 @@ class Grammar(object):
|
||||
Final states are represented by a special arc of
|
||||
the form (0, j) where j is its own state number.
|
||||
|
||||
dfas -- a dict mapping symbol numbers to (DFA, first)
|
||||
dfas -- a dict mapping nonterminal numbers to (DFA, first)
|
||||
pairs, where DFA is an item from the states list
|
||||
above, and first is a set of tokens that can
|
||||
begin this grammar rule (represented by a dict
|
||||
whose values are always 1).
|
||||
|
||||
labels -- a list of (x, y) pairs where x is either a token
|
||||
number or a symbol number, and y is either None
|
||||
number or a nonterminal number, and y is either None
|
||||
or a string; the strings are keywords. The label
|
||||
number is the index in this list; label numbers
|
||||
are used to mark state transitions (arcs) in the
|
||||
DFAs.
|
||||
|
||||
start -- the number of the grammar's start symbol.
|
||||
start -- the number of the grammar's start nonterminal.
|
||||
|
||||
keywords -- a dict mapping keyword strings to arc labels.
|
||||
|
||||
@@ -65,29 +67,29 @@ class Grammar(object):
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, bnf_text, start_symbol):
|
||||
self.symbol2number = {}
|
||||
self.number2symbol = {}
|
||||
def __init__(self, bnf_text, start_nonterminal):
|
||||
self.nonterminal2number = {}
|
||||
self.number2nonterminal = {}
|
||||
self.states = []
|
||||
self.dfas = {}
|
||||
self.labels = [(0, "EMPTY")]
|
||||
self.keywords = {}
|
||||
self.tokens = {}
|
||||
self.symbol2label = {}
|
||||
self.label2symbol = {}
|
||||
self.start_symbol = start_symbol
|
||||
self.nonterminal2label = {}
|
||||
self.label2nonterminal = {}
|
||||
self.start_nonterminal = start_nonterminal
|
||||
|
||||
@property
|
||||
def start(self):
|
||||
return self.symbol2number[self.start_symbol]
|
||||
return self.nonterminal2number[self.start_nonterminal]
|
||||
|
||||
def report(self):
|
||||
"""Dump the grammar tables to standard output, for debugging."""
|
||||
from pprint import pprint
|
||||
print("s2n")
|
||||
pprint(self.symbol2number)
|
||||
pprint(self.nonterminal2number)
|
||||
print("n2s")
|
||||
pprint(self.number2symbol)
|
||||
pprint(self.number2nonterminal)
|
||||
print("states")
|
||||
pprint(self.states)
|
||||
print("dfas")
|
||||
|
||||
@@ -118,8 +118,8 @@ class PgenParser(object):
|
||||
up.
|
||||
|
||||
A concrete syntax tree node is a (type, nodes) tuple, where
|
||||
type is the node type (a token or symbol number) and nodes
|
||||
is a list of children for symbols, and None for tokens.
|
||||
type is the node type (a token or nonterminal number) and nodes
|
||||
is a list of children for nonterminals, and None for tokens.
|
||||
|
||||
An abstract syntax tree node may be anything; this is entirely
|
||||
up to the converter function.
|
||||
@@ -184,11 +184,11 @@ class PgenParser(object):
|
||||
# Done with this token
|
||||
return False
|
||||
elif t >= 256:
|
||||
# See if it's a symbol and if we're in its first set
|
||||
# See if it's a nonterminal and if we're in its first set
|
||||
itsdfa = _gram.dfas[t]
|
||||
itsstates, itsfirst = itsdfa
|
||||
if ilabel in itsfirst:
|
||||
# Push a symbol
|
||||
# Push a nonterminal
|
||||
_push(t, itsdfa, newstate)
|
||||
break # To continue the outer while loop
|
||||
else:
|
||||
@@ -231,7 +231,7 @@ class PgenParser(object):
|
||||
try:
|
||||
# Equal to:
|
||||
# dfa, state, node = self.stack[-1]
|
||||
# symbol, children = node
|
||||
# nonterminal, children = node
|
||||
self.stack[-1][2][1].append(newnode)
|
||||
except IndexError:
|
||||
# Stack is empty, set the rootnode.
|
||||
|
||||
+18
-17
@@ -29,7 +29,8 @@ class ParserGenerator(object):
|
||||
self._nonterminal_to_dfas = rule_to_dfas
|
||||
|
||||
def make_grammar(self, grammar):
|
||||
self._first_terminals = {} # map from symbol name to set of tokens
|
||||
# Map from grammar rule (nonterminal) name to a set of tokens.
|
||||
self._first_terminals = {}
|
||||
|
||||
names = list(self._nonterminal_to_dfas.keys())
|
||||
names.sort()
|
||||
@@ -37,9 +38,9 @@ class ParserGenerator(object):
|
||||
if name not in self._first_terminals:
|
||||
self._calculate_first_terminals(name)
|
||||
|
||||
i = 256 + len(grammar.symbol2number)
|
||||
grammar.symbol2number[name] = i
|
||||
grammar.number2symbol[i] = name
|
||||
i = 256 + len(grammar.nonterminal2number)
|
||||
grammar.nonterminal2number[name] = i
|
||||
grammar.number2nonterminal[i] = name
|
||||
|
||||
# Now that we have calculated the first terminals, we are sure that
|
||||
# there is no left recursion or ambiguities.
|
||||
@@ -55,7 +56,7 @@ class ParserGenerator(object):
|
||||
arcs.append((0, dfas.index(state)))
|
||||
states.append(arcs)
|
||||
grammar.states.append(states)
|
||||
grammar.dfas[grammar.symbol2number[name]] = (states, self._make_first(grammar, name))
|
||||
grammar.dfas[grammar.nonterminal2number[name]] = (states, self._make_first(grammar, name))
|
||||
return grammar
|
||||
|
||||
def _make_first(self, grammar, name):
|
||||
@@ -71,15 +72,15 @@ class ParserGenerator(object):
|
||||
# XXX Maybe this should be a method on a subclass of converter?
|
||||
ilabel = len(grammar.labels)
|
||||
if label[0].isalpha():
|
||||
# Either a symbol name or a named token
|
||||
if label in grammar.symbol2number:
|
||||
# A symbol name (a non-terminal)
|
||||
if label in grammar.symbol2label:
|
||||
return grammar.symbol2label[label]
|
||||
# Either a nonterminal name or a named token
|
||||
if label in grammar.nonterminal2number:
|
||||
# A nonterminal name (a non-terminal)
|
||||
if label in grammar.nonterminal2label:
|
||||
return grammar.nonterminal2label[label]
|
||||
else:
|
||||
grammar.labels.append((grammar.symbol2number[label], None))
|
||||
grammar.symbol2label[label] = ilabel
|
||||
grammar.label2symbol[ilabel] = label
|
||||
grammar.labels.append((grammar.nonterminal2number[label], None))
|
||||
grammar.nonterminal2label[label] = ilabel
|
||||
grammar.label2nonterminal[ilabel] = label
|
||||
return ilabel
|
||||
else:
|
||||
# A named token (NAME, NUMBER, STRING)
|
||||
@@ -293,7 +294,7 @@ def generate_grammar(bnf_grammar, token_namespace):
|
||||
own parser.
|
||||
"""
|
||||
rule_to_dfas = {}
|
||||
start_symbol = None
|
||||
start_nonterminal = None
|
||||
for nfa_a, nfa_z in GrammarParser(bnf_grammar).parse():
|
||||
#_dump_nfa(a, z)
|
||||
dfas = _make_dfas(nfa_a, nfa_z)
|
||||
@@ -304,8 +305,8 @@ def generate_grammar(bnf_grammar, token_namespace):
|
||||
rule_to_dfas[nfa_a.from_rule] = dfas
|
||||
#print(nfa_a.from_rule, oldlen, newlen)
|
||||
|
||||
if start_symbol is None:
|
||||
start_symbol = nfa_a.from_rule
|
||||
if start_nonterminal is None:
|
||||
start_nonterminal = nfa_a.from_rule
|
||||
|
||||
p = ParserGenerator(rule_to_dfas, token_namespace)
|
||||
return p.make_grammar(Grammar(bnf_grammar, start_symbol))
|
||||
return p.make_grammar(Grammar(bnf_grammar, start_nonterminal))
|
||||
Reference in new issue
Block a user