Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 70 additions & 58 deletions rply/parsergenerator.py
Original file line number Diff line number Diff line change
Expand Up @@ -316,74 +316,86 @@ def from_grammar(cls, grammar):
st_goto = {}
for p in I:
if p.getlength() == p.lr_index + 1:

if p.name == "S'":
# Start symbol. Accept!
st_action["$end"] = 0
st_actionp["$end"] = p
else:
laheads = p.lookaheads[st]
for a in laheads:
if a in st_action:
r = st_action[a]
if r > 0:
sprec, slevel = grammar.productions[st_actionp[a].number].prec
rprec, rlevel = grammar.precedence.get(a, ("right", 0))
if (slevel < rlevel) or (slevel == rlevel and rprec == "left"):
st_action[a] = -p.number
st_actionp[a] = p
if not slevel and not rlevel:
sr_conflicts.append((st, repr(a), "reduce"))
grammar.productions[p.number].reduced += 1
elif not (slevel == rlevel and rprec == "nonassoc"):
if not rlevel:
sr_conflicts.append((st, repr(a), "shift"))
elif r < 0:
oldp = grammar.productions[-r]
pp = grammar.productions[p.number]
if oldp.number > pp.number:
st_action[a] = -p.number
st_actionp[a] = p
chosenp, rejectp = pp, oldp
grammar.productions[p.number].reduced += 1
grammar.productions[oldp.number].reduced -= 1
else:
chosenp, rejectp = oldp, pp
rr_conflicts.append((st, repr(chosenp), repr(rejectp)))
else:
raise ParserGeneratorError("Unknown conflict in state %d" % st)
else:
continue

laheads = p.lookaheads[st]
for a in laheads:

if a not in st_action:
st_action[a] = -p.number
st_actionp[a] = p
grammar.productions[p.number].reduced += 1
continue

r = st_action[a]
if r > 0:
sprec, slevel = grammar.productions[st_actionp[a].number].prec
rprec, rlevel = grammar.precedence.get(a, ("right", 0))
if (slevel < rlevel) or (slevel == rlevel and rprec == "left"):
st_action[a] = -p.number
st_actionp[a] = p
if not slevel and not rlevel:
sr_conflicts.append((st, repr(a), "reduce"))
grammar.productions[p.number].reduced += 1
elif not (slevel == rlevel and rprec == "nonassoc"):
if not rlevel:
sr_conflicts.append((st, repr(a), "shift"))
elif r < 0:
oldp = grammar.productions[-r]
pp = grammar.productions[p.number]
if oldp.number > pp.number:
st_action[a] = -p.number
st_actionp[a] = p
chosenp, rejectp = pp, oldp
grammar.productions[p.number].reduced += 1
grammar.productions[oldp.number].reduced -= 1
else:
chosenp, rejectp = oldp, pp
rr_conflicts.append((st, repr(chosenp), repr(rejectp)))
else:
raise ParserGeneratorError("Unknown conflict in state %d" % st)

else:

i = p.lr_index
a = p.prod[i + 1]
if a in grammar.terminals:
g = cls.lr0_goto(I, a, add_count, goto_cache)
j = cidhash.get(g, -1)
if j >= 0:
if a in st_action:
r = st_action[a]
if r > 0:
if r != j:
raise ParserGeneratorError("Shift/shift conflict in state %d" % st)
elif r < 0:
rprec, rlevel = grammar.productions[st_actionp[a].number].prec
sprec, slevel = grammar.precedence.get(a, ("right", 0))
if (slevel > rlevel) or (slevel == rlevel and rprec == "right"):
grammar.productions[st_actionp[a].number].reduced -= 1
st_action[a] = j
st_actionp[a] = p
if not rlevel:
sr_conflicts.append((st, repr(a), "shift"))
elif not (slevel == rlevel and rprec == "nonassoc"):
if not slevel and not rlevel:
sr_conflicts.append((st, repr(a), "reduce"))
else:
raise ParserGeneratorError("Unknown conflict in state %d" % st)
else:
st_action[a] = j
st_actionp[a] = p
if a not in grammar.terminals:
continue

g = cls.lr0_goto(I, a, add_count, goto_cache)
j = cidhash.get(g, -1)
if j < 0:
continue

if a not in st_action:
st_action[a] = j
st_actionp[a] = p
continue

r = st_action[a]
if r > 0:
if r != j:
raise ParserGeneratorError("Shift/shift conflict in state %d" % st)
elif r < 0:
rprec, rlevel = grammar.productions[st_actionp[a].number].prec
sprec, slevel = grammar.precedence.get(a, ("right", 0))
if (slevel > rlevel) or (slevel == rlevel and rprec == "right"):
grammar.productions[st_actionp[a].number].reduced -= 1
st_action[a] = j
st_actionp[a] = p
if not rlevel:
sr_conflicts.append((st, repr(a), "shift"))
elif not (slevel == rlevel and rprec == "nonassoc"):
if not slevel and not rlevel:
sr_conflicts.append((st, repr(a), "reduce"))
else:
raise ParserGeneratorError("Unknown conflict in state %d" % st)

nkeys = set()
for ii in I:
for s in ii.unique_syms:
Expand Down