alex / rply

An attempt to port David Beazley's PLY to RPython, and give it a cooler API.
BSD 3-Clause "New" or "Revised" License
381 stars 60 forks source link

Better warnings for conflicts #28

Open djc opened 10 years ago

djc commented 10 years ago

It would be nice if conflicts would report something a little more actionable than just the fact that a conflict exists. For example, reporting a relevant LRItem provides a clue, at least.

prologic commented 10 years ago

+1

mcepl commented 9 years ago

The same for parser errors. Simple ParsingError is kind of useless.

djc commented 8 years ago

I have something like this now, for reduce/reduce conflicts, does that look good? Warning output:

rnc2rng/parser.py:328: ParserGeneratorWarning: 10 reduce/reduce conflicts:
  'particle-choice -> inner-particle' vs 'particle-group -> inner-particle'
  'particle-choice -> inner-particle' vs 'particle-group -> inner-particle'
  'particle-choice -> inner-particle' vs 'particle-group -> inner-particle'
  'particle-choice -> inner-particle' vs 'particle-group -> inner-particle'
  'particle-choice -> inner-particle' vs 'particle-group -> inner-particle'
  'particle-choice -> inner-particle' vs 'particle-interleave -> inner-particle'
  'particle-choice -> inner-particle' vs 'particle-interleave -> inner-particle'
  'particle-choice -> inner-particle' vs 'particle-interleave -> inner-particle'
  'particle-choice -> inner-particle' vs 'particle-interleave -> inner-particle'
  'particle-choice -> inner-particle' vs 'particle-interleave -> inner-particle'
  parser = pg.build()

Here's the code change, I assume this would need tests:

diff --git a/rply/parsergenerator.py b/rply/parsergenerator.py
index 243705f..9ca2a25 100644
--- a/rply/parsergenerator.py
+++ b/rply/parsergenerator.py
@@ -205,10 +205,15 @@ class ParserGenerator(object):
                 stacklevel=2,
             )
         if table.rr_conflicts:
+            conflicts = table.rr_conflicts
+            prod_str = lambda s: s.split('(', 1)[1][:-1]
+            printable = [(prod_str(i[1]), prod_str(i[2])) for i in conflicts]
+            details = '\n'.join('  %r vs %r' % i for i in printable)
             warnings.warn(
-                "%d reduce/reduce conflict%s" % (
+                "%d reduce/reduce conflict%s:\n%s" % (
                     len(table.rr_conflicts),
-                    "s" if len(table.rr_conflicts) > 1 else ""
+                    "s" if len(conflicts) > 1 else "",
+                    details,
                 ),
                 ParserGeneratorWarning,
                 stacklevel=2,
refi64 commented 8 years ago

FWIW, PLY puts the conflict info in a parser.out file.

nobodxbodon commented 3 years ago

+1 it'll be a great help when there are hundreds of production rules. Trying to get some output for shift/reduce conflicts now.