Conflicting examples.
This commit is contained in:
parent
9781765043
commit
5a0b1654a9
1 changed files with 28 additions and 10 deletions
38
parser.py
38
parser.py
|
|
@ -1,6 +1,7 @@
|
||||||
# This is doty playing with parser tables.
|
# This is doty playing with parser tables.
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
|
|
||||||
class Configuration(
|
class Configuration(
|
||||||
namedtuple('Configuration', ['name', 'symbols', 'position'])
|
namedtuple('Configuration', ['name', 'symbols', 'position'])
|
||||||
):
|
):
|
||||||
|
|
@ -188,8 +189,8 @@ class GenerateLR0(object):
|
||||||
def gen_table(self):
|
def gen_table(self):
|
||||||
"""Generate the parse table.
|
"""Generate the parse table.
|
||||||
|
|
||||||
The parse table is a list of states. The first state in the list is the starting
|
The parse table is a list of states. The first state in the list is
|
||||||
state. Each state is a dictionary that maps a symbol to an
|
the starting state. Each state is a dictionary that maps a symbol to an
|
||||||
action. Each action is a tuple. The first element of the tuple is a
|
action. Each action is a tuple. The first element of the tuple is a
|
||||||
string describing what to do:
|
string describing what to do:
|
||||||
|
|
||||||
|
|
@ -259,16 +260,13 @@ class GenerateLR0(object):
|
||||||
there is already an action for the symbol in the row.
|
there is already an action for the symbol in the row.
|
||||||
"""
|
"""
|
||||||
existing = row.get(symbol, None)
|
existing = row.get(symbol, None)
|
||||||
if existing is not None:
|
if existing is not None and existing != action:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"Conflict: {old} vs {new}",
|
"Conflict: {old} vs {new}".format(old=existing, new=action)
|
||||||
old=existing,
|
|
||||||
new=action,
|
|
||||||
)
|
)
|
||||||
row[symbol] = 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
|
||||||
concrete syntax tree.
|
concrete syntax tree.
|
||||||
|
|
@ -370,7 +368,7 @@ def format_table(generator, table):
|
||||||
return '\n'.join(lines)
|
return '\n'.join(lines)
|
||||||
|
|
||||||
|
|
||||||
# OK, this is
|
# OK, this is a very simple LR0 grammar.
|
||||||
grammar_simple = [
|
grammar_simple = [
|
||||||
('E', ['E', '+', 'T']),
|
('E', ['E', '+', 'T']),
|
||||||
('E', ['T']),
|
('E', ['T']),
|
||||||
|
|
@ -383,5 +381,25 @@ table = gen.gen_table()
|
||||||
tree = parse(table, ['id', '+', '(', 'id', ')'])
|
tree = parse(table, ['id', '+', '(', 'id', ')'])
|
||||||
print(format_node(tree))
|
print(format_node(tree))
|
||||||
|
|
||||||
grammar_lr0_conflict = [
|
# This one doesn't work with LR0, though, it has a shift/reduce conflict.
|
||||||
]
|
try:
|
||||||
|
grammar_lr0_conflict = grammar_simple + [
|
||||||
|
('T', ['id', '[', 'E', ']']),
|
||||||
|
]
|
||||||
|
gen = GenerateLR0(grammar_lr0_conflict, 'E')
|
||||||
|
table = gen.gen_table()
|
||||||
|
assert False
|
||||||
|
except ValueError as e:
|
||||||
|
print(e)
|
||||||
|
|
||||||
|
# Nor does this: it has a reduce/reduce conflict.
|
||||||
|
try:
|
||||||
|
grammar_lr0_conflict = grammar_simple + [
|
||||||
|
('E', ['V', '=', 'E']),
|
||||||
|
('V', ['id']),
|
||||||
|
]
|
||||||
|
gen = GenerateLR0(grammar_lr0_conflict, 'E')
|
||||||
|
table = gen.gen_table()
|
||||||
|
assert False
|
||||||
|
except ValueError as e:
|
||||||
|
print(e)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue