Detect conflicts in the table generation.
This commit is contained in:
parent
edd5ee3d55
commit
c1ecf8e260
1 changed files with 31 additions and 6 deletions
37
parser.py
37
parser.py
|
|
@ -192,6 +192,8 @@ class GenerateLR0(object):
|
||||||
the other actions are always associated with terminals.)
|
the other actions are always associated with terminals.)
|
||||||
|
|
||||||
- 'accept': Accept the result of the parse, it worked.
|
- 'accept': Accept the result of the parse, it worked.
|
||||||
|
|
||||||
|
Anything missing from the row indicates an error.
|
||||||
"""
|
"""
|
||||||
action_table = []
|
action_table = []
|
||||||
config_sets = self.gen_all_sets()
|
config_sets = self.gen_all_sets()
|
||||||
|
|
@ -202,17 +204,24 @@ class GenerateLR0(object):
|
||||||
for config in config_set:
|
for config in config_set:
|
||||||
if config.at_end:
|
if config.at_end:
|
||||||
if config.name != '__start':
|
if config.name != '__start':
|
||||||
actions.update({
|
for a in self.terminals:
|
||||||
a: ('reduce', config.name, len(config.symbols))
|
self.set_table_action(
|
||||||
for a in self.terminals
|
actions,
|
||||||
})
|
a,
|
||||||
|
('reduce', config.name, len(config.symbols)),
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
actions['$'] = ('accept',)
|
self.set_table_action(actions, '$', ('accept',))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if config.next in self.terminals:
|
if config.next in self.terminals:
|
||||||
successor = self.gen_successor(config_set, config.next)
|
successor = self.gen_successor(config_set, config.next)
|
||||||
index = self.find_set_index(config_sets, successor)
|
index = self.find_set_index(config_sets, successor)
|
||||||
actions[config.next] = ('shift', index)
|
self.set_table_action(
|
||||||
|
actions,
|
||||||
|
config.next,
|
||||||
|
('shift', index),
|
||||||
|
)
|
||||||
|
|
||||||
# Gotos
|
# Gotos
|
||||||
for symbol in self.nonterminals:
|
for symbol in self.nonterminals:
|
||||||
|
|
@ -225,6 +234,22 @@ class GenerateLR0(object):
|
||||||
|
|
||||||
return action_table
|
return action_table
|
||||||
|
|
||||||
|
def set_table_action(self, row, symbol, action):
|
||||||
|
"""Set the action for 'symbol' in the table row to 'action'.
|
||||||
|
|
||||||
|
This is destructive; it changes the table. It raises an error if
|
||||||
|
there is already an action for the symbol in the row.
|
||||||
|
"""
|
||||||
|
existing = row.get(symbol, None)
|
||||||
|
if existing is not None:
|
||||||
|
raise ValueError(
|
||||||
|
"Conflict: {old} vs {new}",
|
||||||
|
old=existing,
|
||||||
|
new=action,
|
||||||
|
)
|
||||||
|
row[symbol] = action
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def parse(table, input, trace=False):
|
def parse(table, input, trace=False):
|
||||||
"""Parse the input with the generated parsing table and return the
|
"""Parse the input with the generated parsing table and return the
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue