cex: fix traces

The display of disabled state items is incorrect.  The item is
stuttered, and lacks on end-of-line.

From

    State 7:
        1 exp: exp • "⊕" exp
        ->     1 exp: exp "⊕" • exp
        <-     1 exp: • exp "⊕" exp

        2 exp: exp • "+" exp    2 exp: exp • "+" exp DISABLED
        2 exp: exp "+" exp •
        <-     2 exp: exp "+" • exp

        3 exp: exp • "+" exp    3 exp: exp • "+" exp DISABLED
        3 exp: exp "+" exp •
        <-     3 exp: exp "+" • exp

to

    State 7:
        1 exp: exp • "⊕" exp
        ->     1 exp: exp "⊕" • exp
        <-     1 exp: • exp "⊕" exp

        2 exp: exp • "+" exp  DISABLED

        2 exp: exp "+" exp •
        <-     2 exp: exp "+" • exp

        3 exp: exp • "+" exp  DISABLED

        3 exp: exp "+" exp •
        <-     3 exp: exp "+" • exp

* src/state-item.c (state_items_report): Don't issue disabled items
twice, and issue two '\n' at their end.
* tests/conflicts.at: Check it.
This commit is contained in:
Akim Demaille
2021-01-16 15:05:30 +01:00
parent a9911528e0
commit d85ea95d6f
2 changed files with 301 additions and 24 deletions

View File

@@ -500,34 +500,33 @@ state_items_report (FILE *out)
fprintf (out, "State %d:\n", i);
for (state_item_number j = state_item_map[i]; j < state_item_map[i + 1]; ++j)
{
state_item *si = &state_items[j];
const state_item *si = &state_items[j];
item_print (si->item, NULL, out);
if (SI_DISABLED (j))
fputs (" DISABLED\n", out);
else
{
item_print (si->item, NULL, out);
fputs (" DISABLED\n", out);
continue;
}
putc ('\n', out);
if (si->trans >= 0)
{
fputs (" -> ", out);
state_item_print (&state_items[si->trans], out, "");
}
bitset sets[2] = { si->prods, si->revs };
const char *txt[2] = { " => ", " <- " };
for (int seti = 0; seti < 2; ++seti)
{
bitset b = sets[seti];
if (b)
putc ('\n', out);
if (si->trans >= 0)
{
bitset_iterator biter;
state_item_number sin;
BITSET_FOR_EACH (biter, b, sin, 0)
fputs (" -> ", out);
state_item_print (&state_items[si->trans], out, "");
}
bitset sets[2] = { si->prods, si->revs };
const char *txt[2] = { " => ", " <- " };
for (int seti = 0; seti < 2; ++seti)
{
bitset b = sets[seti];
if (b)
{
fputs (txt[seti], out);
state_item_print (&state_items[sin], out, "");
bitset_iterator biter;
state_item_number sin;
BITSET_FOR_EACH (biter, b, sin, 0)
{
fputs (txt[seti], out);
state_item_print (&state_items[sin], out, "");
}
}
}
}

View File

@@ -1956,7 +1956,285 @@ empty_c2: %prec 'c' ;
empty_c3: %prec 'c' ;
]])
AT_BISON_CHECK([[--report=all -o input.c input.y]], 0, [], [ignore])
AT_BISON_CHECK([[--trace=cex -fcaret --report=all -o input.c input.y]], 0, [],
[[init: 0.000000
# state items: 26
State 0:
0 $accept: . start $end
-> 0 $accept: start . $end
=> 2 start: . empty_a 'a'
=> 4 start: . empty_b 'b'
=> 6 start: . empty_c1 'c'
=> 7 start: . empty_c2 'c'
=> 8 start: . empty_c3 'c'
1 start: . 'a' DISABLED
2 start: . empty_a 'a'
-> 2 start: empty_a . 'a'
=> 9 empty_a: %empty .
<- 0 $accept: . start $end
3 start: . 'b' DISABLED
4 start: . empty_b 'b'
-> 4 start: empty_b . 'b'
=> 10 empty_b: %empty .
<- 0 $accept: . start $end
5 start: . 'c' DISABLED
6 start: . empty_c1 'c'
-> 6 start: empty_c1 . 'c'
=> 11 empty_c1: %empty .
<- 0 $accept: . start $end
7 start: . empty_c2 'c'
-> 7 start: empty_c2 . 'c'
=> 12 empty_c2: %empty .
<- 0 $accept: . start $end
8 start: . empty_c3 'c'
-> 8 start: empty_c3 . 'c'
=> 13 empty_c3: %empty .
<- 0 $accept: . start $end
9 empty_a: %empty .
<- 2 start: . empty_a 'a'
10 empty_b: %empty .
<- 4 start: . empty_b 'b'
11 empty_c1: %empty .
<- 6 start: . empty_c1 'c'
12 empty_c2: %empty .
<- 7 start: . empty_c2 'c'
13 empty_c3: %empty .
<- 8 start: . empty_c3 'c'
State 1:
0 $accept: start . $end
-> 0 $accept: start $end .
<- 0 $accept: . start $end
State 2:
2 start: empty_a . 'a'
-> 2 start: empty_a 'a' .
<- 2 start: . empty_a 'a'
State 3:
4 start: empty_b . 'b'
-> 4 start: empty_b 'b' .
<- 4 start: . empty_b 'b'
State 4:
6 start: empty_c1 . 'c'
-> 6 start: empty_c1 'c' .
<- 6 start: . empty_c1 'c'
State 5:
7 start: empty_c2 . 'c'
-> 7 start: empty_c2 'c' .
<- 7 start: . empty_c2 'c'
State 6:
8 start: empty_c3 . 'c'
-> 8 start: empty_c3 'c' .
<- 8 start: . empty_c3 'c'
State 7:
0 $accept: start $end .
<- 0 $accept: start . $end
State 8:
2 start: empty_a 'a' .
<- 2 start: empty_a . 'a'
State 9:
4 start: empty_b 'b' .
<- 4 start: empty_b . 'b'
State 10:
6 start: empty_c1 'c' .
<- 6 start: empty_c1 . 'c'
State 11:
7 start: empty_c2 'c' .
<- 7 start: empty_c2 . 'c'
State 12:
8 start: empty_c3 'c' .
<- 8 start: empty_c3 . 'c'
FIRSTS
$accept firsts
'a'
'b'
'c'
start firsts
'a'
'b'
'c'
empty_a firsts
empty_b firsts
empty_c1 firsts
empty_c2 firsts
empty_c3 firsts
input.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
input.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples
input.y:4.5-7: warning: rule useless in parser due to conflicts [-Wother]
4 | 'a'
| ^~~
input.y:6.5-7: warning: rule useless in parser due to conflicts [-Wother]
6 | | 'b'
| ^~~
input.y:8.5-7: warning: rule useless in parser due to conflicts [-Wother]
8 | | 'c'
| ^~~
input.y:13.10-18: warning: rule useless in parser due to conflicts [-Wother]
13 | empty_a: %prec 'a' ;
| ^~~~~~~~~
input.y:14.10-18: warning: rule useless in parser due to conflicts [-Wother]
14 | empty_b: %prec 'b' ;
| ^~~~~~~~~
input.y:15.11-19: warning: rule useless in parser due to conflicts [-Wother]
15 | empty_c1: %prec 'c' ;
| ^~~~~~~~~
input.y:16.11-19: warning: rule useless in parser due to conflicts [-Wother]
16 | empty_c2: %prec 'c' ;
| ^~~~~~~~~
input.y:17.11-19: warning: rule useless in parser due to conflicts [-Wother]
17 | empty_c3: %prec 'c' ;
| ^~~~~~~~~
REDUCE ITEM PATH:
0 $accept: . start $end
7 start: . empty_c2 'c'
12 empty_c2: %empty .
CONFLICT 1 (size 1 depth 0 rc 2)
12 empty_c2: %empty .
12 empty_c2: %empty .
.
CONFLICT 2 (size 1 depth 0 rc 2)
13 empty_c3: %empty .
13 empty_c3: %empty .
.
CONFLICT 1 (size 2 depth -1 rc 4)
7 start: . empty_c2 'c'
7 start: empty_c2 . 'c'
empty_c2
`-> 12: %empty .
CONFLICT 2 (size 1 depth 0 rc 3)
13 empty_c3: %empty .
13 empty_c3: %empty .
.
CONFLICT 1 (size 1 depth 0 rc 3)
12 empty_c2: %empty .
12 empty_c2: %empty .
.
CONFLICT 2 (size 2 depth -1 rc 2)
8 start: . empty_c3 'c'
8 start: empty_c3 . 'c'
empty_c3
`-> 13: %empty .
CONFLICT 1 (size 2 depth -1 rc 3)
7 start: . empty_c2 'c'
7 start: empty_c2 . 'c'
empty_c2
`-> 12: %empty .
CONFLICT 2 (size 2 depth -1 rc 2)
8 start: . empty_c3 'c'
8 start: empty_c3 . 'c'
empty_c3
`-> 13: %empty .
CONFLICT 1 (size 3 depth -1 rc 2)
7 start: . empty_c2 'c'
7 start: empty_c2 'c' .
empty_c2
`-> 12: %empty .
CONFLICT 2 (size 3 depth -1 rc 2)
8 start: . empty_c3 'c'
8 start: empty_c3 'c' .
empty_c3
`-> 13: %empty .
CONFLICT 1 (size 2 depth -1 rc 4)
0 $accept: . start $end
0 $accept: start . $end
start
`-> 7: empty_c2 'c'
`-> 12: %empty .
CONFLICT 2 (size 3 depth -1 rc 3)
8 start: . empty_c3 'c'
8 start: empty_c3 'c' .
empty_c3
`-> 13: %empty .
CONFLICT 1 (size 3 depth -1 rc 3)
7 start: . empty_c2 'c'
7 start: empty_c2 'c' .
empty_c2
`-> 12: %empty .
CONFLICT 2 (size 2 depth -1 rc 2)
0 $accept: . start $end
0 $accept: start . $end
start
`-> 8: empty_c3 'c'
`-> 13: %empty .
CONFLICT 1 (size 2 depth -1 rc 3)
0 $accept: . start $end
0 $accept: start . $end
start
`-> 7: empty_c2 'c'
`-> 12: %empty .
CONFLICT 2 (size 2 depth -1 rc 2)
0 $accept: . start $end
0 $accept: start . $end
start
`-> 8: empty_c3 'c'
`-> 13: %empty .
]])
AT_CHECK([[cat input.output | sed -n '/^State 0$/,/^State 1$/p']], 0,
[[State 0