summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkim Demaille <akim.demaille@gmail.com>2020-08-31 07:22:17 +0200
committerAkim Demaille <akim.demaille@gmail.com>2020-09-02 07:31:55 +0200
commit325ec7d32414d3b732d22387bb54da6918ec2ffc (patch)
treefccbfcd581bda06ee997710a730f486bb8f1560d
parent82d913741bbebec4b8be974141801ce328920f67 (diff)
downloadbison-325ec7d32414d3b732d22387bb54da6918ec2ffc.tar.gz
cex: always show ε/%empty in counterexamples
On a case such as %% exp : empty "a" | "a" empty empty : %empty we used to display warning: shift/reduce conflict on token "a" [-Wcounterexamples] Example: • "a" Shift derivation exp ↳ 2: • "a" empty ↳ 2: ε Example: • "a" Reduce derivation exp ↳ 1: empty "a" ↳ 3: • where the shift derivation shows an item "2: empty → ε", with an explicit "ε", but the reduce derivation shows "3: empty → •", without "ε". For consistency, let's always show ε/%empty in rules with an empty rhs: Reduce derivation exp ↳ 1: empty "a" ↳ 3: ε • * src/derivation.c (derivation_width, derivation_print_tree_impl): Always show ε/%empty in counterexamples. * tests/diagnostics.at: Check that case. * tests/conflicts.at, tests/counterexample.at: Adjust.
-rw-r--r--NEWS11
-rw-r--r--doc/bison.texi4
-rw-r--r--src/derivation.c14
-rw-r--r--tests/conflicts.at12
-rw-r--r--tests/counterexample.at104
-rw-r--r--tests/diagnostics.at62
6 files changed, 141 insertions, 66 deletions
diff --git a/NEWS b/NEWS
index c14d17f2..5f869f12 100644
--- a/NEWS
+++ b/NEWS
@@ -19,17 +19,18 @@ GNU Bison NEWS
*** Counterexamples
- Counterexamples now show the rule numbers:
+ Counterexamples now show the rule numbers, and always show ε for rules
+ with an empty right-hand side. For instance
exp
- ↳ 1: "if" exp "then" exp
- ↳ 2: "if" exp "then" exp • "else" exp
+ ↳ 1: e1 e2 "a"
+ ↳ 3: ε • ↳ 1: ε
instead of
exp
- ↳ "if" exp "then" exp
- ↳ "if" exp "then" exp • "else" exp
+ ↳ e1 e2 "a"
+ ↳ • ↳ ε
* Noteworthy changes in release 3.7.1 (2020-08-02) [stable]
diff --git a/doc/bison.texi b/doc/bison.texi
index e36f8a38..f9aaf343 100644
--- a/doc/bison.texi
+++ b/doc/bison.texi
@@ -10605,8 +10605,8 @@ This shows two separate derivations in the grammar for the same @code{exp}:
given example. Here, the first derivation completes a reduction when seeing
@samp{/}, causing @samp{e1 + e2} to be grouped as an @code{exp}. The second
derivation shifts on @samp{/}, resulting in @samp{e2 / e3} being grouped as
-an @code{exp}. Therefore, it is easy to see that adding @code{%precedence}
-directives would fix this conflict.
+an @code{exp}. Therefore, it is easy to see that adding
+precedence/associativity directives would fix this conflict.
The remaining states are similar:
diff --git a/src/derivation.c b/src/derivation.c
index 382dc458..433f504e 100644
--- a/src/derivation.c
+++ b/src/derivation.c
@@ -245,6 +245,13 @@ derivation_width (const derivation *deriv)
children_width += empty_width;
else
{
+ if (gl_list_size (deriv->children) == 1
+ && gl_list_get_first (deriv->children) == &d_dot)
+ {
+ children_width += empty_width;
+ children_width += derivation_separator_width;
+ }
+
derivation *child;
for (gl_list_iterator_t it = gl_list_iterator (deriv->children);
derivation_list_next (&it, &child);
@@ -310,6 +317,13 @@ derivation_print_tree_impl (const derivation *deriv, FILE *out,
res += fputs_if (depth == 1, out, padding, empty);
else
{
+ if (gl_list_size (deriv->children) == 1
+ && gl_list_get_first (deriv->children) == &d_dot)
+ {
+ res += fputs_if (depth == 1, out, padding, empty);
+ res += fputs_if (depth == 1, out, padding, derivation_separator);
+ }
+
bool first = true;
derivation *child;
for (gl_list_iterator_t it = gl_list_iterator (deriv->children);
diff --git a/tests/conflicts.at b/tests/conflicts.at
index d68f03aa..de0a993e 100644
--- a/tests/conflicts.at
+++ b/tests/conflicts.at
@@ -1776,7 +1776,7 @@ State 4
Reduce derivation
start
`-> 1: resolved_conflict reported_conflicts 'a'
- `-> 10: .
+ `-> 10: %empty .
shift/reduce conflict on token 'a':
10 reported_conflicts: . %empty
@@ -1790,7 +1790,7 @@ State 4
Reduce derivation
start
`-> 1: resolved_conflict reported_conflicts 'a'
- `-> 10: .
+ `-> 10: %empty .
@@ -1999,12 +1999,12 @@ AT_CHECK([[cat input.output | sed -n '/^State 0$/,/^State 1$/p']], 0,
Example: . 'c'
First reduce derivation
start
- `-> 7: empty_c2 'c'
- `-> 12: .
+ `-> 7: empty_c2 'c'
+ `-> 12: %empty .
Second reduce derivation
start
- `-> 8: empty_c3 'c'
- `-> 13: .
+ `-> 8: empty_c3 'c'
+ `-> 13: %empty .
diff --git a/tests/counterexample.at b/tests/counterexample.at
index bd9c1e96..fcc239bb 100644
--- a/tests/counterexample.at
+++ b/tests/counterexample.at
@@ -164,9 +164,9 @@ input.y: warning: shift/reduce conflict on token B [-Wcounterexamples]
`-> 9: . B
Reduce derivation
s
- `-> 1: ax by
- `-> 3: A x `-> 6: B y
- `-> 4: . `-> 6: %empty
+ `-> 1: ax by
+ `-> 3: A x `-> 6: B y
+ `-> 4: %empty . `-> 6: %empty
input.y: warning: shift/reduce conflict on token B [-Wcounterexamples]
First example: A X . B Y $end
Shift derivation
@@ -178,11 +178,11 @@ input.y: warning: shift/reduce conflict on token B [-Wcounterexamples]
Second example: A X . B y $end
Reduce derivation
$accept
- `-> 0: s $end
- `-> 1: ax by
- `-> 3: A x `-> 6: B y
+ `-> 0: s $end
+ `-> 1: ax by
+ `-> 3: A x `-> 6: B y
`-> 5: X x
- `-> 4: .
+ `-> 4: %empty .
input.y:5.4-9: warning: rule useless in parser due to conflicts [-Wother]
]],
[[input.y: warning: 2 shift/reduce conflicts [-Wconflicts-sr]
@@ -571,10 +571,10 @@ input.y: warning: reduce/reduce conflict on tokens b, c [-Wcounterexamples]
Second reduce derivation
S
`-> 1: B C
- `-> 7: A c A
- `-> 3: B `-> 7: %empty
- `-> 6: A b A
- `-> 5: . `-> 6: %empty
+ `-> 7: A c A
+ `-> 3: B `-> 7: %empty
+ `-> 6: A b A
+ `-> 5: %empty . `-> 6: %empty
input.y: warning: reduce/reduce conflict on tokens b, c [-Wcounterexamples]
Example: C . c b
First reduce derivation
@@ -585,10 +585,10 @@ input.y: warning: reduce/reduce conflict on tokens b, c [-Wcounterexamples]
Second reduce derivation
S
`-> 2: C B
- `-> 6: A b A
- `-> 4: C `-> 6: %empty
- `-> 7: A c A
- `-> 5: . `-> 7: %empty
+ `-> 6: A b A
+ `-> 4: C `-> 6: %empty
+ `-> 7: A c A
+ `-> 5: %empty . `-> 7: %empty
]],
[[input.y: warning: 4 reduce/reduce conflicts [-Wconflicts-rr]
input.y: warning: reduce/reduce conflict on tokens b, c [-Wcounterexamples]
@@ -625,49 +625,49 @@ input.y: warning: reduce/reduce conflict on token A [-Wcounterexamples]
First example: . c A A $end
First reduce derivation
$accept
- `-> 0: a $end
- `-> 1: b d
- `-> 3: . `-> 6: c A A
+ `-> 0: a $end
+ `-> 1: b d
+ `-> 3: %empty . `-> 6: c A A
Second example: . c A A $end
Second reduce derivation
$accept
- `-> 0: a $end
- `-> 2: c d
- `-> 4: . `-> 6: c A A
+ `-> 0: a $end
+ `-> 2: c d
+ `-> 4: %empty . `-> 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
- `-> 0: a $end
+ `-> 0: a $end
`-> 1: b d
`-> 5: a
- `-> 1: b d
- `-> 3: . `-> 6: c A A
+ `-> 1: b d
+ `-> 3: %empty . `-> 6: c A A
Second example: b . A $end
Second reduce derivation
$accept
- `-> 0: a $end
+ `-> 0: a $end
`-> 1: b d
- `-> 6: c A
- `-> 4: .
+ `-> 6: c A
+ `-> 4: %empty .
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
- `-> 0: a $end
+ `-> 0: a $end
`-> 2: c d
`-> 5: a
- `-> 1: b d
- `-> 3: . `-> 6: c A A
+ `-> 1: b d
+ `-> 3: %empty . `-> 6: c A A
Second example: c . A $end
Second reduce derivation
$accept
- `-> 0: a $end
+ `-> 0: a $end
`-> 2: c d
- `-> 6: c A
- `-> 4: .
+ `-> 6: c A
+ `-> 4: %empty .
input.y: warning: shift/reduce conflict on token A [-Wcounterexamples]
time limit exceeded: XXX
First example: b c . A
@@ -678,33 +678,33 @@ time limit exceeded: XXX
Second example: b c . c A A $end
Reduce derivation
$accept
- `-> 0: a $end
+ `-> 0: a $end
`-> 1: b d
`-> 5: a
`-> 2: c d
`-> 5: a
- `-> 1: b d
- `-> 3: . `-> 6: c A A
+ `-> 1: b d
+ `-> 3: %empty . `-> 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
- `-> 0: a $end
+ `-> 0: a $end
`-> 1: b d
`-> 5: a
`-> 2: c d
`-> 5: a
- `-> 1: b d
- `-> 3: . `-> 6: c A A
+ `-> 1: b d
+ `-> 3: %empty . `-> 6: c A A
Second example: b c . A $end
Second reduce derivation
$accept
- `-> 0: a $end
+ `-> 0: a $end
`-> 1: b d
`-> 5: a
`-> 2: c d
- `-> 6: c A
- `-> 4: .
+ `-> 6: c A
+ `-> 4: %empty .
input.y: warning: shift/reduce conflict on token A [-Wcounterexamples]
First example: b c . A
Shift derivation
@@ -714,12 +714,12 @@ input.y: warning: shift/reduce conflict on token A [-Wcounterexamples]
Second example: b c . A $end
Reduce derivation
$accept
- `-> 0: a $end
+ `-> 0: a $end
`-> 1: b d
`-> 5: a
`-> 2: c d
- `-> 6: c A
- `-> 4: .
+ `-> 6: c A
+ `-> 4: %empty .
input.y: warning: reduce/reduce conflict on token $end [-Wcounterexamples]
Example: b d .
First reduce derivation
@@ -861,10 +861,10 @@ input.y: warning: shift/reduce conflict on token D [-Wcounterexamples]
`-> 6: . D
Reduce derivation
s
- `-> 2: A a a d
- `-> 3: b `-> 6: D
+ `-> 2: A a a d
+ `-> 3: b `-> 6: D
`-> 4: c
- `-> 5: .
+ `-> 5: %empty .
]],
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
input.y: warning: shift/reduce conflict on token D [-Wcounterexamples]
@@ -905,11 +905,11 @@ input.y: warning: shift/reduce conflict on token D [-Wcounterexamples]
Second example: A a . D E $end
Reduce derivation
$accept
- `-> 0: s $end
- `-> 2: A a a d E
- `-> 3: b `-> 6: D
+ `-> 0: s $end
+ `-> 2: A a a d E
+ `-> 3: b `-> 6: D
`-> 4: c
- `-> 5: .
+ `-> 5: %empty .
]],
[[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 faf4c9a7..42b6d3a8 100644
--- a/tests/diagnostics.at
+++ b/tests/diagnostics.at
@@ -532,9 +532,58 @@ exp
| "if" exp "then" exp "else" exp
| exp "+" exp
| "num"
+| empty "a"
+| "a" empty
+
+empty
+: %empty
]],
[1],
-[[input.y: <error>error:</error> shift/reduce conflicts: 4 found, 0 expected
+[[input.y: <error>error:</error> shift/reduce conflicts: 9 found, 0 expected
+input.y: <warning>warning:</warning> shift/reduce conflict on token "a" [<warning>-Wcounterexamples</warning>]
+ Example: <cex-0><cex-dot>•</cex-dot> <cex-leaf>"a"</cex-leaf><cex-1></cex-1></cex-0>
+ Shift derivation
+ <cex-0><cex-step>exp</cex-step></cex-0>
+ <cex-0><cex-step>↳ 6: <cex-dot>•</cex-dot><cex-leaf> "a"</cex-leaf><cex-1><cex-step> empty</cex-step></cex-1></cex-step></cex-0>
+ <cex-1><cex-step> ↳ 6: ε</cex-step></cex-1>
+ Example: <cex-0><cex-1><cex-dot>•</cex-dot></cex-1> <cex-leaf>"a"</cex-leaf></cex-0>
+ Reduce derivation
+ <cex-0><cex-step>exp</cex-step></cex-0>
+ <cex-0><cex-step>↳ 5: <cex-1><cex-step>empty</cex-step></cex-1><cex-leaf> "a"</cex-leaf></cex-step></cex-0>
+ <cex-1><cex-step> ↳ 7: ε<cex-dot> •</cex-dot></cex-step></cex-1>
+input.y: <warning>warning:</warning> shift/reduce conflict on token "a" [<warning>-Wcounterexamples</warning>]
+ Example: <cex-0><cex-dot>•</cex-dot> <cex-leaf>"a"</cex-leaf><cex-1></cex-1></cex-0>
+ Shift derivation
+ <cex-0><cex-step>exp</cex-step></cex-0>
+ <cex-0><cex-step>↳ 6: <cex-dot>•</cex-dot><cex-leaf> "a"</cex-leaf><cex-1><cex-step> empty</cex-step></cex-1></cex-step></cex-0>
+ <cex-1><cex-step> ↳ 6: ε</cex-step></cex-1>
+ Example: <cex-0><cex-1><cex-dot>•</cex-dot></cex-1> <cex-leaf>"a"</cex-leaf></cex-0>
+ Reduce derivation
+ <cex-0><cex-step>exp</cex-step></cex-0>
+ <cex-0><cex-step>↳ 5: <cex-1><cex-step>empty</cex-step></cex-1><cex-leaf> "a"</cex-leaf></cex-step></cex-0>
+ <cex-1><cex-step> ↳ 7: ε<cex-dot> •</cex-dot></cex-step></cex-1>
+input.y: <warning>warning:</warning> shift/reduce conflict on token "a" [<warning>-Wcounterexamples</warning>]
+ Example: <cex-0><cex-dot>•</cex-dot> <cex-leaf>"a"</cex-leaf><cex-1></cex-1></cex-0>
+ Shift derivation
+ <cex-0><cex-step>exp</cex-step></cex-0>
+ <cex-0><cex-step>↳ 6: <cex-dot>•</cex-dot><cex-leaf> "a"</cex-leaf><cex-1><cex-step> empty</cex-step></cex-1></cex-step></cex-0>
+ <cex-1><cex-step> ↳ 6: ε</cex-step></cex-1>
+ Example: <cex-0><cex-1><cex-dot>•</cex-dot></cex-1> <cex-leaf>"a"</cex-leaf></cex-0>
+ Reduce derivation
+ <cex-0><cex-step>exp</cex-step></cex-0>
+ <cex-0><cex-step>↳ 5: <cex-1><cex-step>empty</cex-step></cex-1><cex-leaf> "a"</cex-leaf></cex-step></cex-0>
+ <cex-1><cex-step> ↳ 7: ε<cex-dot> •</cex-dot></cex-step></cex-1>
+input.y: <warning>warning:</warning> shift/reduce conflict on token "a" [<warning>-Wcounterexamples</warning>]
+ Example: <cex-0><cex-dot>•</cex-dot> <cex-leaf>"a"</cex-leaf><cex-1></cex-1></cex-0>
+ Shift derivation
+ <cex-0><cex-step>exp</cex-step></cex-0>
+ <cex-0><cex-step>↳ 6: <cex-dot>•</cex-dot><cex-leaf> "a"</cex-leaf><cex-1><cex-step> empty</cex-step></cex-1></cex-step></cex-0>
+ <cex-1><cex-step> ↳ 6: ε</cex-step></cex-1>
+ Example: <cex-0><cex-1><cex-dot>•</cex-dot></cex-1> <cex-leaf>"a"</cex-leaf></cex-0>
+ Reduce derivation
+ <cex-0><cex-step>exp</cex-step></cex-0>
+ <cex-0><cex-step>↳ 5: <cex-1><cex-step>empty</cex-step></cex-1><cex-leaf> "a"</cex-leaf></cex-step></cex-0>
+ <cex-1><cex-step> ↳ 7: ε<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>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
@@ -568,6 +617,17 @@ input.y: <warning>warning:</warning> shift/reduce conflict on token "+" [<warnin
<cex-0><cex-step>exp</cex-step></cex-0>
<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 "a" [<warning>-Wcounterexamples</warning>]
+ Example: <cex-0><cex-dot>•</cex-dot> <cex-leaf>"a"</cex-leaf><cex-1></cex-1></cex-0>
+ Shift derivation
+ <cex-0><cex-step>exp</cex-step></cex-0>
+ <cex-0><cex-step>↳ 6: <cex-dot>•</cex-dot><cex-leaf> "a"</cex-leaf><cex-1><cex-step> empty</cex-step></cex-1></cex-step></cex-0>
+ <cex-1><cex-step> ↳ 6: ε</cex-step></cex-1>
+ Example: <cex-0><cex-1><cex-dot>•</cex-dot></cex-1> <cex-leaf>"a"</cex-leaf></cex-0>
+ Reduce derivation
+ <cex-0><cex-step>exp</cex-step></cex-0>
+ <cex-0><cex-step>↳ 5: <cex-1><cex-step>empty</cex-step></cex-1><cex-leaf> "a"</cex-leaf></cex-step></cex-0>
+ <cex-1><cex-step> ↳ 7: ε<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