[PATCH 5/5] cex: display the rule numbers

Akim Demaille <[email protected]>
Newsgroups gmane.comp.parsers.bison.patches
Message-ID <[email protected]>
From

    Example: "if" expr "then" "if" expr "then" stmt • "else" stmt
    Shift derivation
      if_stmt
      ↳ "if" expr "then" stmt
                         ↳ if_stmt
                           ↳ "if" expr "then" stmt • "else" stmt
    Reduce derivation
      if_stmt
      ↳ "if" expr "then" stmt                        "else" stmt
                         ↳ if_stmt
                           ↳ "if" expr "then" stmt •

to

    Example: "if" expr "then" "if" expr "then" stmt • "else" stmt
    Shift derivation
      if_stmt
      ↳ 3: "if" expr "then" stmt
                            ↳ 2: if_stmt
                                 ↳ 4: "if" expr "then" stmt • "else" stmt
    Example: "if" expr "then" "if" expr "then" stmt • "else" stmt
    Reduce derivation
      if_stmt
      ↳ 4: "if" expr "then" stmt                              "else" stmt
                            ↳ 2: if_stmt
                                 ↳ 3: "if" expr "then" stmt •

* src/state-item.h, src/state-item.c (state_item_rule): New.
* src/derivation.h, src/derivation.c (struct derivation): Add a rule
member.
Adjust dependencies.
* src/counterexample.c, src/parse-simulation.c: Pass the rule to
derivation_new.
* src/derivation.c (fprintf_if): New.
(derivation_width, derivation_print_tree_impl): Take the rule number
into account.

* tests/conflicts.at, tests/counterexample.at, tests/diagnostics.at,
* tests/report.at: Adjust.
---
 src/counterexample.c    |   5 +-
 src/derivation.c        |  28 ++-
 src/derivation.h        |   7 +-
 src/parse-simulation.c  |   6 +-
 src/state-item.c        |   6 +
 src/state-item.h        |   1 +
 tests/conflicts.at      |  44 ++---
 tests/counterexample.at | 370 ++++++++++++++++++++--------------------
 tests/diagnostics.at    |  66 +++----
 tests/report.at         |  88 +++++-----
 10 files changed, 330 insertions(+), 291 deletions(-)

diff --git a/src/counterexample.c b/src/counterexample.c
index cdf3f218..c0dc796c 100644
--- a/src/counterexample.c
+++ b/src/counterexample.c
@@ -293,7 +293,8 @@ expand_to_conflict (state_item_number start, symbol_number conflict_sym)
             derivation_list_append (result, derivation_new_leaf (*i));
           symbol_number lhs =
             rules[item_number_as_rule_number (*i)].lhs->number;
-          derivation *deriv = derivation_new (lhs, result);
+          derivation *deriv = derivation_new (lhs, result,
+                                              state_item_rule (si));
           result = derivation_list_new ();
           derivation_list_append (result, deriv);
         }
@@ -427,7 +428,7 @@ complete_diverging_example (symbol_number conflict_sym,
             derivation_list_prepend (result, derivation_new_leaf (*i));
         }
       // completing the derivation
-      derivation *new_deriv = derivation_new (r->lhs->number, result);
+      derivation *new_deriv = derivation_new (r->lhs->number, result, r);
       result = derivation_list_new ();
       derivation_list_append (result, new_deriv);
     }
diff --git a/src/derivation.c b/src/derivation.c
index 9772cabd..030cc17b 100644
--- a/src/derivation.c
+++ b/src/derivation.c
@@ -25,6 +25,7 @@
 #include <c-ctype.h>
 #include <gl_linked_list.h>
 #include <mbswidth.h>
+#include <vasnprintf.h>
 
 #include "system.h"
 #include "complain.h"
@@ -34,13 +35,15 @@ struct derivation
   symbol_number sym;
   derivation_list children;
   int reference_count;
+  // The rule SYM -> CHILDREN.
+  const rule *rule;
   // Color assigned for styling.  Guarantees that the derivation is
   // always displayed with the same color, independently of the order
   // in which the derivations are traversed.
   int color;
 };
 
-static derivation d_dot = { -1, NULL, -1, -1 };
+static derivation d_dot = { -1, NULL, -1, NULL, -1 };
 
 derivation *
 derivation_dot (void)
@@ -74,12 +77,14 @@ void derivation_list_free (derivation_list dl)
 }
 
 derivation *
-derivation_new (symbol_number sym, derivation_list children)
+derivation_new (symbol_number sym, derivation_list children,
+                const rule *r)
 {
   derivation *res = xmalloc (sizeof *res);
   res->sym = sym;
   res->children = children;
   res->reference_count = 0;
+  res->rule = r;
   res->color = -1;
   return res;
 }
@@ -211,6 +216,23 @@ fputs_if (bool cond, FILE *out, int *padding, const char *s)
   return res;
 }
 
+static int
+fprintf_if (bool cond, FILE *out, int *padding, const char *fmt, ...)
+{
+  char buf[256];
+  size_t len = sizeof (buf);
+  va_list args;
+  va_start (args, fmt);
+  char *cp = vasnprintf (buf, &len, fmt, args);
+  va_end (args);
+  if (!cp)
+    xalloc_die ();
+  int res = fputs_if (cond, out, padding, cp);
+  if (cp != buf)
+    free (cp);
+  return res;
+}
+
 // The width taken to report this derivation recursively down to its
 // leaves.
 static int
@@ -223,6 +245,7 @@ derivation_width (const derivation *deriv)
 
       // Arrow and space.
       int children_width = down_arrow_width;
+      children_width += snprintf (NULL, 0, "%d: ", deriv->rule->number);
       if (gl_list_size (deriv->children) == 0)
         // Empty rhs.
         children_width += empty_width;
@@ -287,6 +310,7 @@ derivation_print_tree_impl (const derivation *deriv, FILE *out,
       else
         {
           res += fputs_if (depth == 1, out, padding, down_arrow);
+          res += fprintf_if (depth == 1, out, padding, "%d: ", deriv->rule->number);
           if (gl_list_size (deriv->children) == 0)
             // Empty rhs.
             res += fputs_if (depth == 1, out, padding, empty);
diff --git a/src/derivation.h b/src/derivation.h
index 4dfba945..3f376642 100644
--- a/src/derivation.h
+++ b/src/derivation.h
@@ -54,11 +54,14 @@ void derivation_list_append (derivation_list dl, derivation *d);
 void derivation_list_prepend (derivation_list dl, derivation *d);
 void derivation_list_free (derivation_list dl);
 
-derivation *derivation_new (symbol_number sym, derivation_list children);
+// rule_num is the number of the rule SYM -> CHILDREN.
+derivation *
+derivation_new (symbol_number sym, derivation_list children,
+                const rule *r);
 
 static inline derivation *derivation_new_leaf (symbol_number sym)
 {
-  return derivation_new (sym, NULL);
+  return derivation_new (sym, NULL, NULL);
 }
 
 // Number of symbols.
diff --git a/src/parse-simulation.c b/src/parse-simulation.c
index ba09c44c..764a62e0 100644
--- a/src/parse-simulation.c
+++ b/src/parse-simulation.c
@@ -421,7 +421,9 @@ nullable_closure (parse_state *ps, state_item *si, parse_state_list state_list)
       state_item *nsi = &state_items[sin];
       current_ps = copy_parse_state (false, current_ps);
       ps_si_append (current_ps, nsi);
-      ps_derivs_append (current_ps, derivation_new (sp, derivation_list_new ()));
+      ps_derivs_append (current_ps,
+                        derivation_new (sp, derivation_list_new (),
+                                        state_item_rule (nsi)));
       parse_state_list_append (state_list, current_ps);
     }
 }
@@ -516,7 +518,7 @@ simulate_reduction (parse_state *ps, int rule_len, bitset symbol_set)
   state_item *si = (state_item *) ps->state_items.tail_elt;
   const rule *r = item_rule (si->item);
   symbol_number lhs = r->lhs->number;
-  derivation *deriv = derivation_new (lhs, popped_derivs);
+  derivation *deriv = derivation_new (lhs, popped_derivs, state_item_rule (si));
   --new_root->depth;
   ps_derivs_append (new_root, deriv);
 
diff --git a/src/state-item.c b/src/state-item.c
index a0c5a31a..a56be1f2 100644
--- a/src/state-item.c
+++ b/src/state-item.c
@@ -482,6 +482,12 @@ state_item_print (const state_item *si, FILE *out, const char *prefix)
   putc ('\n', out);
 }
 
+const rule*
+state_item_rule (const state_item *si)
+{
+  return item_rule (si->item);
+}
+
 /**
  * Report the state_item graph
  */
diff --git a/src/state-item.h b/src/state-item.h
index a0a3d36f..bfe9f8be 100644
--- a/src/state-item.h
+++ b/src/state-item.h
@@ -93,6 +93,7 @@ void state_items_init (void);
 void state_items_free (void);
 
 void state_item_print (const state_item *si, FILE *out, const char *prefix);
+const rule *state_item_rule (const state_item *si);
 
 bool production_allowed (const state_item *si, const state_item *next);
 
diff --git a/tests/conflicts.at b/tests/conflicts.at
index 2b6f4315..f103a4e1 100644
--- a/tests/conflicts.at
+++ b/tests/conflicts.at
@@ -867,12 +867,12 @@ State 5
       Example: exp OP exp . OP exp
       Shift derivation
         exp
-        `-> exp OP exp
-                   `-> exp . OP exp
+        `-> 1: exp OP exp
+                      `-> 1: exp . OP exp
       Reduce derivation
         exp
-        `-> exp              OP exp
-            `-> exp OP exp .
+        `-> 1: exp                 OP exp
+               `-> 1: exp OP exp .
 
 ]])
 
@@ -1215,12 +1215,12 @@ State 1
       Example: '0' .
       First reduce derivation
         exp
-        `-> num
-            `-> '0' .
+        `-> 1: num
+               `-> 3: '0' .
       Second reduce derivation
         exp
-        `-> id
-            `-> '0' .
+        `-> 2: id
+               `-> 4: '0' .
 
 
 
@@ -1770,13 +1770,13 @@ State 4
       First example: resolved_conflict . 'a' 'a'
       Shift derivation
         start
-        `-> resolved_conflict reported_conflicts 'a'
-                              `-> . 'a'
+        `-> 1: resolved_conflict reported_conflicts 'a'
+                                 `-> 8: . 'a'
       Second example: resolved_conflict . 'a'
       Reduce derivation
         start
-        `-> resolved_conflict reported_conflicts 'a'
-                              `-> .
+        `-> 1: resolved_conflict reported_conflicts 'a'
+                                 `-> 10: .
 
     shift/reduce conflict on token 'a':
        10 reported_conflicts: . %empty
@@ -1784,13 +1784,13 @@ State 4
       First example: resolved_conflict . 'a' 'a'
       Shift derivation
         start
-        `-> resolved_conflict reported_conflicts 'a'
-                              `-> . 'a'
+        `-> 1: resolved_conflict reported_conflicts 'a'
+                                 `-> 9: . 'a'
       Second example: resolved_conflict . 'a'
       Reduce derivation
         start
-        `-> resolved_conflict reported_conflicts 'a'
-                              `-> .
+        `-> 1: resolved_conflict reported_conflicts 'a'
+                                 `-> 10: .
 
 
 
@@ -1809,10 +1809,10 @@ State 5
       Example: 'a' .
       First reduce derivation
         reported_conflicts
-        `-> 'a' .
+        `-> 8: 'a' .
       Second reduce derivation
         reported_conflicts
-        `-> 'a' .
+        `-> 9: 'a' .
 
 
 
@@ -1999,12 +1999,12 @@ AT_CHECK([[cat input.output | sed -n '/^State 0$/,/^State 1$/p']], 0,
       Example: . 'c'
       First reduce derivation
         start
-        `-> empty_c2 'c'
-            `-> .
+        `-> 7: empty_c2  'c'
+               `-> 12: .
       Second reduce derivation
         start
-        `-> empty_c3 'c'
-            `-> .
+        `-> 8: empty_c3  'c'
+               `-> 13: .
 
 
 
diff --git a/tests/counterexample.at b/tests/counterexample.at
index 4d1709a6..bd9c1e96 100644
--- a/tests/counterexample.at
+++ b/tests/counterexample.at
@@ -58,12 +58,12 @@ input.y: warning: shift/reduce conflict on token B [-Wcounterexamples]
   Example: A . B C
   Shift derivation
     s
-    `-> y         c
-        `-> A . B `-> C
+    `-> 2: y            c
+           `-> 8: A . B `-> 4: C
   Reduce derivation
     s
-    `-> a       x
-        `-> A . `-> B C
+    `-> 1: a          x
+           `-> 3: A . `-> 6: B C
 input.y:4.4: warning: rule useless in parser due to conflicts [-Wother]
 ]],
 [[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
@@ -98,29 +98,29 @@ input.y: warning: shift/reduce conflict on token B [-Wcounterexamples]
   Example: A . B C
   Shift derivation
     s
-    `-> ac
-        `-> A ac          C
-              `-> b
-                  `-> . B
+    `-> 1: ac
+           `-> 3: A ac                C
+                    `-> 4: b
+                           `-> 5: . B
   Reduce derivation
     s
-    `-> a       bc
-        `-> A . `-> B C
+    `-> 2: a          bc
+           `-> 7: A . `-> 10: B C
 input.y: warning: shift/reduce conflict on token B [-Wcounterexamples]
   Example: A A . B B C C
   Shift derivation
     s
-    `-> ac
-        `-> A ac                        C
-              `-> A ac                C
-                    `-> b
-                        `-> . b
-                              `-> B B
+    `-> 1: ac
+           `-> 3: A ac                                    C
+                    `-> 3: A ac                         C
+                             `-> 4: b
+                                    `-> 6: . b
+                                             `-> 5: B B
   Reduce derivation
     s
-    `-> a             bc
-        `-> A a       `-> B bc      C
-              `-> A .       `-> B C
+    `-> 2: a                   bc
+           `-> 8: A a          `-> 9: B bc          C
+                    `-> 7: A .          `-> 10: B C
 input.y:6.4: warning: rule useless in parser due to conflicts [-Wother]
 ]],
 [[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
@@ -160,29 +160,29 @@ input.y: warning: shift/reduce conflict on token B [-Wcounterexamples]
   Example: A . B
   Shift derivation
     s
-    `-> A xby
-          `-> . B
+    `-> 2: A xby
+             `-> 9: . B
   Reduce derivation
     s
-    `-> ax          by
-        `-> A x     `-> B y
-              `-> .       `-> %empty
+    `-> 1: ax                by
+           `-> 3: A x        `-> 6: B y
+                    `-> 4: .          `-> 6: %empty
 input.y: warning: shift/reduce conflict on token B [-Wcounterexamples]
   First example: A X . B Y $end
   Shift derivation
     $accept
-    `-> s                     $end
-        `-> A xby
-              `-> X xby     Y
-                    `-> . B
+    `-> 0: s                               $end
+           `-> 2: A xby
+                    `-> 10: X xby        Y
+                              `-> 9: . B
   Second example: A X . B y $end
   Reduce derivation
     $accept
-    `-> s                             $end
-        `-> ax                by
-            `-> A x           `-> B y
-                  `-> X x
-                        `-> .
+    `-> 0: s                                            $end
+           `-> 1: ax                         by
+                  `-> 3: A x                 `-> 6: B y
+                           `-> 5: X x
+                                    `-> 4: .
 input.y:5.4-9: warning: rule useless in parser due to conflicts [-Wother]
 ]],
 [[input.y: warning: 2 shift/reduce conflicts [-Wconflicts-sr]
@@ -223,17 +223,17 @@ input.y: warning: shift/reduce conflict on token C [-Wcounterexamples]
   First example: B . C $end
   Shift derivation
     $accept
-    `-> g                 $end
-        `-> x
-            `-> bc
-                `-> B . C
+    `-> 0: g                          $end
+           `-> 2: x
+                  `-> 6: bc
+                         `-> 9: B . C
   Second example: B . C D $end
   Reduce derivation
     $accept
-    `-> g                       $end
-        `-> x
-            `-> b       cd
-                `-> B . `-> C D
+    `-> 0: g                                   $end
+           `-> 2: x
+                  `-> 5: b          cd
+                         `-> 7: B . `-> 8: C D
 input.y:6.4: warning: rule useless in parser due to conflicts [-Wother]
 ]],
 [[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
@@ -268,18 +268,18 @@ input.y: warning: shift/reduce conflict on token A [-Wcounterexamples]
   First example: A . A B $end
   Shift derivation
     $accept
-    `-> s                   $end
-        `-> t
-            `-> y
-                `-> A . A B
+    `-> 0: s                            $end
+           `-> 1: t
+                  `-> 4: y
+                         `-> 6: A . A B
   Second example: A . A $end
   Reduce derivation
     $accept
-    `-> s                             $end
-        `-> s               t
-            `-> t           `-> x
-                `-> x           `-> A
-                    `-> A .
+    `-> 0: s                                               $end
+           `-> 2: s                        t
+                  `-> 1: t                 `-> 3: x
+                         `-> 3: x                 `-> 5: A
+                                `-> 5: A .
 ]],
 [[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
 input.y: warning: shift/reduce conflict on token A [-Wcounterexamples]
@@ -317,26 +317,26 @@ input.y: warning: shift/reduce conflict on token A [-Wcounterexamples]
   Example: b . A X X Y
   Shift derivation
     a
-    `-> s
-        `-> b . xx        y
-                `-> A X X `-> Y
+    `-> 2: s
+           `-> 7: b . xx           y
+                      `-> 9: A X X `-> 11: Y
   Reduce derivation
     a
-    `-> r       t
-        `-> b . `-> A x     xy
-                      `-> X `-> X Y
+    `-> 1: r          t
+           `-> 3: b . `-> 6: A x        xy
+                               `-> 8: X `-> 10: X Y
 input.y: warning: shift/reduce conflict on token X [-Wcounterexamples]
   First example: A X . X
   Shift derivation
     a
-    `-> t
-        `-> A xx
-              `-> X . X
+    `-> 1: t
+           `-> 5: A xx
+                    `-> 9: X . X
   Second example: X . X xy
   Reduce derivation
     a
-    `-> x       t
-        `-> X . `-> X xy
+    `-> 1: x          t
+           `-> 8: X . `-> 6: X xy
 input.y:4.4: warning: rule useless in parser due to conflicts [-Wother]
 input.y:8.4: warning: rule useless in parser due to conflicts [-Wother]
 ]],
@@ -375,11 +375,11 @@ input.y: warning: reduce/reduce conflict on token $end [-Wcounterexamples]
   Example: A b .
   First reduce derivation
     a
-    `-> A b .
+    `-> 1: A b .
   Second reduce derivation
     a
-    `-> A b
-          `-> b .
+    `-> 1: A b
+             `-> 3: b .
 input.y:4.9: warning: rule useless in parser due to conflicts [-Wother]
 ]],
 [[input.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
@@ -412,15 +412,15 @@ input.y: warning: reduce/reduce conflict on tokens A, C [-Wcounterexamples]
   First example: D . A $end
   First reduce derivation
     $accept
-    `-> s             $end
-        `-> a       A
-            `-> D .
+    `-> 0: s                   $end
+           `-> 1: a          A
+                  `-> 5: D .
   Second example: B D . A $end
   Second reduce derivation
     $accept
-    `-> s               $end
-        `-> B b       A
-              `-> D .
+    `-> 0: s                     $end
+           `-> 4: B b          A
+                    `-> 6: D .
 input.y:5.4: warning: rule useless in parser due to conflicts [-Wother]
 ]],
 [[input.y: warning: 2 reduce/reduce conflicts [-Wconflicts-rr]
@@ -455,15 +455,15 @@ time limit exceeded: XXX
   First example: H i . J K $end
   Shift derivation
     $accept
-    `-> a                 $end
-        `-> H i
-              `-> i . J K
+    `-> 0: a                       $end
+           `-> 2: H i
+                    `-> 4: i . J K
   Second example: H i . J $end
   Reduce derivation
     $accept
-    `-> s               $end
-        `-> a         J
-            `-> H i .
+    `-> 0: s                     $end
+           `-> 1: a            J
+                  `-> 2: H i .
 input.y:4.4-6: warning: rule useless in parser due to conflicts [-Wother]
 ]],
 [[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
@@ -502,28 +502,28 @@ input.y: warning: shift/reduce conflict on token B [-Wcounterexamples]
   Example: N A . B C
   Shift derivation
     s
-    `-> n
-        `-> N b
-              `-> A . B C
+    `-> 1: n
+           `-> 6: N b
+                    `-> 8: A . B C
   Reduce derivation
     s
-    `-> n               C
-        `-> N a       B
-              `-> A .
+    `-> 2: n                     C
+           `-> 5: N a          B
+                    `-> 7: A .
 input.y: warning: shift/reduce conflict on token B [-Wcounterexamples]
   Example: N N A . B D C
   Shift derivation
     s
-    `-> n
-        `-> N n                 C
-              `-> N b
-                    `-> A . B D
+    `-> 1: n
+           `-> 4: N n                       C
+                    `-> 6: N b
+                             `-> 9: A . B D
   Reduce derivation
     s
-    `-> n                       C
-        `-> N n               D
-              `-> N a       B
-                    `-> A .
+    `-> 2: n                                C
+           `-> 3: N n                     D
+                    `-> 5: N a          B
+                             `-> 7: A .
 input.y:5.4: warning: rule useless in parser due to conflicts [-Wother]
 ]],
 [[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
@@ -565,30 +565,30 @@ input.y: warning: reduce/reduce conflict on tokens b, c [-Wcounterexamples]
   Example: B . b c
   First reduce derivation
     S
-    `-> B                        C
-        `-> A       b A          `-> A          c A
-            `-> B .   `-> %empty     `-> %empty   `-> %empty
+    `-> 1: B                                 C
+           `-> 6: A          b A             `-> 7: A             c A
+                  `-> 3: B .   `-> 6: %empty        `-> 7: %empty   `-> 7: %empty
   Second reduce derivation
     S
-    `-> B C
-          `-> A                          c A
-              `-> B                        `-> %empty
-                  `-> A     b A
-                      `-> .   `-> %empty
+    `-> 1: B C
+             `-> 7: A                                      c A
+                    `-> 3: B                                 `-> 7: %empty
+                           `-> 6: A        b A
+                                  `-> 5: .   `-> 6: %empty
 input.y: warning: reduce/reduce conflict on tokens b, c [-Wcounterexamples]
   Example: C . c b
   First reduce derivation
     S
-    `-> C                        B
-        `-> A       c A          `-> A          b A
-            `-> C .   `-> %empty     `-> %empty   `-> %empty
+    `-> 2: C                                 B
+           `-> 7: A          c A             `-> 6: A             b A
+                  `-> 4: C .   `-> 7: %empty        `-> 6: %empty   `-> 6: %empty
   Second reduce derivation
     S
-    `-> C B
-          `-> A                          b A
-              `-> C                        `-> %empty
-                  `-> A     c A
-                      `-> .   `-> %empty
+    `-> 2: C B
+             `-> 6: A                                      b A
+                    `-> 4: C                                 `-> 6: %empty
+                           `-> 7: A        c A
+                                  `-> 5: .   `-> 7: %empty
 ]],
 [[input.y: warning: 4 reduce/reduce conflicts [-Wconflicts-rr]
 input.y: warning: reduce/reduce conflict on tokens b, c [-Wcounterexamples]
@@ -625,119 +625,119 @@ input.y: warning: reduce/reduce conflict on token A [-Wcounterexamples]
   First example: . c A A $end
   First reduce derivation
     $accept
-    `-> a                   $end
-        `-> b     d
-            `-> . `-> c A A
+    `-> 0: a                            $end
+           `-> 1: b        d
+                  `-> 3: . `-> 6: c A A
   Second example: . c A A $end
   Second reduce derivation
     $accept
-    `-> a                   $end
-        `-> c     d
-            `-> . `-> c A A
+    `-> 0: a                            $end
+           `-> 2: c        d
+                  `-> 4: . `-> 6: c A A
 input.y: warning: reduce/reduce conflict on token A [-Wcounterexamples]
 time limit exceeded: XXX
   First example: b . c A A $end
   First reduce derivation
     $accept
-    `-> a                             $end
-        `-> b d
-              `-> a
-                  `-> b     d
-                      `-> . `-> c A A
+    `-> 0: a                                            $end
+           `-> 1: b d
+                    `-> 5: a
+                           `-> 1: b        d
+                                  `-> 3: . `-> 6: c A A
   Second example: b . A $end
   Second reduce derivation
     $accept
-    `-> a                 $end
-        `-> b d
-              `-> c     A
-                  `-> .
+    `-> 0: a                          $end
+           `-> 1: b d
+                    `-> 6: c        A
+                           `-> 4: .
 input.y: warning: reduce/reduce conflict on token A [-Wcounterexamples]
 time limit exceeded: XXX
   First example: c . c A A $end
   First reduce derivation
     $accept
-    `-> a                             $end
-        `-> c d
-              `-> a
-                  `-> b     d
-                      `-> . `-> c A A
+    `-> 0: a                                            $end
+           `-> 2: c d
+                    `-> 5: a
+                           `-> 1: b        d
+                                  `-> 3: . `-> 6: c A A
   Second example: c . A $end
   Second reduce derivation
     $accept
-    `-> a                 $end
-        `-> c d
-              `-> c     A
-                  `-> .
+    `-> 0: a                          $end
+           `-> 2: c d
+                    `-> 6: c        A
+                           `-> 4: .
 input.y: warning: shift/reduce conflict on token A [-Wcounterexamples]
 time limit exceeded: XXX
   First example: b c . A
   Shift derivation
     a
-    `-> b d
-          `-> c . A
+    `-> 1: b d
+             `-> 6: c . A
   Second example: b c . c A A $end
   Reduce derivation
     $accept
-    `-> a                                       $end
-        `-> b d
-              `-> a
-                  `-> c d
-                        `-> a
-                            `-> b     d
-                                `-> . `-> c A A
+    `-> 0: a                                                            $end
+           `-> 1: b d
+                    `-> 5: a
+                           `-> 2: c d
+                                    `-> 5: a
+                                           `-> 1: b        d
+                                                  `-> 3: . `-> 6: c A A
 input.y: warning: reduce/reduce conflict on token A [-Wcounterexamples]
   First example: b c . c A A $end
   First reduce derivation
     $accept
-    `-> a                                       $end
-        `-> b d
-              `-> a
-                  `-> c d
-                        `-> a
-                            `-> b     d
-                                `-> . `-> c A A
+    `-> 0: a                                                            $end
+           `-> 1: b d
+                    `-> 5: a
+                           `-> 2: c d
+                                    `-> 5: a
+                                           `-> 1: b        d
+                                                  `-> 3: . `-> 6: c A A
   Second example: b c . A $end
   Second reduce derivation
     $accept
-    `-> a                           $end
-        `-> b d
-              `-> a
-                  `-> c d
-                        `-> c     A
-                            `-> .
+    `-> 0: a                                          $end
+           `-> 1: b d
+                    `-> 5: a
+                           `-> 2: c d
+                                    `-> 6: c        A
+                                           `-> 4: .
 input.y: warning: shift/reduce conflict on token A [-Wcounterexamples]
   First example: b c . A
   Shift derivation
     a
-    `-> b d
-          `-> c . A
+    `-> 1: b d
+             `-> 6: c . A
   Second example: b c . A $end
   Reduce derivation
     $accept
-    `-> a                           $end
-        `-> b d
-              `-> a
-                  `-> c d
-                        `-> c     A
-                            `-> .
+    `-> 0: a                                          $end
+           `-> 1: b d
+                    `-> 5: a
+                           `-> 2: c d
+                                    `-> 6: c        A
+                                           `-> 4: .
 input.y: warning: reduce/reduce conflict on token $end [-Wcounterexamples]
   Example: b d .
   First reduce derivation
     a
-    `-> b d .
+    `-> 1: b d .
   Second reduce derivation
     a
-    `-> b d
-          `-> d .
+    `-> 1: b d
+             `-> 7: d .
 input.y: warning: reduce/reduce conflict on token $end [-Wcounterexamples]
   Example: c d .
   First reduce derivation
     a
-    `-> c d .
+    `-> 2: c d .
   Second reduce derivation
     a
-    `-> c d
-          `-> d .
+    `-> 2: c d
+             `-> 7: d .
 input.y:5.4: warning: rule useless in parser due to conflicts [-Wother]
 input.y:6.15: warning: rule useless in parser due to conflicts [-Wother]
 ]],
@@ -813,13 +813,13 @@ input.y: warning: shift/reduce conflict on token J [-Wcounterexamples]
   Example: H i J . J J
   Shift derivation
     s
-    `-> a             J
-        `-> H i J . J
+    `-> 2: a                J
+           `-> 3: H i J . J
   Reduce derivation
     s
-    `-> a
-        `-> H i         J J
-              `-> i J .
+    `-> 1: a
+           `-> 3: H i            J J
+                    `-> 5: i J .
 input.y:5.13-15: warning: rule useless in parser due to conflicts [-Wother]
 ]],
 [[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
@@ -857,14 +857,14 @@ input.y: warning: shift/reduce conflict on token D [-Wcounterexamples]
   Example: A a . D
   Shift derivation
     s
-    `-> A a d
-            `-> . D
+    `-> 1: A a d
+               `-> 6: . D
   Reduce derivation
     s
-    `-> A a a             d
-            `-> b         `-> D
-                `-> c
-                    `-> .
+    `-> 2: A a a                      d
+               `-> 3: b               `-> 6: D
+                      `-> 4: c
+                             `-> 5: .
 ]],
 [[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
 input.y: warning: shift/reduce conflict on token D [-Wcounterexamples]
@@ -899,17 +899,17 @@ input.y: warning: shift/reduce conflict on token D [-Wcounterexamples]
   First example: A a . D $end
   Shift derivation
     $accept
-    `-> s               $end
-        `-> A a d
-                `-> . D
+    `-> 0: s                     $end
+           `-> 1: A a d
+                      `-> 6: . D
   Second example: A a . D E $end
   Reduce derivation
     $accept
-    `-> s                             $end
-        `-> A a a             d     E
-                `-> b         `-> D
-                    `-> c
-                        `-> .
+    `-> 0: s                                            $end
+           `-> 2: A a a                      d        E
+                      `-> 3: b               `-> 6: D
+                             `-> 4: c
+                                    `-> 5: .
 ]],
 [[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
 input.y: warning: shift/reduce conflict on token D [-Wcounterexamples]
diff --git a/tests/diagnostics.at b/tests/diagnostics.at
index e8dcb384..43b365b9 100644
--- a/tests/diagnostics.at
+++ b/tests/diagnostics.at
@@ -378,10 +378,12 @@ exp:^M
 ]],
 [0],
 [[input.y:11.9-11: <warning>warning:</warning> symbol FOO redeclared [<warning>-Wother</warning>]
-   11 | %token 
 <warning>FOO</warning>
+   11 | %token 
+ <warning>FOO</warning>
       |         <warning>^~~</warning>
 input.y:10.9-11: <note>note:</note> previous declaration
-   10 | %token 
 <note>FOO</note>
+   10 | %token 
+ <note>FOO</note>
       |         <note>^~~</note>
 input.y:13.5: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
    13 | exp:
@@ -539,46 +541,46 @@ input.y: <warning>warning:</warning> shift/reduce conflict on token "+" [<warnin
   Example: <cex-0><cex-leaf>exp</cex-leaf> <cex-leaf>"+"</cex-leaf><cex-1> <cex-leaf>exp</cex-leaf> <cex-dot>•</cex-dot> <cex-leaf>"+"</cex-leaf> <cex-leaf>exp</cex-leaf></cex-1></cex-0>
   Shift derivation
     <cex-0><cex-step>exp</cex-step></cex-0>
-    <cex-0><cex-step>↳ <cex-leaf>exp</cex-leaf><cex-leaf> "+"</cex-leaf><cex-1><cex-step> exp</cex-step></cex-1></cex-step></cex-0>
-    <cex-1><cex-step>          ↳ <cex-leaf>exp</cex-leaf><cex-dot> •</cex-dot><cex-leaf> "+"</cex-leaf><cex-leaf> exp</cex-leaf></cex-step></cex-1>
+    <cex-0><cex-step>↳ 3: <cex-leaf>exp</cex-leaf><cex-leaf> "+"</cex-leaf><cex-1><cex-step> exp</cex-step></cex-1></cex-step></cex-0>
+    <cex-1><cex-step>             ↳ 3: <cex-leaf>exp</cex-leaf><cex-dot> •</cex-dot><cex-leaf> "+"</cex-leaf><cex-leaf> exp</cex-leaf></cex-step></cex-1>
   Example: <cex-0><cex-1><cex-leaf>exp</cex-leaf> <cex-leaf>"+"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-dot>•</cex-dot></cex-1> <cex-leaf>"+"</cex-leaf> <cex-leaf>exp</cex-leaf></cex-0>
   Reduce derivation
     <cex-0><cex-step>exp</cex-step></cex-0>
-    <cex-0><cex-step>↳ <cex-1><cex-step>exp</cex-step></cex-1><cex-leaf>             "+"</cex-leaf><cex-leaf> exp</cex-leaf></cex-step></cex-0>
-    <cex-1><cex-step>  ↳ <cex-leaf>exp</cex-leaf><cex-leaf> "+"</cex-leaf><cex-leaf> exp</cex-leaf><cex-dot> •</cex-dot></cex-step></cex-1>
+    <cex-0><cex-step>↳ 3: <cex-1><cex-step>exp</cex-step></cex-1><cex-leaf>                "+"</cex-leaf><cex-leaf> exp</cex-leaf></cex-step></cex-0>
+    <cex-1><cex-step>     ↳ 3: <cex-leaf>exp</cex-leaf><cex-leaf> "+"</cex-leaf><cex-leaf> exp</cex-leaf><cex-dot> •</cex-dot></cex-step></cex-1>
 input.y: <warning>warning:</warning> shift/reduce conflict on token "else" [<warning>-Wcounterexamples</warning>]
   Example: <cex-0><cex-leaf>"if"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-leaf>"then"</cex-leaf><cex-1> <cex-leaf>"if"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-leaf>"then"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-dot>•</cex-dot> <cex-leaf>"else"</cex-leaf> <cex-leaf>exp</cex-leaf></cex-1></cex-0>
   Shift derivation
     <cex-0><cex-step>exp</cex-step></cex-0>
-    <cex-0><cex-step>↳ <cex-leaf>"if"</cex-leaf><cex-leaf> exp</cex-leaf><cex-leaf> "then"</cex-leaf><cex-1><cex-step> exp</cex-step></cex-1></cex-step></cex-0>
-    <cex-1><cex-step>                  ↳ <cex-leaf>"if"</cex-leaf><cex-leaf> exp</cex-leaf><cex-leaf> "then"</cex-leaf><cex-leaf> exp</cex-leaf><cex-dot> •</cex-dot><cex-leaf> "else"</cex-leaf><cex-leaf> exp</cex-leaf></cex-step></cex-1>
+    <cex-0><cex-step>↳ 1: <cex-leaf>"if"</cex-leaf><cex-leaf> exp</cex-leaf><cex-leaf> "then"</cex-leaf><cex-1><cex-step> exp</cex-step></cex-1></cex-step></cex-0>
+    <cex-1><cex-step>                     ↳ 2: <cex-leaf>"if"</cex-leaf><cex-leaf> exp</cex-leaf><cex-leaf> "then"</cex-leaf><cex-leaf> exp</cex-leaf><cex-dot> •</cex-dot><cex-leaf> "else"</cex-leaf><cex-leaf> exp</cex-leaf></cex-step></cex-1>
   Example: <cex-0><cex-leaf>"if"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-leaf>"then"</cex-leaf><cex-1> <cex-leaf>"if"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-leaf>"then"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-dot>•</cex-dot></cex-1> <cex-leaf>"else"</cex-leaf> <cex-leaf>exp</cex-leaf></cex-0>
   Reduce derivation
     <cex-0><cex-step>exp</cex-step></cex-0>
-    <cex-0><cex-step>↳ <cex-leaf>"if"</cex-leaf><cex-leaf> exp</cex-leaf><cex-leaf> "then"</cex-leaf><cex-1><cex-step> exp</cex-step></cex-1><cex-leaf>                     "else"</cex-leaf><cex-leaf> exp</cex-leaf></cex-step></cex-0>
-    <cex-1><cex-step>                  ↳ <cex-leaf>"if"</cex-leaf><cex-leaf> exp</cex-leaf><cex-leaf> "then"</cex-leaf><cex-leaf> exp</cex-leaf><cex-dot> •</cex-dot></cex-step></cex-1>
+    <cex-0><cex-step>↳ 2: <cex-leaf>"if"</cex-leaf><cex-leaf> exp</cex-leaf><cex-leaf> "then"</cex-leaf><cex-1><cex-step> exp</cex-step></cex-1><cex-leaf>                        "else"</cex-leaf><cex-leaf> exp</cex-leaf></cex-step></cex-0>
+    <cex-1><cex-step>                     ↳ 1: <cex-leaf>"if"</cex-leaf><cex-leaf> exp</cex-leaf><cex-leaf> "then"</cex-leaf><cex-leaf> exp</cex-leaf><cex-dot> •</cex-dot></cex-step></cex-1>
 input.y: <warning>warning:</warning> shift/reduce conflict on token "+" [<warning>-Wcounterexamples</warning>]
   Example: <cex-0><cex-leaf>"if"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-leaf>"then"</cex-leaf><cex-1> <cex-leaf>exp</cex-leaf> <cex-dot>•</cex-dot> <cex-leaf>"+"</cex-leaf> <cex-leaf>exp</cex-leaf></cex-1></cex-0>
   Shift derivation
     <cex-0><cex-step>exp</cex-step></cex-0>
-    <cex-0><cex-step>↳ <cex-leaf>"if"</cex-leaf><cex-leaf> exp</cex-leaf><cex-leaf> "then"</cex-leaf><cex-1><cex-step> exp</cex-step></cex-1></cex-step></cex-0>
-    <cex-1><cex-step>                  ↳ <cex-leaf>exp</cex-leaf><cex-dot> •</cex-dot><cex-leaf> "+"</cex-leaf><cex-leaf> exp</cex-leaf></cex-step></cex-1>
+    <cex-0><cex-step>↳ 1: <cex-leaf>"if"</cex-leaf><cex-leaf> exp</cex-leaf><cex-leaf> "then"</cex-leaf><cex-1><cex-step> exp</cex-step></cex-1></cex-step></cex-0>
+    <cex-1><cex-step>                     ↳ 3: <cex-leaf>exp</cex-leaf><cex-dot> •</cex-dot><cex-leaf> "+"</cex-leaf><cex-leaf> exp</cex-leaf></cex-step></cex-1>
   Example: <cex-0><cex-1><cex-leaf>"if"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-leaf>"then"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-dot>•</cex-dot></cex-1> <cex-leaf>"+"</cex-leaf> <cex-leaf>exp</cex-leaf></cex-0>
   Reduce derivation
     <cex-0><cex-step>exp</cex-step></cex-0>
-    <cex-0><cex-step>↳ <cex-1><cex-step>exp</cex-step></cex-1><cex-leaf>                     "+"</cex-leaf><cex-leaf> exp</cex-leaf></cex-step></cex-0>
-    <cex-1><cex-step>  ↳ <cex-leaf>"if"</cex-leaf><cex-leaf> exp</cex-leaf><cex-leaf> "then"</cex-leaf><cex-leaf> exp</cex-leaf><cex-dot> •</cex-dot></cex-step></cex-1>
+    <cex-0><cex-step>↳ 3: <cex-1><cex-step>exp</cex-step></cex-1><cex-leaf>                        "+"</cex-leaf><cex-leaf> exp</cex-leaf></cex-step></cex-0>
+    <cex-1><cex-step>     ↳ 1: <cex-leaf>"if"</cex-leaf><cex-leaf> exp</cex-leaf><cex-leaf> "then"</cex-leaf><cex-leaf> exp</cex-leaf><cex-dot> •</cex-dot></cex-step></cex-1>
 input.y: <warning>warning:</warning> shift/reduce conflict on token "+" [<warning>-Wcounterexamples</warning>]
   Example: <cex-0><cex-leaf>"if"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-leaf>"then"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-leaf>"else"</cex-leaf><cex-1> <cex-leaf>exp</cex-leaf> <cex-dot>•</cex-dot> <cex-leaf>"+"</cex-leaf> <cex-leaf>exp</cex-leaf></cex-1></cex-0>
   Shift derivation
     <cex-0><cex-step>exp</cex-step></cex-0>
-    <cex-0><cex-step>↳ <cex-leaf>"if"</cex-leaf><cex-leaf> exp</cex-leaf><cex-leaf> "then"</cex-leaf><cex-leaf> exp</cex-leaf><cex-leaf> "else"</cex-leaf><cex-1><cex-step> exp</cex-step></cex-1></cex-step></cex-0>
-    <cex-1><cex-step>                             ↳ <cex-leaf>exp</cex-leaf><cex-dot> •</cex-dot><cex-leaf> "+"</cex-leaf><cex-leaf> exp</cex-leaf></cex-step></cex-1>
+    <cex-0><cex-step>↳ 2: <cex-leaf>"if"</cex-leaf><cex-leaf> exp</cex-leaf><cex-leaf> "then"</cex-leaf><cex-leaf> exp</cex-leaf><cex-leaf> "else"</cex-leaf><cex-1><cex-step> exp</cex-step></cex-1></cex-step></cex-0>
+    <cex-1><cex-step>                                ↳ 3: <cex-leaf>exp</cex-leaf><cex-dot> •</cex-dot><cex-leaf> "+"</cex-leaf><cex-leaf> exp</cex-leaf></cex-step></cex-1>
   Example: <cex-0><cex-1><cex-leaf>"if"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-leaf>"then"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-leaf>"else"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-dot>•</cex-dot></cex-1> <cex-leaf>"+"</cex-leaf> <cex-leaf>exp</cex-leaf></cex-0>
   Reduce derivation
     <cex-0><cex-step>exp</cex-step></cex-0>
-    <cex-0><cex-step>↳ <cex-1><cex-step>exp</cex-step></cex-1><cex-leaf>                                "+"</cex-leaf><cex-leaf> exp</cex-leaf></cex-step></cex-0>
-    <cex-1><cex-step>  ↳ <cex-leaf>"if"</cex-leaf><cex-leaf> exp</cex-leaf><cex-leaf> "then"</cex-leaf><cex-leaf> exp</cex-leaf><cex-leaf> "else"</cex-leaf><cex-leaf> exp</cex-leaf><cex-dot> •</cex-dot></cex-step></cex-1>
+    <cex-0><cex-step>↳ 3: <cex-1><cex-step>exp</cex-step></cex-1><cex-leaf>                                   "+"</cex-leaf><cex-leaf> exp</cex-leaf></cex-step></cex-0>
+    <cex-1><cex-step>     ↳ 2: <cex-leaf>"if"</cex-leaf><cex-leaf> exp</cex-leaf><cex-leaf> "then"</cex-leaf><cex-leaf> exp</cex-leaf><cex-leaf> "else"</cex-leaf><cex-leaf> exp</cex-leaf><cex-dot> •</cex-dot></cex-step></cex-1>
 ]])
 
 
@@ -621,23 +623,23 @@ input.y: <warning>warning:</warning> reduce/reduce conflict on token "X" [<warni
   Example: <cex-0><cex-1><cex-2><cex-3><cex-leaf>"X"</cex-leaf> <cex-dot>•</cex-dot></cex-3></cex-2></cex-1><cex-4></cex-4><cex-5><cex-6><cex-7><cex-8><cex-9><cex-10> <cex-leaf>"X"</cex-leaf></cex-10></cex-9></cex-8><cex-11> <cex-leaf>"quuux"</cex-leaf></cex-11></cex-7></cex-6></cex-5><cex-12><cex-13><cex-14> <cex-leaf>"X"</cex-leaf></cex-14></cex-13></cex-12></cex-0>
   First reduce derivation
     <cex-0><cex-step>exp</cex-step></cex-0>
-    <cex-0><cex-step>↳ <cex-1><cex-step>x1</cex-step></cex-1><cex-4><cex-step>          e1</cex-step></cex-4><cex-5><cex-step>  foo1</cex-step></cex-5><cex-12><cex-step>                      x1</cex-step></cex-12></cex-step></cex-0>
-    <cex-1><cex-step>  ↳ <cex-2><cex-step>x2</cex-step></cex-2></cex-step></cex-1><cex-4><cex-step>        ↳ ε</cex-step></cex-4><cex-5><cex-step> ↳ <cex-6><cex-step>foo2</cex-step></cex-6></cex-step></cex-5><cex-12><cex-step>                    ↳ <cex-13><cex-step>x2</cex-step></cex-13></cex-step></cex-12>
-    <cex-2><cex-step>    ↳ <cex-3><cex-step>x3</cex-step></cex-3></cex-step></cex-2><cex-6><cex-step>            ↳ <cex-7><cex-step>foo3</cex-step></cex-7></cex-step></cex-6><cex-13><cex-step>                    ↳ <cex-14><cex-step>x3</cex-step></cex-14></cex-step></cex-13>
-    <cex-3><cex-step>      ↳ <cex-leaf>"X"</cex-leaf><cex-dot> •</cex-dot></cex-step></cex-3><cex-7><cex-step>         ↳ <cex-8><cex-step>x1</cex-step></cex-8><cex-11><cex-step>        foo4</cex-step></cex-11></cex-step></cex-7><cex-14><cex-step>          ↳ <cex-leaf>"X"</cex-leaf></cex-step></cex-14>
-    <cex-8><cex-step>                        ↳ <cex-9><cex-step>x2</cex-step></cex-9></cex-step></cex-8><cex-11><cex-step>      ↳ <cex-leaf>"quuux"</cex-leaf></cex-step></cex-11>
-    <cex-9><cex-step>                          ↳ <cex-10><cex-step>x3</cex-step></cex-10></cex-step></cex-9>
-    <cex-10><cex-step>                            ↳ <cex-leaf>"X"</cex-leaf></cex-step></cex-10>
+    <cex-0><cex-step>↳ 1: <cex-1><cex-step>x1</cex-step></cex-1><cex-4><cex-step>                      e1</cex-step></cex-4><cex-5><cex-step>     foo1</cex-step></cex-5><cex-12><cex-step>                                              x1</cex-step></cex-12></cex-step></cex-0>
+    <cex-1><cex-step>     ↳ 11: <cex-2><cex-step>x2</cex-step></cex-2></cex-step></cex-1><cex-4><cex-step>                ↳ 1: ε</cex-step></cex-4><cex-5><cex-step> ↳ 3: <cex-6><cex-step>foo2</cex-step></cex-6></cex-step></cex-5><cex-12><cex-step>                                         ↳ 11: <cex-13><cex-step>x2</cex-step></cex-13></cex-step></cex-12>
+    <cex-2><cex-step>           ↳ 12: <cex-3><cex-step>x3</cex-step></cex-3></cex-step></cex-2><cex-6><cex-step>                      ↳ 4: <cex-7><cex-step>foo3</cex-step></cex-7></cex-step></cex-6><cex-13><cex-step>                                          ↳ 12: <cex-14><cex-step>x3</cex-step></cex-14></cex-step></cex-13>
+    <cex-3><cex-step>                 ↳ 13: <cex-leaf>"X"</cex-leaf><cex-dot> •</cex-dot></cex-step></cex-3><cex-7><cex-step>                  ↳ 5: <cex-8><cex-step>x1</cex-step></cex-8><cex-11><cex-step>                    foo4</cex-step></cex-11></cex-step></cex-7><cex-14><cex-step>                     ↳ 13: <cex-leaf>"X"</cex-leaf></cex-step></cex-14>
+    <cex-8><cex-step>                                                   ↳ 11: <cex-9><cex-step>x2</cex-step></cex-9></cex-step></cex-8><cex-11><cex-step>              ↳ 6: <cex-leaf>"quuux"</cex-leaf></cex-step></cex-11>
+    <cex-9><cex-step>                                                         ↳ 12: <cex-10><cex-step>x3</cex-step></cex-10></cex-step></cex-9>
+    <cex-10><cex-step>                                                               ↳ 13: <cex-leaf>"X"</cex-leaf></cex-step></cex-10>
   Example: <cex-0><cex-1><cex-2><cex-3><cex-leaf>"X"</cex-leaf> <cex-dot>•</cex-dot></cex-3></cex-2></cex-1><cex-4></cex-4><cex-5><cex-6><cex-7><cex-8><cex-9><cex-10> <cex-leaf>"X"</cex-leaf></cex-10></cex-9></cex-8><cex-11> <cex-leaf>"quuux"</cex-leaf></cex-11></cex-7></cex-6></cex-5><cex-12><cex-13><cex-14> <cex-leaf>"X"</cex-leaf></cex-14></cex-13></cex-12></cex-0>
   Second reduce derivation
     <cex-0><cex-step>exp</cex-step></cex-0>
-    <cex-0><cex-step>↳ <cex-1><cex-step>y1</cex-step></cex-1><cex-4><cex-step>          e2</cex-step></cex-4><cex-5><cex-step>  bar1</cex-step></cex-5><cex-12><cex-step>                      y1</cex-step></cex-12></cex-step></cex-0>
-    <cex-1><cex-step>  ↳ <cex-2><cex-step>y2</cex-step></cex-2></cex-step></cex-1><cex-4><cex-step>        ↳ ε</cex-step></cex-4><cex-5><cex-step> ↳ <cex-6><cex-step>bar2</cex-step></cex-6></cex-step></cex-5><cex-12><cex-step>                    ↳ <cex-13><cex-step>y2</cex-step></cex-13></cex-step></cex-12>
-    <cex-2><cex-step>    ↳ <cex-3><cex-step>y3</cex-step></cex-3></cex-step></cex-2><cex-6><cex-step>            ↳ <cex-7><cex-step>bar3</cex-step></cex-7></cex-step></cex-6><cex-13><cex-step>                    ↳ <cex-14><cex-step>y3</cex-step></cex-14></cex-step></cex-13>
-    <cex-3><cex-step>      ↳ <cex-leaf>"X"</cex-leaf><cex-dot> •</cex-dot></cex-step></cex-3><cex-7><cex-step>         ↳ <cex-8><cex-step>y1</cex-step></cex-8><cex-11><cex-step>        bar4</cex-step></cex-11></cex-step></cex-7><cex-14><cex-step>          ↳ <cex-leaf>"X"</cex-leaf></cex-step></cex-14>
-    <cex-8><cex-step>                        ↳ <cex-9><cex-step>y2</cex-step></cex-9></cex-step></cex-8><cex-11><cex-step>      ↳ <cex-leaf>"quuux"</cex-leaf></cex-step></cex-11>
-    <cex-9><cex-step>                          ↳ <cex-10><cex-step>y3</cex-step></cex-10></cex-step></cex-9>
-    <cex-10><cex-step>                            ↳ <cex-leaf>"X"</cex-leaf></cex-step></cex-10>
+    <cex-0><cex-step>↳ 2: <cex-1><cex-step>y1</cex-step></cex-1><cex-4><cex-step>                      e2</cex-step></cex-4><cex-5><cex-step>     bar1</cex-step></cex-5><cex-12><cex-step>                                               y1</cex-step></cex-12></cex-step></cex-0>
+    <cex-1><cex-step>     ↳ 14: <cex-2><cex-step>y2</cex-step></cex-2></cex-step></cex-1><cex-4><cex-step>                ↳ 2: ε</cex-step></cex-4><cex-5><cex-step> ↳ 7: <cex-6><cex-step>bar2</cex-step></cex-6></cex-step></cex-5><cex-12><cex-step>                                          ↳ 14: <cex-13><cex-step>y2</cex-step></cex-13></cex-step></cex-12>
+    <cex-2><cex-step>           ↳ 15: <cex-3><cex-step>y3</cex-step></cex-3></cex-step></cex-2><cex-6><cex-step>                      ↳ 8: <cex-7><cex-step>bar3</cex-step></cex-7></cex-step></cex-6><cex-13><cex-step>                                           ↳ 15: <cex-14><cex-step>y3</cex-step></cex-14></cex-step></cex-13>
+    <cex-3><cex-step>                 ↳ 16: <cex-leaf>"X"</cex-leaf><cex-dot> •</cex-dot></cex-step></cex-3><cex-7><cex-step>                  ↳ 9: <cex-8><cex-step>y1</cex-step></cex-8><cex-11><cex-step>                    bar4</cex-step></cex-11></cex-step></cex-7><cex-14><cex-step>                      ↳ 16: <cex-leaf>"X"</cex-leaf></cex-step></cex-14>
+    <cex-8><cex-step>                                                   ↳ 14: <cex-9><cex-step>y2</cex-step></cex-9></cex-step></cex-8><cex-11><cex-step>              ↳ 10: <cex-leaf>"quuux"</cex-leaf></cex-step></cex-11>
+    <cex-9><cex-step>                                                         ↳ 15: <cex-10><cex-step>y3</cex-step></cex-10></cex-step></cex-9>
+    <cex-10><cex-step>                                                               ↳ 16: <cex-leaf>"X"</cex-leaf></cex-step></cex-10>
 input.y: <warning>warning:</warning> fix-its can be applied.  Rerun with option '--update'. [<warning>-Wother</warning>]
 ]])
 
diff --git a/tests/report.at b/tests/report.at
index 9021f6d5..35493b93 100644
--- a/tests/report.at
+++ b/tests/report.at
@@ -1541,60 +1541,60 @@ input.y: warning: shift/reduce conflict on token "⊕" [-Wcounterexamples]
   Example: exp "+" exp • "⊕" exp
   Shift derivation
     exp
-    ↳ exp "+" exp
-              ↳ exp • "⊕" exp
+    ↳ 2: exp "+" exp
+                 ↳ 1: exp • "⊕" exp
   Reduce derivation
     exp
-    ↳ exp             "⊕" exp
-      ↳ exp "+" exp •
+    ↳ 1: exp                "⊕" exp
+         ↳ 2: exp "+" exp •
 input.y: warning: reduce/reduce conflict on tokens $end, "+", "⊕" [-Wcounterexamples]
   Example: exp "+" exp •
   First reduce derivation
     exp
-    ↳ exp "+" exp •
+    ↳ 2: exp "+" exp •
   Second reduce derivation
     exp
-    ↳ exp "+" exp •
+    ↳ 3: exp "+" exp •
 input.y: warning: shift/reduce conflict on token "⊕" [-Wcounterexamples]
   Example: exp "+" exp • "⊕" exp
   Shift derivation
     exp
-    ↳ exp "+" exp
-              ↳ exp • "⊕" exp
+    ↳ 2: exp "+" exp
+                 ↳ 1: exp • "⊕" exp
   Reduce derivation
     exp
-    ↳ exp             "⊕" exp
-      ↳ exp "+" exp •
+    ↳ 1: exp                "⊕" exp
+         ↳ 3: exp "+" exp •
 input.y: warning: shift/reduce conflict on token "⊕" [-Wcounterexamples]
   Example: exp "⊕" exp • "⊕" exp
   Shift derivation
     exp
-    ↳ exp "⊕" exp
-              ↳ exp • "⊕" exp
+    ↳ 1: exp "⊕" exp
+                 ↳ 1: exp • "⊕" exp
   Reduce derivation
     exp
-    ↳ exp             "⊕" exp
-      ↳ exp "⊕" exp •
+    ↳ 1: exp                "⊕" exp
+         ↳ 1: exp "⊕" exp •
 input.y: warning: shift/reduce conflict on token "+" [-Wcounterexamples]
   Example: exp "⊕" exp • "+" exp
   Shift derivation
     exp
-    ↳ exp "⊕" exp
-              ↳ exp • "+" exp
+    ↳ 1: exp "⊕" exp
+                 ↳ 2: exp • "+" exp
   Reduce derivation
     exp
-    ↳ exp             "+" exp
-      ↳ exp "⊕" exp •
+    ↳ 2: exp                "+" exp
+         ↳ 1: exp "⊕" exp •
 input.y: warning: shift/reduce conflict on token "+" [-Wcounterexamples]
   Example: exp "⊕" exp • "+" exp
   Shift derivation
     exp
-    ↳ exp "⊕" exp
-              ↳ exp • "+" exp
+    ↳ 1: exp "⊕" exp
+                 ↳ 3: exp • "+" exp
   Reduce derivation
     exp
-    ↳ exp             "+" exp
-      ↳ exp "⊕" exp •
+    ↳ 2: exp                "+" exp
+         ↳ 1: exp "⊕" exp •
 input.y:6.3-13: warning: rule useless in parser due to conflicts [-Wother]
 ]])
 
@@ -1745,12 +1745,12 @@ State 7
       Example: exp "+" exp • "⊕" exp
       Shift derivation
         exp
-        ↳ exp "+" exp
-                  ↳ exp • "⊕" exp
+        ↳ 2: exp "+" exp
+                     ↳ 1: exp • "⊕" exp
       Reduce derivation
         exp
-        ↳ exp             "⊕" exp
-          ↳ exp "+" exp •
+        ↳ 1: exp                "⊕" exp
+             ↳ 2: exp "+" exp •
 
     reduce/reduce conflict on tokens $end, "+", "⊕":
         2 exp: exp "+" exp •
@@ -1758,10 +1758,10 @@ State 7
       Example: exp "+" exp •
       First reduce derivation
         exp
-        ↳ exp "+" exp •
+        ↳ 2: exp "+" exp •
       Second reduce derivation
         exp
-        ↳ exp "+" exp •
+        ↳ 3: exp "+" exp •
 
     shift/reduce conflict on token "⊕":
         3 exp: exp "+" exp •
@@ -1769,12 +1769,12 @@ State 7
       Example: exp "+" exp • "⊕" exp
       Shift derivation
         exp
-        ↳ exp "+" exp
-                  ↳ exp • "⊕" exp
+        ↳ 2: exp "+" exp
+                     ↳ 1: exp • "⊕" exp
       Reduce derivation
         exp
-        ↳ exp             "⊕" exp
-          ↳ exp "+" exp •
+        ↳ 1: exp                "⊕" exp
+             ↳ 3: exp "+" exp •
 
 
 
@@ -1798,12 +1798,12 @@ State 8
       Example: exp "⊕" exp • "⊕" exp
       Shift derivation
         exp
-        ↳ exp "⊕" exp
-                  ↳ exp • "⊕" exp
+        ↳ 1: exp "⊕" exp
+                     ↳ 1: exp • "⊕" exp
       Reduce derivation
         exp
-        ↳ exp             "⊕" exp
-          ↳ exp "⊕" exp •
+        ↳ 1: exp                "⊕" exp
+             ↳ 1: exp "⊕" exp •
 
     shift/reduce conflict on token "+":
         1 exp: exp "⊕" exp •
@@ -1811,12 +1811,12 @@ State 8
       Example: exp "⊕" exp • "+" exp
       Shift derivation
         exp
-        ↳ exp "⊕" exp
-                  ↳ exp • "+" exp
+        ↳ 1: exp "⊕" exp
+                     ↳ 2: exp • "+" exp
       Reduce derivation
         exp
-        ↳ exp             "+" exp
-          ↳ exp "⊕" exp •
+        ↳ 2: exp                "+" exp
+             ↳ 1: exp "⊕" exp •
 
     shift/reduce conflict on token "+":
         1 exp: exp "⊕" exp •
@@ -1824,12 +1824,12 @@ State 8
       Example: exp "⊕" exp • "+" exp
       Shift derivation
         exp
-        ↳ exp "⊕" exp
-                  ↳ exp • "+" exp
+        ↳ 1: exp "⊕" exp
+                     ↳ 3: exp • "+" exp
       Reduce derivation
         exp
-        ↳ exp             "+" exp
-          ↳ exp "⊕" exp •
+        ↳ 2: exp                "+" exp
+             ↳ 1: exp "⊕" exp •
 
 ]])
 
-- 
2.27.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.