cex: display derivations as trees

Sometimes, understanding the derivations is difficult, because they
are serialized to fit in one line.  For instance, the example taken
from the NEWS file:

    %token ID
    %%
    s: a ID
    a: expr
    expr: expr ID ',' | "expr"

gave

    First example        expr • ID ',' ID $end
    Shift derivation     $accept → [ s → [ a → [ expr → [ expr • ID ',' ] ] ID ] $end ]
    Second example       expr • ID $end
    Reduce derivation    $accept → [ s → [ a → [ expr • ] ID ] $end ]

Printing as trees, it gives:

    First example        expr • ID ',' ID $end
    Shift derivation
      $accept
      ↳ s                      $end
        ↳ a                 ID
          ↳ expr
            ↳ expr • ID ','
    Second example       expr • ID $end
    Reduce derivation
      $accept
      ↳ s             $end
        ↳ a        ID
          ↳ expr •

* src/glyphs.h, src/glyphs.c (down_arrow, empty, derivation_separator):
New.
* src/derivation.c (derivation_print, derivation_print_impl): Rename
as...
(derivation_print_flat, derivation_print_flat_impl): These.
(fputs_if, derivation_depth, derivation_width, derivation_print_tree)
(derivation_print_tree_impl, derivation_print): New.
* src/counterexample.c (print_counterexample): Adjust.
* tests/conflicts.at, tests/counterexample.at, tests/diagnostics.at,
* tests/report.at: Adjust.
This commit is contained in:
Akim Demaille
2020-07-14 08:16:16 +02:00
parent 5544615a59
commit fff17fe8fe
9 changed files with 986 additions and 72 deletions

27
NEWS
View File

@@ -46,9 +46,17 @@ Changes in the display of counterexamples.
strings in the grammar which can be parsed in two ways due to the strings in the grammar which can be parsed in two ways due to the
conflict. For example: conflict. For example:
Example exp '+' exp • '/' exp Shift/reduce conflict on token "/":
Shift derivation exp → [ exp '+' exp → [ exp • '/' exp ] ] Example exp "+" exp • "/" exp
Reduce derivation exp → [ exp → [ exp '+' exp • ] '/' exp ] Shift derivation
exp
↳ exp "+" exp
↳ exp • "/" exp
Example exp "+" exp • "/" exp
Reduce derivation
exp
↳ exp "/" exp
↳ exp "+" exp •
When Bison is installed with text styling enabled, the example is actually When Bison is installed with text styling enabled, the example is actually
shown twice, with colors highlighting the ambiguity. shown twice, with colors highlighting the ambiguity.
@@ -59,9 +67,18 @@ Changes in the display of counterexamples.
generates two examples that are the same up until the dot: generates two examples that are the same up until the dot:
First example expr • ID ',' ID $end First example expr • ID ',' ID $end
Shift derivation $accept → [ s → [ a → [ expr → [ expr • ID ',' ] ] ID ] $end ] Shift derivation
$accept
↳ s $end
↳ a ID
↳ expr
↳ expr • ID ','
Second example expr • ID $end Second example expr • ID $end
Reduce derivation $accept → [ s → [ a → [ expr • ] ID ] $end ] Reduce derivation
$accept
↳ s $end
↳ a ID
↳ expr •
In these cases, the parser usually doesn't have enough lookahead to In these cases, the parser usually doesn't have enough lookahead to
differentiate the two given examples. differentiate the two given examples.

View File

@@ -115,10 +115,11 @@ free_counterexample (counterexample *cex)
static void static void
print_counterexample (const counterexample *cex, FILE *out, const char *prefix) print_counterexample (const counterexample *cex, FILE *out, const char *prefix)
{ {
const bool flat = getenv ("YYFLAT");
fprintf (out, " %s%-20s ", fprintf (out, " %s%-20s ",
prefix, cex->unifying ? _("Example") : _("First example")); prefix, cex->unifying ? _("Example") : _("First example"));
derivation_print_leaves (cex->d1, out, prefix); derivation_print_leaves (cex->d1, out, prefix);
fprintf (out, " %s%-20s ", fprintf (out, flat ? " %s%-20s " : " %s%s",
prefix, cex->shift_reduce ? _("Shift derivation") : _("First derivation")); prefix, cex->shift_reduce ? _("Shift derivation") : _("First derivation"));
derivation_print (cex->d1, out, prefix); derivation_print (cex->d1, out, prefix);
@@ -131,7 +132,7 @@ print_counterexample (const counterexample *cex, FILE *out, const char *prefix)
prefix, cex->unifying ? _("Example") : _("Second example")); prefix, cex->unifying ? _("Example") : _("Second example"));
derivation_print_leaves (cex->d2, out, prefix); derivation_print_leaves (cex->d2, out, prefix);
} }
fprintf (out, " %s%-20s ", fprintf (out, flat ? " %s%-20s " : " %s%s",
prefix, cex->shift_reduce ? _("Reduce derivation") : _("Second derivation")); prefix, cex->shift_reduce ? _("Reduce derivation") : _("Second derivation"));
derivation_print (cex->d2, out, prefix); derivation_print (cex->d2, out, prefix);

View File

@@ -22,7 +22,9 @@
#include "derivation.h" #include "derivation.h"
#include "glyphs.h" #include "glyphs.h"
#include <c-ctype.h>
#include <gl_linked_list.h> #include <gl_linked_list.h>
#include <mbswidth.h>
#include "system.h" #include "system.h"
#include "complain.h" #include "complain.h"
@@ -32,9 +34,13 @@ struct derivation
symbol_number sym; symbol_number sym;
derivation_list children; derivation_list children;
int reference_count; int reference_count;
// 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 }; static derivation d_dot = { -1, NULL, -1, -1 };
derivation * derivation *
derivation_dot (void) derivation_dot (void)
@@ -74,6 +80,7 @@ derivation_new (symbol_number sym, derivation_list children)
deriv->sym = sym; deriv->sym = sym;
deriv->children = children; deriv->children = children;
deriv->reference_count = 0; deriv->reference_count = 0;
deriv->color = -1;
return deriv; return deriv;
} }
@@ -127,19 +134,235 @@ derivation_size (const derivation *deriv)
return size; return size;
} }
static int
max (int a, int b)
{
return a < b ? b : a;
}
// Longest distance from root to leaf.
static int
derivation_depth (const derivation *deriv)
{
if (deriv->children)
{
// Children's depth cannot be 0, even if there are no children
// (the case of a derivation with an empty RHS).
int res = 1;
derivation *child;
for (gl_list_iterator_t it = gl_list_iterator (deriv->children);
derivation_list_next (&it, &child);
)
res = max (res, derivation_depth (child));
return res + 1;
}
else
return 1;
}
static bool
all_spaces (const char *s)
{
while (c_isspace (*s))
s++;
return *s == '\0';
}
// Printing the derivation as trees without trailing spaces is
// painful: we cannot simply pad one "column" before moving to the
// next:
//
// exp
// ↳ x1 e1 foo1 x1
// ↳ x2 ↳ ε ↳ foo2 ↳ x2
// ↳ x3 ↳ foo3 ↳ x3
// ↳ "X" • ↳ x1 foo4 ↳ "X"
// ↳ x2 ↳ "quuux"
// ↳ x3
// ↳ "X"
//
// It's hard for a column to know that it's "last" to decide whether
// to output the right-padding or not. So when we need to pad on the
// right to complete a column, we don't output the spaces, we
// accumulate the width of padding in *PADDING.
//
// Each time we actually print something (non space), we flush that
// padding. When we _don't_ print something, its width is added to
// the current padding.
//
// This function implements this.
//
// When COND is true, put S on OUT, preceeded by *PADDING white
// spaces. Otherwise add the width to *PADDING. Return the width of
// S.
static int
fputs_if (bool cond, FILE *out, int *padding, const char *s)
{
int res = mbswidth (s, 0);
if (cond && !all_spaces (s))
{
fprintf (out, "%*s%s", *padding, "", s);
*padding = 0;
}
else
{
*padding += res;
}
return res;
}
// The width taken to report this derivation recursively down to its
// leaves.
static int
derivation_width (const derivation *deriv)
{
if (deriv->children)
{
const symbol *sym = symbols[deriv->sym];
int self_width = mbswidth (sym->tag, 0);
// Arrow and space.
int children_width = down_arrow_width;
if (gl_list_size (deriv->children) == 0)
// Empty rhs.
children_width += empty_width;
else
{
derivation *child;
for (gl_list_iterator_t it = gl_list_iterator (deriv->children);
derivation_list_next (&it, &child);
)
children_width
+= derivation_separator_width + derivation_width (child);
// No separator at the beginning.
children_width -= derivation_separator_width;
}
return max (self_width, children_width);
}
else if (deriv == &d_dot)
{
return dot_width;
}
else // leaf.
{
const symbol *sym = symbols[deriv->sym];
return mbswidth (sym->tag, 0);
}
}
// Print DERIV for DEPTH.
//
// The tree is printed from top to bottom with DEPTH ranging from 0 to
// the total depth of the tree. DERIV should only printed when we
// reach its depth, i.e., then DEPTH is 0.
//
// When DEPTH is 1 and we're on a subderivation, then we print the RHS
// of the derivation (in DEPTH 0 we printed its LHS).
//
// Return the "logical printed" width. We might have not have reached
// that width, in which case the missing spaces are in *PADDING.
static int
derivation_print_tree_impl (const derivation *deriv, FILE *out,
int depth, int *padding)
{
const int width = derivation_width (deriv);
int res = 0;
if (deriv->children)
{
const symbol *sym = symbols[deriv->sym];
char style[20];
snprintf (style, 20, "cex-%d", deriv->color);
if (depth == 0 || depth == 1)
{
begin_use_class (style, out);
begin_use_class ("cex-step", out);
}
if (depth == 0)
{
res += fputs_if (true, out, padding, sym->tag);
}
else
{
res += fputs_if (depth == 1, out, padding, down_arrow);
if (gl_list_size (deriv->children) == 0)
// Empty rhs.
res += fputs_if (depth == 1, out, padding, empty);
else
{
bool first = true;
derivation *child;
for (gl_list_iterator_t it = gl_list_iterator (deriv->children);
derivation_list_next (&it, &child);
)
{
if (!first)
res += fputs_if (depth == 1, out, padding, derivation_separator);
res += derivation_print_tree_impl (child, out, depth - 1, padding);
first = false;
}
}
}
if (depth == 0 || depth == 1)
{
end_use_class ("cex-step", out);
end_use_class (style, out);
}
*padding += width - res;
res = width;
}
else if (deriv == &d_dot)
{
if (depth == 0)
begin_use_class ("cex-dot", out);
res += fputs_if (depth == 0, out, padding, dot);
if (depth == 0)
end_use_class ("cex-dot", out);
}
else // leaf.
{
const symbol *sym = symbols[deriv->sym];
if (depth == 0)
begin_use_class ("cex-leaf", out);
res += fputs_if (depth == 0, out, padding, sym->tag);
if (depth == 0)
end_use_class ("cex-leaf", out);
}
return res;
}
static void
derivation_print_tree (const derivation *deriv, FILE *out, const char *prefix)
{
fputc ('\n', out);
for (int depth = 0, max_depth = derivation_depth (deriv);
depth < max_depth; ++depth)
{
int padding = 0;
fprintf (out, " %s", prefix);
derivation_print_tree_impl (deriv, out, depth, &padding);
fputc ('\n', out);
}
}
/* Print DERIV, colored according to COUNTER. /* Print DERIV, colored according to COUNTER.
Return false if nothing is printed. */ Return false if nothing is printed. */
static bool static bool
derivation_print_impl (const derivation *deriv, FILE *out, derivation_print_flat_impl (derivation *deriv, FILE *out,
bool leaves_only, bool leaves_only,
int *counter, const char *prefix) int *counter, const char *prefix)
{ {
if (deriv->children) if (deriv->children)
{ {
const symbol *sym = symbols[deriv->sym]; const symbol *sym = symbols[deriv->sym];
char style[20]; deriv->color = *counter;
snprintf (style, 20, "cex-%d", *counter);
++*counter; ++*counter;
char style[20];
snprintf (style, 20, "cex-%d", deriv->color);
begin_use_class (style, out); begin_use_class (style, out);
if (!leaves_only) if (!leaves_only)
@@ -156,7 +379,8 @@ derivation_print_impl (const derivation *deriv, FILE *out,
derivation_list_next (&it, &child); derivation_list_next (&it, &child);
) )
{ {
if (derivation_print_impl (child, out, leaves_only, counter, prefix)) if (derivation_print_flat_impl (child, out,
leaves_only, counter, prefix))
{ {
prefix = " "; prefix = " ";
res = true; res = true;
@@ -194,21 +418,29 @@ derivation_print_impl (const derivation *deriv, FILE *out,
return true; return true;
} }
void static void
derivation_print (const derivation *deriv, FILE *out, const char *prefix) derivation_print_flat (const derivation *deriv, FILE *out, const char *prefix)
{ {
int counter = 0; int counter = 0;
fputs (prefix, out); fputs (prefix, out);
derivation_print_impl (deriv, out, false, &counter, ""); derivation_print_flat_impl ((derivation *)deriv, out, false, &counter, "");
fputc ('\n', out); fputc ('\n', out);
} }
void void
derivation_print_leaves (const derivation *deriv, FILE *out, const char *prefix) derivation_print_leaves (const derivation *deriv, FILE *out, const char *prefix)
{ {
int counter = 0; int counter = 0;
fputs (prefix, out); fputs (prefix, out);
derivation_print_impl (deriv, out, true, &counter, ""); derivation_print_flat_impl ((derivation *)deriv, out, true, &counter, "");
fputc ('\n', out); fputc ('\n', out);
} }
void
derivation_print (const derivation *deriv, FILE *out, const char *prefix)
{
if (getenv ("YYFLAT"))
derivation_print_flat (deriv, out, prefix);
else
derivation_print_tree (deriv, out, prefix);
}

View File

@@ -36,10 +36,21 @@ static glyph_buffer_t arrow_buf;
const char *arrow; const char *arrow;
int arrow_width; int arrow_width;
static glyph_buffer_t down_arrow_buf;
const char *down_arrow;
int down_arrow_width;
static glyph_buffer_t dot_buf; static glyph_buffer_t dot_buf;
const char *dot; const char *dot;
int dot_width; int dot_width;
static glyph_buffer_t empty_buf;
const char *empty;
int empty_width;
const char *derivation_separator = " ";
int derivation_separator_width = 1;
typedef struct typedef struct
{ {
const char **glyph; const char **glyph;
@@ -54,7 +65,6 @@ on_success (const char *buf, size_t buflen, void *callback_arg)
callback_arg_t *arg = (callback_arg_t *) callback_arg; callback_arg_t *arg = (callback_arg_t *) callback_arg;
assert (buflen < sizeof arg->buf); assert (buflen < sizeof arg->buf);
strncpy (arg->buf, buf, buflen); strncpy (arg->buf, buf, buflen);
*arg->glyph = arg->buf;
return 1; return 1;
} }
@@ -63,7 +73,8 @@ on_failure (unsigned code MAYBE_UNUSED, const char *msg MAYBE_UNUSED,
void *callback_arg) void *callback_arg)
{ {
callback_arg_t *arg = (callback_arg_t *) callback_arg; callback_arg_t *arg = (callback_arg_t *) callback_arg;
*arg->glyph = arg->fallback; assert (strlen (arg->fallback) < sizeof arg->buf);
strcpy (arg->buf, arg->fallback);
return 0; return 0;
} }
@@ -74,6 +85,7 @@ glyph_set (const char **glyph,
{ {
callback_arg_t arg = { glyph, buf, fallback }; callback_arg_t arg = { glyph, buf, fallback };
int res = unicode_to_mb (code, on_success, on_failure, &arg); int res = unicode_to_mb (code, on_success, on_failure, &arg);
*glyph = buf;
*width = mbswidth (*glyph, 0); *width = mbswidth (*glyph, 0);
return res; return res;
} }
@@ -83,4 +95,9 @@ glyphs_init (void)
{ {
glyph_set (&arrow, arrow_buf, &arrow_width, 0x2192, "->"); glyph_set (&arrow, arrow_buf, &arrow_width, 0x2192, "->");
glyph_set (&dot, dot_buf, &dot_width, 0x2022, "."); glyph_set (&dot, dot_buf, &dot_width, 0x2022, ".");
glyph_set (&down_arrow, down_arrow_buf, &down_arrow_width, 0x21b3, "`->");
glyph_set (&empty, empty_buf, &empty_width, 0x03b5, "%empty");
strncat (down_arrow_buf, " ", sizeof down_arrow_buf - strlen (down_arrow_buf) - 1);
down_arrow_width += 1;
} }

View File

@@ -31,4 +31,16 @@ extern int arrow_width;
extern const char *dot; extern const char *dot;
extern int dot_width; extern int dot_width;
/* "↳ ", below an lhs to announce the rhs. */
extern const char *down_arrow;
extern int down_arrow_width;
/* "ε", an empty rhs. */
extern const char *empty;
extern int empty_width;
/* " ", separate symbols in the rhs of a derivation. */
extern const char *derivation_separator;
extern int derivation_separator_width;
#endif /* GLYPHS_H */ #endif /* GLYPHS_H */

View File

@@ -865,8 +865,14 @@ State 5
1 exp: exp OP exp . 1 exp: exp OP exp .
1 exp: exp . OP exp 1 exp: exp . OP exp
Example exp OP exp . OP exp Example exp OP exp . OP exp
Shift derivation exp -> [ exp OP exp -> [ exp . OP exp ] ] Shift derivation
Reduce derivation exp -> [ exp -> [ exp OP exp . ] OP exp ] exp
`-> exp OP exp
`-> exp . OP exp
Reduce derivation
exp
`-> exp OP exp
`-> exp OP exp .
]]) ]])
@@ -1119,7 +1125,7 @@ m4_popdef([AT_TEST])
# else. # else.
AT_SETUP([Defaulted Conflicted Reduction]) AT_SETUP([Defaulted Conflicted Reduction])
AT_KEYWORDS([report]) AT_KEYWORDS([cex report])
AT_DATA([input.y], AT_DATA([input.y],
[[%% [[%%
@@ -1207,8 +1213,14 @@ State 1
3 num: '0' . 3 num: '0' .
4 id: '0' . 4 id: '0' .
Example '0' . Example '0' .
First derivation exp -> [ num -> [ '0' . ] ] First derivation
Second derivation exp -> [ id -> [ '0' . ] ] exp
`-> num
`-> '0' .
Second derivation
exp
`-> id
`-> '0' .
@@ -1579,6 +1591,8 @@ AT_CLEANUP
AT_SETUP([[Unreachable States After Conflict Resolution]]) AT_SETUP([[Unreachable States After Conflict Resolution]])
AT_KEYWORDS([cex report])
# If conflict resolution makes states unreachable, remove those states, report # If conflict resolution makes states unreachable, remove those states, report
# rules that are then unused, and don't report conflicts in those states. Test # rules that are then unused, and don't report conflicts in those states. Test
# what happens when a nonterminal becomes useless as a result of state removal # what happens when a nonterminal becomes useless as a result of state removal
@@ -1754,17 +1768,29 @@ State 4
10 reported_conflicts: . %empty 10 reported_conflicts: . %empty
8 reported_conflicts: . 'a' 8 reported_conflicts: . 'a'
First example resolved_conflict . 'a' 'a' First example resolved_conflict . 'a' 'a'
Shift derivation start -> [ resolved_conflict reported_conflicts -> [ . 'a' ] 'a' ] Shift derivation
start
`-> resolved_conflict reported_conflicts 'a'
`-> . 'a'
Second example resolved_conflict . 'a' Second example resolved_conflict . 'a'
Reduce derivation start -> [ resolved_conflict reported_conflicts -> [ . ] 'a' ] Reduce derivation
start
`-> resolved_conflict reported_conflicts 'a'
`-> .
Shift/reduce conflict on token 'a': Shift/reduce conflict on token 'a':
10 reported_conflicts: . %empty 10 reported_conflicts: . %empty
9 reported_conflicts: . 'a' 9 reported_conflicts: . 'a'
First example resolved_conflict . 'a' 'a' First example resolved_conflict . 'a' 'a'
Shift derivation start -> [ resolved_conflict reported_conflicts -> [ . 'a' ] 'a' ] Shift derivation
start
`-> resolved_conflict reported_conflicts 'a'
`-> . 'a'
Second example resolved_conflict . 'a' Second example resolved_conflict . 'a'
Reduce derivation start -> [ resolved_conflict reported_conflicts -> [ . ] 'a' ] Reduce derivation
start
`-> resolved_conflict reported_conflicts 'a'
`-> .
@@ -1781,8 +1807,12 @@ State 5
8 reported_conflicts: 'a' . 8 reported_conflicts: 'a' .
9 reported_conflicts: 'a' . 9 reported_conflicts: 'a' .
Example 'a' . Example 'a' .
First derivation reported_conflicts -> [ 'a' . ] First derivation
Second derivation reported_conflicts -> [ 'a' . ] reported_conflicts
`-> 'a' .
Second derivation
reported_conflicts
`-> 'a' .
@@ -1904,6 +1934,8 @@ AT_CLEANUP
AT_SETUP([[%nonassoc error actions for multiple reductions in a state]]) AT_SETUP([[%nonassoc error actions for multiple reductions in a state]])
AT_KEYWORDS([cex report])
AT_DATA([[input.y]], AT_DATA([[input.y]],
[[%nonassoc 'a' 'b' 'c' [[%nonassoc 'a' 'b' 'c'
%% %%
@@ -1965,8 +1997,14 @@ AT_CHECK([[cat input.output | sed -n '/^State 0$/,/^State 1$/p']], 0,
12 empty_c2: . %empty 12 empty_c2: . %empty
13 empty_c3: . %empty 13 empty_c3: . %empty
Example . 'c' Example . 'c'
First derivation start -> [ empty_c2 -> [ . ] 'c' ] First derivation
Second derivation start -> [ empty_c3 -> [ . ] 'c' ] start
`-> empty_c2 'c'
`-> .
Second derivation
start
`-> empty_c3 'c'
`-> .

View File

@@ -17,14 +17,23 @@
AT_BANNER([[Counterexamples.]]) AT_BANNER([[Counterexamples.]])
# AT_BISON_CHECK_CEX(EXPERR) # AT_BISON_CHECK_CEX(TREE, FLAT)
# -------------------------- # ------------------------------
m4_define([AT_BISON_CHECK_CEX], m4_define([AT_BISON_CHECK_CEX],
[AT_KEYWORDS([cex]) [AT_KEYWORDS([cex])
AT_DATA([expout], [$1])
AT_BISON_CHECK([-Wcounterexamples input.y], [0], [], [stderr])
# FIXME: Avoid trailing white spaces.
AT_CHECK([[sed -e 's/time limit exceeded: [0-9][.0-9]*/time limit exceeded: XXX/g;s/ *$//;' stderr]],
[], [$1])
m4_pushdef([AT_SET_ENV_IF],
[[YYFLAT=1; export YYFLAT;]]m4_defn([AT_SET_ENV_IF]))
AT_BISON_CHECK([-Wcounterexamples input.y], [0], [], [stderr]) AT_BISON_CHECK([-Wcounterexamples input.y], [0], [], [stderr])
AT_CHECK([[sed -e 's/time limit exceeded: [0-9][.0-9]*/time limit exceeded: XXX/g' stderr]], AT_CHECK([[sed -e 's/time limit exceeded: [0-9][.0-9]*/time limit exceeded: XXX/g' stderr]],
[], [expout]) [], [$2])
m4_popdef([AT_SET_ENV_IF])
]) ])
## --------------------- ## ## --------------------- ##
@@ -45,6 +54,20 @@ y: A | A B;
AT_BISON_CHECK_CEX( AT_BISON_CHECK_CEX(
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr] [[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
Shift/reduce conflict on token B:
Example A . B C
Shift derivation
s
`-> y c
`-> A . B `-> C
Reduce derivation
s
`-> a x
`-> A . `-> B C
input.y:4.4: warning: rule useless in parser due to conflicts [-Wother]
]],
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
Shift/reduce conflict on token B: Shift/reduce conflict on token B:
Example A . B C Example A . B C
Shift derivation s -> [ y -> [ A . B ] c -> [ C ] ] Shift derivation s -> [ y -> [ A . B ] c -> [ C ] ]
@@ -73,6 +96,38 @@ bc: B bc C | B C;
AT_BISON_CHECK_CEX( AT_BISON_CHECK_CEX(
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr] [[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
Shift/reduce conflict on token B:
Example A . B C
Shift derivation
s
`-> ac
`-> A ac C
`-> b
`-> . B
Reduce derivation
s
`-> a bc
`-> A . `-> B C
Shift/reduce conflict on token B:
Example A A . B B C C
Shift derivation
s
`-> ac
`-> A ac C
`-> A ac C
`-> b
`-> . b
`-> B B
Reduce derivation
s
`-> a bc
`-> A a `-> B bc C
`-> A . `-> B C
input.y:6.4: warning: rule useless in parser due to conflicts [-Wother]
]],
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
Shift/reduce conflict on token B: Shift/reduce conflict on token B:
Example A . B C Example A . B C
Shift derivation s -> [ ac -> [ A ac -> [ b -> [ . B ] ] C ] ] Shift derivation s -> [ ac -> [ A ac -> [ b -> [ . B ] ] C ] ]
@@ -107,6 +162,38 @@ xby: B | X xby Y;
AT_BISON_CHECK_CEX( AT_BISON_CHECK_CEX(
[[input.y: warning: 2 shift/reduce conflicts [-Wconflicts-sr] [[input.y: warning: 2 shift/reduce conflicts [-Wconflicts-sr]
Shift/reduce conflict on token B:
Example A . B
Shift derivation
s
`-> A xby
`-> . B
Reduce derivation
s
`-> ax by
`-> A x `-> B y
`-> . `-> %empty
Shift/reduce conflict on token B:
First example A X . B Y $end
Shift derivation
$accept
`-> s $end
`-> A xby
`-> X xby Y
`-> . B
Second example A X . B y $end
Reduce derivation
$accept
`-> s $end
`-> ax by
`-> A x `-> B y
`-> X x
`-> .
input.y:5.4-9: warning: rule useless in parser due to conflicts [-Wother]
]],
[[input.y: warning: 2 shift/reduce conflicts [-Wconflicts-sr]
Shift/reduce conflict on token B: Shift/reduce conflict on token B:
Example A . B Example A . B
Shift derivation s -> [ A xby -> [ . B ] ] Shift derivation s -> [ A xby -> [ . B ] ]
@@ -142,6 +229,25 @@ bc: B C;
AT_BISON_CHECK_CEX( AT_BISON_CHECK_CEX(
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr] [[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
Shift/reduce conflict on token C:
First example B . C $end
Shift derivation
$accept
`-> g $end
`-> x
`-> bc
`-> B . C
Second example B . C D $end
Reduce derivation
$accept
`-> g $end
`-> x
`-> b cd
`-> B . `-> C D
input.y:6.4: warning: rule useless in parser due to conflicts [-Wother]
]],
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
Shift/reduce conflict on token C: Shift/reduce conflict on token C:
First example B . C $end First example B . C $end
Shift derivation $accept -> [ g -> [ x -> [ bc -> [ B . C ] ] ] $end ] Shift derivation $accept -> [ g -> [ x -> [ bc -> [ B . C ] ] ] $end ]
@@ -170,6 +276,25 @@ y: A A B;
AT_BISON_CHECK_CEX( AT_BISON_CHECK_CEX(
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr] [[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
Shift/reduce conflict on token A:
First example A . A B $end
Shift derivation
$accept
`-> s $end
`-> t
`-> y
`-> A . A B
Second example A . A $end
Reduce derivation
$accept
`-> s $end
`-> s t
`-> t `-> x
`-> x `-> A
`-> A .
]],
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
Shift/reduce conflict on token A: Shift/reduce conflict on token A:
First example A . A B $end First example A . A B $end
Shift derivation $accept -> [ s -> [ t -> [ y -> [ A . A B ] ] ] $end ] Shift derivation $accept -> [ s -> [ t -> [ y -> [ A . A B ] ] ] $end ]
@@ -202,6 +327,36 @@ y: Y;
AT_BISON_CHECK_CEX( AT_BISON_CHECK_CEX(
[[input.y: warning: 2 shift/reduce conflicts [-Wconflicts-sr] [[input.y: warning: 2 shift/reduce conflicts [-Wconflicts-sr]
Shift/reduce conflict on token A:
Example b . A X X Y
Shift derivation
a
`-> s
`-> b . xx y
`-> A X X `-> Y
Reduce derivation
a
`-> r t
`-> b . `-> A x xy
`-> X `-> X Y
Shift/reduce conflict on token X:
First example A X . X
Shift derivation
a
`-> t
`-> A xx
`-> X . X
Second example X . X xy
Reduce derivation
a
`-> x t
`-> X . `-> 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]
]],
[[input.y: warning: 2 shift/reduce conflicts [-Wconflicts-sr]
Shift/reduce conflict on token A: Shift/reduce conflict on token A:
Example b . A X X Y Example b . A X X Y
Shift derivation a -> [ s -> [ b . xx -> [ A X X ] y -> [ Y ] ] ] Shift derivation a -> [ s -> [ b . xx -> [ A X X ] y -> [ Y ] ] ]
@@ -234,6 +389,19 @@ b : A | b;
AT_BISON_CHECK_CEX( AT_BISON_CHECK_CEX(
[[input.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr] [[input.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
Reduce/reduce conflict on token $end:
Example A b .
First derivation
a
`-> A b .
Second derivation
a
`-> A b
`-> b .
input.y:4.9: warning: rule useless in parser due to conflicts [-Wother]
]],
[[input.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
Reduce/reduce conflict on token $end: Reduce/reduce conflict on token $end:
Example A b . Example A b .
First derivation a -> [ A b . ] First derivation a -> [ A b . ]
@@ -260,6 +428,23 @@ b: D;
AT_BISON_CHECK_CEX( AT_BISON_CHECK_CEX(
[[input.y: warning: 2 reduce/reduce conflicts [-Wconflicts-rr] [[input.y: warning: 2 reduce/reduce conflicts [-Wconflicts-rr]
Reduce/reduce conflict on tokens A, C:
First example D . A $end
First derivation
$accept
`-> s $end
`-> a A
`-> D .
Second example B D . A $end
Second derivation
$accept
`-> s $end
`-> B b A
`-> D .
input.y:5.4: warning: rule useless in parser due to conflicts [-Wother]
]],
[[input.y: warning: 2 reduce/reduce conflicts [-Wconflicts-rr]
Reduce/reduce conflict on tokens A, C: Reduce/reduce conflict on tokens A, C:
First example D . A $end First example D . A $end
First derivation $accept -> [ s -> [ a -> [ D . ] A ] $end ] First derivation $accept -> [ s -> [ a -> [ D . ] A ] $end ]
@@ -288,6 +473,24 @@ i: X | i J K;
AT_BISON_CHECK_CEX( AT_BISON_CHECK_CEX(
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr] [[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
Shift/reduce conflict on token J: Shift/reduce conflict on token J:
time limit exceeded: XXX
First example H i . J K $end
Shift derivation
$accept
`-> a $end
`-> H i
`-> i . J K
Second example H i . J $end
Reduce derivation
$accept
`-> s $end
`-> a J
`-> 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]
Shift/reduce conflict on token J:
time limit exceeded: XXX time limit exceeded: XXX
First example H i . J K $end First example H i . J K $end
Shift derivation $accept -> [ a -> [ H i -> [ i . J K ] ] $end ] Shift derivation $accept -> [ a -> [ H i -> [ i . J K ] ] $end ]
@@ -319,6 +522,37 @@ b: A B C | A B D;
AT_BISON_CHECK_CEX( AT_BISON_CHECK_CEX(
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr] [[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
Shift/reduce conflict on token B:
Example N A . B C
Shift derivation
s
`-> n
`-> N b
`-> A . B C
Reduce derivation
s
`-> n C
`-> N a B
`-> A .
Shift/reduce conflict on token B:
Example N N A . B D C
Shift derivation
s
`-> n
`-> N n C
`-> N b
`-> A . B D
Reduce derivation
s
`-> n C
`-> N n D
`-> N a B
`-> A .
input.y:5.4: warning: rule useless in parser due to conflicts [-Wother]
]],
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
Shift/reduce conflict on token B: Shift/reduce conflict on token B:
Example N A . B C Example N A . B C
Shift derivation s -> [ n -> [ N b -> [ A . B C ] ] ] Shift derivation s -> [ n -> [ N b -> [ A . B C ] ] ]
@@ -355,6 +589,38 @@ C : A c A;
AT_BISON_CHECK_CEX( AT_BISON_CHECK_CEX(
[[input.y: warning: 4 reduce/reduce conflicts [-Wconflicts-rr] [[input.y: warning: 4 reduce/reduce conflicts [-Wconflicts-rr]
Reduce/reduce conflict on tokens b, c:
Example B . b c
First derivation
S
`-> B C
`-> A b A `-> A c A
`-> B . `-> %empty `-> %empty `-> %empty
Second derivation
S
`-> B C
`-> A c A
`-> B `-> %empty
`-> A b A
`-> . `-> %empty
Reduce/reduce conflict on tokens b, c:
Example C . c b
First derivation
S
`-> C B
`-> A c A `-> A b A
`-> C . `-> %empty `-> %empty `-> %empty
Second derivation
S
`-> C B
`-> A b A
`-> C `-> %empty
`-> A c A
`-> . `-> %empty
]],
[[input.y: warning: 4 reduce/reduce conflicts [-Wconflicts-rr]
Reduce/reduce conflict on tokens b, c: Reduce/reduce conflict on tokens b, c:
Example B . b c Example B . b c
First derivation S -> [ B -> [ A -> [ B . ] b A -> [ ] ] C -> [ A -> [ ] c A -> [ ] ] ] First derivation S -> [ B -> [ A -> [ B . ] b A -> [ ] ] C -> [ A -> [ ] c A -> [ ] ] ]
@@ -387,6 +653,136 @@ d : a | c A | d;
AT_BISON_CHECK_CEX( AT_BISON_CHECK_CEX(
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr] [[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
input.y: warning: 6 reduce/reduce conflicts [-Wconflicts-rr] input.y: warning: 6 reduce/reduce conflicts [-Wconflicts-rr]
Reduce/reduce conflict on token A:
First example . c A A $end
First derivation
$accept
`-> a $end
`-> b d
`-> . `-> c A A
Second example . c A A $end
Second derivation
$accept
`-> a $end
`-> c d
`-> . `-> c A A
Reduce/reduce conflict on token A:
time limit exceeded: XXX
First example b . c A A $end
First derivation
$accept
`-> a $end
`-> b d
`-> a
`-> b d
`-> . `-> c A A
Second example b . A $end
Second derivation
$accept
`-> a $end
`-> b d
`-> c A
`-> .
Reduce/reduce conflict on token A:
time limit exceeded: XXX
First example c . c A A $end
First derivation
$accept
`-> a $end
`-> c d
`-> a
`-> b d
`-> . `-> c A A
Second example c . A $end
Second derivation
$accept
`-> a $end
`-> c d
`-> c A
`-> .
Shift/reduce conflict on token A:
time limit exceeded: XXX
First example b c . A
Shift derivation
a
`-> b d
`-> 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
Reduce/reduce conflict on token A:
First example b c . c A A $end
First derivation
$accept
`-> a $end
`-> b d
`-> a
`-> c d
`-> a
`-> b d
`-> . `-> c A A
Second example b c . A $end
Second derivation
$accept
`-> a $end
`-> b d
`-> a
`-> c d
`-> c A
`-> .
Shift/reduce conflict on token A:
First example b c . A
Shift derivation
a
`-> b d
`-> c . A
Second example b c . A $end
Reduce derivation
$accept
`-> a $end
`-> b d
`-> a
`-> c d
`-> c A
`-> .
Reduce/reduce conflict on token $end:
Example b d .
First derivation
a
`-> b d .
Second derivation
a
`-> b d
`-> d .
Reduce/reduce conflict on token $end:
Example c d .
First derivation
a
`-> c d .
Second derivation
a
`-> c d
`-> 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]
]],
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
input.y: warning: 6 reduce/reduce conflicts [-Wconflicts-rr]
Reduce/reduce conflict on token A: Reduce/reduce conflict on token A:
First example . c A A $end First example . c A A $end
First derivation $accept -> [ a -> [ b -> [ . ] d -> [ c A A ] ] $end ] First derivation $accept -> [ a -> [ b -> [ . ] d -> [ c A A ] ] $end ]
@@ -461,6 +857,21 @@ i: %empty | i J;
AT_BISON_CHECK_CEX( AT_BISON_CHECK_CEX(
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr] [[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
Shift/reduce conflict on token J:
Example H i J . J J
Shift derivation
s
`-> a J
`-> H i J . J
Reduce derivation
s
`-> a
`-> H i J J
`-> 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]
Shift/reduce conflict on token J: Shift/reduce conflict on token J:
Example H i J . J J Example H i J . J J
Shift derivation s -> [ a -> [ H i J . J ] J ] Shift derivation s -> [ a -> [ H i J . J ] J ]
@@ -492,6 +903,21 @@ d: D;
AT_BISON_CHECK_CEX( AT_BISON_CHECK_CEX(
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr] [[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
Shift/reduce conflict on token D:
Example A a . D
Shift derivation
s
`-> A a d
`-> . D
Reduce derivation
s
`-> A a a d
`-> b `-> D
`-> c
`-> .
]],
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
Shift/reduce conflict on token D: Shift/reduce conflict on token D:
Example A a . D Example A a . D
Shift derivation s -> [ A a d -> [ . D ] ] Shift derivation s -> [ A a d -> [ . D ] ]
@@ -521,6 +947,24 @@ d: D;
AT_BISON_CHECK_CEX( AT_BISON_CHECK_CEX(
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr] [[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
Shift/reduce conflict on token D:
First example A a . D $end
Shift derivation
$accept
`-> s $end
`-> A a d
`-> . D
Second example A a . D E $end
Reduce derivation
$accept
`-> s $end
`-> A a a d E
`-> b `-> D
`-> c
`-> .
]],
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
Shift/reduce conflict on token D: Shift/reduce conflict on token D:
First example A a . D $end First example A a . D $end
Shift derivation $accept -> [ s -> [ A a d -> [ . D ] ] $end ] Shift derivation $accept -> [ s -> [ A a d -> [ . D ] ] $end ]

View File

@@ -28,6 +28,8 @@ m4_pushdef([AT_TEST],
AT_SETUP([$1]) AT_SETUP([$1])
AT_KEYWORDS([diagnostics]) AT_KEYWORDS([diagnostics])
m4_if(m4_index([$1], [Counterexample]), [-1], [], [AT_KEYWORDS([cex])])
# We need UTF-8 support for correct screen-width computation of UTF-8 # We need UTF-8 support for correct screen-width computation of UTF-8
# characters. Skip the test if not available. # characters. Skip the test if not available.
locale=`locale -a | $EGREP '^en_US\.(UTF-8|utf8)$' | sed 1q` locale=`locale -a | $EGREP '^en_US\.(UTF-8|utf8)$' | sed 1q`
@@ -535,32 +537,114 @@ exp
]], ]],
[1], [1],
[[input.y: <error>error:</error> shift/reduce conflicts: 4 found, 0 expected [[input.y: <error>error:</error> shift/reduce conflicts: 4 found, 0 expected
Shift/reduce conflict on token "+": Shift/reduce conflict on token "+":
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-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>
Shift derivation <cex-0><cex-step>exp → [ </cex-step><cex-leaf>exp</cex-leaf> <cex-leaf>"+"</cex-leaf><cex-1> <cex-step>exp → [ </cex-step><cex-leaf>exp</cex-leaf> <cex-dot>•</cex-dot> <cex-leaf>"+"</cex-leaf> <cex-leaf>exp</cex-leaf><cex-step> ]</cex-step></cex-1><cex-step> ]</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>
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-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-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>
Shift/reduce conflict on token "else": Shift/reduce conflict on token "else":
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-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>
Shift derivation <cex-0><cex-step>exp → [ </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-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-step></cex-1><cex-step> ]</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>
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-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-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>
Shift/reduce conflict on token "+": Shift/reduce conflict on token "+":
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-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>
Shift derivation <cex-0><cex-step>exp → [ </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-leaf>exp</cex-leaf> <cex-dot>•</cex-dot> <cex-leaf>"+"</cex-leaf> <cex-leaf>exp</cex-leaf><cex-step> ]</cex-step></cex-1><cex-step> ]</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>
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-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-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>
Shift/reduce conflict on token "+": Shift/reduce conflict on token "+":
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-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>
Shift derivation <cex-0><cex-step>exp → [ </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-leaf>exp</cex-leaf> <cex-dot>•</cex-dot> <cex-leaf>"+"</cex-leaf> <cex-leaf>exp</cex-leaf><cex-step> ]</cex-step></cex-1><cex-step> ]</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>
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-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-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>
]]) ]])
AT_TEST([[Deep Counterexamples]],
[[%expect 0
%%
exp: x1 e1 foo1 x1 | y1 e2 bar1 y1
foo1: foo2
foo2: foo3
foo3: x1 foo4 foo3: x1 foo4
foo4: "quuux"
bar1: bar2
bar2: bar3
bar3: y1 bar4
bar4: "quuux"
x1: x2
x2: x3
x3: "X"
y1: y2
y2: y3
y3: "X"
e1:
e2:
]],
[1],
[[input.y:30.4: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
30 | e1:
| <warning>^</warning>
| <fixit-insert>%empty</fixit-insert>
input.y:31.4: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
31 | e2:
| <warning>^</warning>
| <fixit-insert>%empty</fixit-insert>
input.y: <error>error:</error> reduce/reduce conflicts: 1 found, 0 expected
Reduce/reduce conflict on token "X":
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 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>
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 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>
input.y: <warning>warning:</warning> fix-its can be applied. Rerun with option '--update'. [<warning>-Wother</warning>] input.y: <warning>warning:</warning> fix-its can be applied. Rerun with option '--update'. [<warning>-Wother</warning>]
]]) ]])

View File

@@ -1539,39 +1539,74 @@ AT_CHECK([LC_ALL="$locale" bison -fno-caret -o input.cc -rall -Wcex --graph=inpu
input.y: warning: 3 reduce/reduce conflicts [-Wconflicts-rr] input.y: warning: 3 reduce/reduce conflicts [-Wconflicts-rr]
Shift/reduce conflict on token "⊕": Shift/reduce conflict on token "⊕":
Example exp "+" exp • "⊕" exp Example exp "+" exp • "⊕" exp
Shift derivation exp → [ exp "+" exp → [ exp • "⊕" exp ] ] Shift derivation
Reduce derivation exp → [ exp → [ exp "+" exp • ] "⊕" exp ] exp
↳ exp "+" exp
↳ exp • "⊕" exp
Reduce derivation
exp
↳ exp "⊕" exp
↳ exp "+" exp •
Reduce/reduce conflict on tokens $end, "+", "⊕": Reduce/reduce conflict on tokens $end, "+", "⊕":
Example exp "+" exp • Example exp "+" exp •
First derivation exp → [ exp "+" exp • ] First derivation
Second derivation exp → [ exp "+" exp • ] exp
↳ exp "+" exp •
Second derivation
exp
↳ exp "+" exp •
Shift/reduce conflict on token "⊕": Shift/reduce conflict on token "⊕":
Example exp "+" exp • "⊕" exp Example exp "+" exp • "⊕" exp
Shift derivation exp → [ exp "+" exp → [ exp • "⊕" exp ] ] Shift derivation
Reduce derivation exp → [ exp → [ exp "+" exp • ] "⊕" exp ] exp
↳ exp "+" exp
↳ exp • "⊕" exp
Reduce derivation
exp
↳ exp "⊕" exp
↳ exp "+" exp •
Shift/reduce conflict on token "⊕": Shift/reduce conflict on token "⊕":
Example exp "⊕" exp • "⊕" exp Example exp "⊕" exp • "⊕" exp
Shift derivation exp → [ exp "⊕" exp → [ exp • "⊕" exp ] ] Shift derivation
Reduce derivation exp → [ exp → [ exp "⊕" exp • ] "⊕" exp ] exp
↳ exp "⊕" exp
↳ exp • "⊕" exp
Reduce derivation
exp
↳ exp "⊕" exp
↳ exp "⊕" exp •
Shift/reduce conflict on token "+": Shift/reduce conflict on token "+":
Example exp "⊕" exp • "+" exp Example exp "⊕" exp • "+" exp
Shift derivation exp → [ exp "⊕" exp → [ exp • "+" exp ] ] Shift derivation
Reduce derivation exp → [ exp → [ exp "⊕" exp • ] "+" exp ] exp
↳ exp "⊕" exp
↳ exp • "+" exp
Reduce derivation
exp
↳ exp "+" exp
↳ exp "⊕" exp •
Shift/reduce conflict on token "+": Shift/reduce conflict on token "+":
Example exp "⊕" exp • "+" exp Example exp "⊕" exp • "+" exp
Shift derivation exp → [ exp "⊕" exp → [ exp • "+" exp ] ] Shift derivation
Reduce derivation exp → [ exp → [ exp "⊕" exp • ] "+" exp ] exp
↳ exp "⊕" exp
↳ exp • "+" exp
Reduce derivation
exp
↳ exp "+" exp
↳ exp "⊕" exp •
input.y:6.3-13: warning: rule useless in parser due to conflicts [-Wother] input.y:6.3-13: warning: rule useless in parser due to conflicts [-Wother]
]]) ]])
# Check the contents of the report. # Check the contents of the report.
AT_CHECK([cat input.output], [], # FIXME: Avoid trailing white spaces.
AT_CHECK([sed -e 's/ *$//' input.output], [],
[[Rules useless in parser due to conflicts [[Rules useless in parser due to conflicts
3 exp: exp "+" exp 3 exp: exp "+" exp
@@ -1714,22 +1749,38 @@ State 7
2 exp: exp "+" exp • 2 exp: exp "+" exp •
1 exp: exp • "⊕" exp 1 exp: exp • "⊕" exp
Example exp "+" exp • "⊕" exp Example exp "+" exp • "⊕" exp
Shift derivation exp → [ exp "+" exp → [ exp • "⊕" exp ] ] Shift derivation
Reduce derivation exp → [ exp → [ exp "+" exp • ] "⊕" exp ] exp
↳ exp "+" exp
↳ exp • "⊕" exp
Reduce derivation
exp
↳ exp "⊕" exp
↳ exp "+" exp •
Reduce/reduce conflict on tokens $end, "+", "⊕": Reduce/reduce conflict on tokens $end, "+", "⊕":
2 exp: exp "+" exp • 2 exp: exp "+" exp •
3 exp: exp "+" exp • 3 exp: exp "+" exp •
Example exp "+" exp • Example exp "+" exp •
First derivation exp → [ exp "+" exp • ] First derivation
Second derivation exp → [ exp "+" exp • ] exp
↳ exp "+" exp •
Second derivation
exp
↳ exp "+" exp •
Shift/reduce conflict on token "⊕": Shift/reduce conflict on token "⊕":
3 exp: exp "+" exp • 3 exp: exp "+" exp •
1 exp: exp • "⊕" exp 1 exp: exp • "⊕" exp
Example exp "+" exp • "⊕" exp Example exp "+" exp • "⊕" exp
Shift derivation exp → [ exp "+" exp → [ exp • "⊕" exp ] ] Shift derivation
Reduce derivation exp → [ exp → [ exp "+" exp • ] "⊕" exp ] exp
↳ exp "+" exp
↳ exp • "⊕" exp
Reduce derivation
exp
↳ exp "⊕" exp
↳ exp "+" exp •
@@ -1751,22 +1802,40 @@ State 8
1 exp: exp "⊕" exp • 1 exp: exp "⊕" exp •
1 exp: exp • "⊕" exp 1 exp: exp • "⊕" exp
Example exp "⊕" exp • "⊕" exp Example exp "⊕" exp • "⊕" exp
Shift derivation exp → [ exp "⊕" exp → [ exp • "⊕" exp ] ] Shift derivation
Reduce derivation exp → [ exp → [ exp "⊕" exp • ] "⊕" exp ] exp
↳ exp "⊕" exp
↳ exp • "⊕" exp
Reduce derivation
exp
↳ exp "⊕" exp
↳ exp "⊕" exp •
Shift/reduce conflict on token "+": Shift/reduce conflict on token "+":
1 exp: exp "⊕" exp • 1 exp: exp "⊕" exp •
2 exp: exp • "+" exp 2 exp: exp • "+" exp
Example exp "⊕" exp • "+" exp Example exp "⊕" exp • "+" exp
Shift derivation exp → [ exp "⊕" exp → [ exp • "+" exp ] ] Shift derivation
Reduce derivation exp → [ exp → [ exp "⊕" exp • ] "+" exp ] exp
↳ exp "⊕" exp
↳ exp • "+" exp
Reduce derivation
exp
↳ exp "+" exp
↳ exp "⊕" exp •
Shift/reduce conflict on token "+": Shift/reduce conflict on token "+":
1 exp: exp "⊕" exp • 1 exp: exp "⊕" exp •
3 exp: exp • "+" exp 3 exp: exp • "+" exp
Example exp "⊕" exp • "+" exp Example exp "⊕" exp • "+" exp
Shift derivation exp → [ exp "⊕" exp → [ exp • "+" exp ] ] Shift derivation
Reduce derivation exp → [ exp → [ exp "⊕" exp • ] "+" exp ] exp
↳ exp "⊕" exp
↳ exp • "+" exp
Reduce derivation
exp
↳ exp "+" exp
↳ exp "⊕" exp •
]]) ]])