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

Akim Demaille <[email protected]>
Newsgroups gmane.comp.parsers.bison.patches
Message-ID <[email protected]>
I was hoping to get some feedback about this proposal.

> Le 29 juil. 2020 à 06:46, Akim Demaille <[email protected]> a écrit :
> 
> 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 •

So the feedback will be mine only:

akim> I like that, please install!

Ok, installed as follows.  Cheers!

commit 3c36d871fad4d9d762f8daf0537ff28803f18397
Author: Akim Demaille <[email protected]>
Date:   Tue Jul 28 19:50:22 2020 +0200

    cex: display the rule numbers
    
    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.
    
    * doc/bison.texi: Adjust.

diff --git a/NEWS b/NEWS
index 79efc8d8..c14d17f2 100644
--- a/NEWS
+++ b/NEWS
@@ -2,12 +2,10 @@ GNU Bison NEWS
 
 * Noteworthy changes in release ?.? (????-??-??) [?]
 
-** Bug fixes
-
-  Push parsers use YYMALLOC/YYFREE instead of direct calls to malloc/free.
-
 ** Changes
 
+*** A C++ native GLR parser
+
   A new version of the generated C++ GLR parser was added as "glr2.cc". It
   is forked from the existing glr.c/cc parser, with the objective of making
   it a more modern, truly C++ parser (instead of a C++ wrapper around a C
@@ -19,6 +17,21 @@ GNU Bison NEWS
 
   %skeleton "glr2.cc"
 
+*** Counterexamples
+
+  Counterexamples now show the rule numbers:
+
+    exp
+    ↳ 1: "if" exp "then" exp
+                         ↳ 2: "if" exp "then" exp • "else" exp
+
+  instead of
+
+    exp
+    ↳ "if" exp "then" exp
+                      ↳ "if" exp "then" exp • "else" exp
+
+
 * Noteworthy changes in release 3.7.1 (2020-08-02) [stable]
 
 ** Bug fixes
diff --git a/doc/bison.texi b/doc/bison.texi
index 48428f04..e36f8a38 100644
--- a/doc/bison.texi
+++ b/doc/bison.texi
@@ -8329,29 +8329,29 @@ with two different parses:
   Example: @yellow{"if" expr "then"} @blue{"if" expr "then" stmt} @red{•} @blue{"else" stmt}
   Shift derivation
     @yellow{if_stmt}
-    @yellow{↳ "if" expr "then"} @green{stmt}
-                        @green{↳} @blue{if_stmt}
-                           @blue{↳ "if" expr "then" stmt} @red{•} @blue{"else" stmt}
+    @yellow{↳ 3: "if" expr "then"} @green{stmt}
+                           @green{↳ 2:} @blue{if_stmt}
+                                 @blue{↳ 4: "if" expr "then" stmt} @red{•} @blue{"else" stmt}
   Example: @yellow{"if" expr "then"} @blue{"if" expr "then" stmt} @red{•} @yellow{"else" stmt}
   Reduce derivation
     @yellow{if_stmt}
-    @yellow{↳ "if" expr "then"} @green{stmt}                        @yellow{"else" stmt}
-                        @green{↳} @blue{if_stmt}
-                           @blue{↳ "if" expr "then" stmt} @red{•}
+    @yellow{↳ 4: "if" expr "then"} @green{stmt}                                @yellow{"else" stmt}
+                           @green{↳ 2:} @blue{if_stmt}
+                                 @blue{↳ 3: "if" expr "then" stmt} @red{•}
 @end ifnottex
 @iftex
   Example: @yellow{"if" expr "then"} @blue{"if" expr "then" stmt} @red{•} @blue{"else" stmt}
   Shift derivation
     @yellow{if_stmt}
-    @yellow{@arrow{} "if" expr "then"} @green{stmt}
-                        @green{@arrow{}} @blue{if_stmt}
-                           @blue{@arrow{} "if" expr "then" stmt} @red{•} @blue{"else" stmt}
+    @yellow{@arrow{} 3: "if" expr "then"} @green{stmt}
+                           @green{@arrow{} 2:} @blue{if_stmt}
+                                 @blue{@arrow{} 4: "if" expr "then" stmt} @red{•} @blue{"else" stmt}
   Example: @yellow{"if" expr "then"} @blue{"if" expr "then" stmt} @red{•} @yellow{"else" stmt}
   Reduce derivation
     @yellow{if_stmt}
-    @yellow{@arrow{} "if" expr "then"} @green{stmt}                        @yellow{"else" stmt}
-                        @green{@arrow{}} @blue{if_stmt}
-                           @blue{@arrow{} "if" expr "then" stmt} @red{•}
+    @yellow{@arrow{} 4: "if" expr "then"} @green{stmt}                                @yellow{"else" stmt}
+                           @green{@arrow{} 2:} @blue{if_stmt}
+                                 @blue{@arrow{} 3: "if" expr "then" stmt} @red{•}
 @end iftex
 @end group
 @end macro
@@ -9957,11 +9957,11 @@ initially developed by Chinawat Isradisaikul and Andrew Myers
 As a first example, see the grammar of @ref{Shift/Reduce}, which features
 one shift/reduce conflict:
 
-@c see doc/if-then-else.y
+@c see doc/else.y
 @example
-$ @kbd{bison if-then-else.y}
-if-then-else.y: @dwarning{warning}: 1 shift/reduce conflict [@dwarning{-Wconflicts-sr}]
-if-then-else.y: @dnotice{note}: rerun with option '-Wcounterexamples' to generate conflict counterexamples
+$ @kbd{bison else.y}
+else.y: @dwarning{warning}: 1 shift/reduce conflict [@dwarning{-Wconflicts-sr}]
+else.y: @dnotice{note}: rerun with option '-Wcounterexamples' to generate conflict counterexamples
 @end example
 
 @noindent
@@ -9970,8 +9970,8 @@ Let's rerun @command{bison} with the option
 output is actually in color)}:
 
 @example
-if-then-else.y: @dwarning{warning}: 1 shift/reduce conflict [@dwarning{-Wconflicts-sr}]
-if-then-else.y: @dwarning{warning}: shift/reduce conflict on token "else" [@dwarning{-Wcounterexamples}]
+else.y: @dwarning{warning}: 1 shift/reduce conflict [@dwarning{-Wconflicts-sr}]
+else.y: @dwarning{warning}: shift/reduce conflict on token "else" [@dwarning{-Wcounterexamples}]
 @danglingElseCex
 @end example
 
@@ -10011,39 +10011,39 @@ sequence.y: @dwarning{warning}: shift/reduce conflict on token "word" [@dwarning
   Example: @red{•} @green{"word"}
   Shift derivation
     @yellow{sequence}
-    @yellow{↳} @green{maybeword}
-      @green{↳} @red{•} @green{"word"}
+    @yellow{↳ 2:} @green{maybeword}
+          @green{↳ 5:} @red{•} @green{"word"}
   Example: @red{•} @yellow{"word"}
   Reduce derivation
     @yellow{sequence}
-    @yellow{↳} @green{sequence} @yellow{"word"}
-      @green{↳} @red{•}
+    @yellow{↳ 3:} @green{sequence} @yellow{"word"}
+          @green{↳ 1:} @red{•}
 @end group
 @group
 sequence.y: @dwarning{warning}: reduce/reduce conflict on tokens $end, "word" [@dwarning{-Wcounterexamples}]
   Example: @red{•}
   First reduce derivation
     @yellow{sequence}
-    @yellow{↳} @red{•}
+    @yellow{↳ 1:} @red{•}
   Example: @red{•}
   Second reduce derivation
     @yellow{sequence}
-    @yellow{↳} @green{maybeword}
-      @green{↳} @red{•}
+    @yellow{↳ 2:} @green{maybeword}
+          @green{↳ 4:} @red{•}
 @end group
 @group
 sequence.y: @dwarning{warning}: shift/reduce conflict on token "word" [@dwarning{-Wcounterexamples}]
   Example: @red{•} @green{"word"}
   Shift derivation
     @yellow{sequence}
-    @yellow{↳} @green{maybeword}
-      @green{↳} @red{•} @green{"word"}
+    @yellow{↳ 2:} @green{maybeword}
+          @green{↳ 5:} @red{•} @green{"word"}
   Example: @red{•} @yellow{"word"}
   Reduce derivation
     @yellow{sequence}
-    @yellow{↳} @green{sequence}    @yellow{"word"}
-      @green{↳} @blue{maybeword}
-        @blue{↳} @red{•}
+    @yellow{↳ 3:} @green{sequence}        @yellow{"word"}
+          @green{↳ 2:} @blue{maybeword}
+                @blue{↳ 4:} @red{•}
 @end group
 @group
 sequence.y:8.3-45: @dwarning{warning}: rule useless in parser due to conflicts [@dwarning{-Wother}]
@@ -10057,39 +10057,39 @@ sequence.y: @dwarning{warning}: shift/reduce conflict on token "word" [@dwarning
   Example: @red{•} @green{"word"}
   Shift derivation
     @yellow{sequence}
-    @yellow{@arrow{}} @green{maybeword}
-       @green{@arrow{}} @red{•} @green{"word"}
+    @yellow{@arrow{} 2:} @green{maybeword}
+          @green{@arrow{} 5:} @red{•} @green{"word"}
   Example: @red{•} @yellow{"word"}
   Reduce derivation
     @yellow{sequence}
-    @yellow{@arrow{}} @green{sequence} @yellow{"word"}
-       @green{@arrow{}} @red{•}
+    @yellow{@arrow{} 3:} @green{sequence} @yellow{"word"}
+          @green{@arrow{} 1:} @red{•}
 @end group
 @group
 sequence.y: @dwarning{warning}: reduce/reduce conflict on tokens $end, "word" [@dwarning{-Wcounterexamples}]
   Example: @red{•}
   First reduce derivation
     @yellow{sequence}
-    @yellow{@arrow{}} @red{•}
+    @yellow{@arrow{} 1:} @red{•}
   Example: @red{•}
   Second reduce derivation
     @yellow{sequence}
-    @yellow{@arrow{}} @green{maybeword}
-       @green{@arrow{}} @red{•}
+    @yellow{@arrow{} 2:} @green{maybeword}
+          @green{@arrow{}: 4} @red{•}
 @end group
 @group
 sequence.y: @dwarning{warning}: shift/reduce conflict on token "word" [@dwarning{-Wcounterexamples}]
   Example: @red{•} @green{"word"}
   Shift derivation
     @yellow{sequence}
-    @yellow{@arrow{}} @green{maybeword}
-       @green{@arrow{}} @red{•} @green{"word"}
+    @yellow{@arrow{} 2:} @green{maybeword}
+          @green{@arrow{} 5:} @red{•} @green{"word"}
   Example: @red{•} @yellow{"word"}
   Reduce derivation
     @yellow{sequence}
-    @yellow{@arrow{}} @green{sequence}    @yellow{"word"}
-      @green{@arrow{}} @blue{maybeword}
-         @blue{@arrow{}} @red{•}
+    @yellow{@arrow{} 3:} @green{sequence}        @yellow{"word"}
+          @green{@arrow{} 2:} @blue{maybeword}
+                @blue{@arrow{} 4:} @red{•}
 @end group
 @group
 sequence.y:8.3-45: @dwarning{warning}: rule useless in parser due to conflicts [@dwarning{-Wother}]
@@ -10130,16 +10130,16 @@ ids.y: @dwarning{warning}: shift/reduce conflict on token ID [@dwarning{-Wcounte
   First example: @purple{expr} @red{•} @purple{ID ','} @green{ID} @yellow{$end}
   Shift derivation
     @yellow{$accept}
-    @yellow{↳} @green{s}                      @yellow{$end}
-      @green{↳} @blue{a}                 @green{ID}
-        @blue{↳} @purple{expr}
-          @purple{↳ expr} @red{•} @purple{ID ','}
+    @yellow{↳ 0:} @green{s}                                 @yellow{$end}
+         @green{↳ 1:} @blue{a}                        @green{ID}
+              @blue{↳ 2:} @purple{expr}
+                    @purple{↳ 4: expr} @red{•} @purple{ID ','}
   Second example: @blue{expr} @red{•} @green{ID} @yellow{$end}
   Reduce derivation
     @yellow{$accept}
-    @yellow{↳} @green{s}             @yellow{$end}
-      @green{↳} @blue{a}        @green{ID}
-        @blue{↳ expr} @red{•}
+    @yellow{↳ 0:} @green{s}                   @yellow{$end}
+         @green{↳ 1:} @blue{a}           @green{ID}
+              @blue{↳ 2: expr} @red{•}
 @end group
 @group
 ids.y:4.4-7: @dwarning{warning}: rule useless in parser due to conflicts [@dwarning{-Wother}]
@@ -10152,16 +10152,16 @@ ids.y:4.4-7: @dwarning{warning}: rule useless in parser due to conflicts [@dwarn
   First example: @purple{expr} @red{•} @purple{ID ','} @green{ID} @yellow{$end}
   Shift derivation
     @yellow{$accept}
-    @yellow{@arrow{}} @green{s}                      @yellow{$end}
-       @green{@arrow{}} @blue{a}                 @green{ID}
-          @blue{@arrow{}} @purple{expr}
-             @purple{@arrow{} expr} @red{•} @purple{ID ','}
+    @yellow{@arrow{} 0:} @green{s}                                   @yellow{$end}
+          @green{@arrow{} 1:} @blue{a}                         @green{ID}
+                @blue{@arrow{} 2:} @purple{expr}
+                      @purple{@arrow{} 4: expr} @red{•} @purple{ID ','}
   Second example: @blue{expr} @red{•} @green{ID} @yellow{$end}
   Reduce derivation
     @yellow{$accept}
-    @yellow{@arrow{}} @green{s}             @yellow{$end}
-       @green{@arrow{}} @blue{a}        @green{ID}
-          @blue{@arrow{} expr} @red{•}
+    @yellow{@arrow{} 0:} @green{s}                     @yellow{$end}
+          @green{@arrow{} 1:} @blue{a}            @green{ID}
+                @blue{@arrow{} 2: expr} @red{•}
 @end group
 @group
 ids.y:4.4-7: @dwarning{warning}: rule useless in parser due to conflicts [@dwarning{-Wother}]
@@ -10570,13 +10570,13 @@ shift/reduce conflict on token '/':
   Example: exp '+' exp • '/' exp
   Shift derivation
     exp
-    ↳ exp '+' exp
-              ↳ exp • '/' exp
+    ↳ 1: exp '+' exp
+                 ↳ 4: exp • '/' exp
   Example: exp '+' exp • '/' exp
   Reduce derivation
     exp
-    ↳ exp             '/' exp
-      ↳ exp '+' exp •
+    ↳ 4: exp                 '/' exp
+         ↳ 1: exp '+' exp •
 @end group
 @end example
 @end ifnottex
@@ -10589,13 +10589,13 @@ shift/reduce conflict on token '/':
   Example: exp '+' exp • '/' exp
   Shift derivation
     exp
-    @arrow{} exp '+' exp
-               @arrow{} exp • '/' exp
+    @arrow{} 1: exp '+' exp
+                  @arrow{} 4: exp • '/' exp
   Example: exp '+' exp • '/' exp
   Reduce derivation
     exp
-    @arrow{} exp             '/' exp
-       @arrow{} exp '+' exp •
+    @arrow{} 4: exp                '/' exp
+          @arrow{} 1: exp '+' exp •
 @end group
 @end example
 @end iftex
diff --git a/doc/if-then-else.y b/doc/else.y
similarity index 100%
rename from doc/if-then-else.y
rename to doc/else.y
diff --git a/src/counterexample.c b/src/counterexample.c
index 8a19aa51..f38c7fd6 100644
--- a/src/counterexample.c
+++ b/src/counterexample.c
@@ -288,7 +288,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);
         }
@@ -422,7 +423,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 f1b37639..382dc458 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;
 }
@@ -205,6 +210,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
@@ -217,6 +239,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;
@@ -281,6 +304,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 70bfb177..41d5e583 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 07e4f7b1..d68f03aa 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..faf4c9a7 100644
--- a/tests/diagnostics.at
+++ b/tests/diagnostics.at
@@ -539,46 +539,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 +621,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 •
 
 ]])
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.