%expect-rr: tune the number of conflicts per rule

Currently on a grammar such as

    exp : a '1' | a '2' | a '3' | b '1' | b '2' | b '3'
    a:
    b:

we count only one rr-conflict on the `b:` rule, i.e., we expect:

    b: %expect-rr 1

although there are 3 conflicts in total.  That's because in the
conflicted state we count only a single conflict, not three (one for
each of the lookaheads: '1', '2', '3').

    State 0

        0 $accept: . exp $end
        1 exp: . a '1'
        2    | . a '2'
        3    | . a '3'
        4    | . b '1'
        5    | . b '2'
        6    | . b '3'
        7 a: . %empty  ['1', '2', '3']
        8 b: . %empty  ['1', '2', '3']

        '1'       reduce using rule 7 (a)
        '1'       [reduce using rule 8 (b)]
        '2'       reduce using rule 7 (a)
        '2'       [reduce using rule 8 (b)]
        '3'       reduce using rule 7 (a)
        '3'       [reduce using rule 8 (b)]
        $default  reduce using rule 7 (a)

        exp  go to state 1
        a    go to state 2
        b    go to state 3

See https://lists.gnu.org/archive/html/bison-patches/2013-02/msg00106.html.

* src/conflicts.c (rule_has_state_rr_conflicts): Rename as...
(count_rule_state_sr_conflicts): this.
DWIM.
(count_rule_rr_conflicts): Adjust.
* tests/conflicts.at (%expect-rr in grammar rules)
(%expect-rr too much in grammar rules)
(%expect-rr not enough in grammar rules): New.
This commit is contained in:
Akim Demaille
2018-11-09 17:29:29 +01:00
parent ad0b4661d1
commit 7ded5bb764
2 changed files with 100 additions and 16 deletions

View File

@@ -483,7 +483,7 @@ count_state_rr_conflicts (state *s)
int count = 0;
for (int j = 0; j < reds->num; ++j)
count += bitset_test (reds->lookahead_tokens[j], i);
if (count >= 2)
if (2 <= count)
res += count-1;
}
@@ -546,23 +546,25 @@ count_rule_sr_conflicts (rule *r)
| involved in reduce/reduce conflicts. |
`-----------------------------------------------------------------*/
static bool
rule_has_state_rr_conflicts (rule *r, state *s)
static size_t
count_rule_state_rr_conflicts (rule *r, state *s)
{
reductions *reds = s->reductions;
size_t res = 0;
const reductions *reds = s->reductions;
bitset lookaheads = bitset_create (ntokens, BITSET_FIXED);
for (int i = 0; i < reds->num; ++i)
if (reds->rules[i] == r)
{
bitset lookaheads = reds->lookahead_tokens[i];
for (int j = 0; j < reds->num; ++j)
if (reds->rules[j] != r &&
!bitset_disjoint_p (lookaheads, reds->lookahead_tokens[j]))
return true;
break;
if (reds->rules[j] != r)
{
bitset_and (lookaheads,
reds->lookahead_tokens[i],
reds->lookahead_tokens[j]);
res += bitset_count (lookaheads);
}
return false;
bitset_free (lookaheads);
return res;
}
static size_t
@@ -570,8 +572,7 @@ count_rule_rr_conflicts (rule *r)
{
size_t res = 0;
for (state_number i = 0; i < nstates; ++i)
if (conflicts[i] && rule_has_state_rr_conflicts (r, states[i]))
res++;
res += count_rule_state_rr_conflicts (r, states[i]);
return res;
}

View File

@@ -1318,6 +1318,89 @@ AT_BISON_CHECK([-o input.c input.y], 1, [],
AT_CLEANUP
## ---------------------------- ##
## %expect-rr in grammar rule. ##
## ---------------------------- ##
AT_SETUP([%expect-rr in grammar rule])
AT_DATA([input.y],
[[%glr-parser
%expect-rr 3
%%
exp
: a '1'
| a '2'
| a '3'
| b '1'
| b '2'
| b '3'
a:
b: %expect-rr 3
]])
AT_BISON_CHECK([-o input.c input.y])
AT_CLEANUP
## ------------------------------------- ##
## %expect-rr too much in grammar rule. ##
## ------------------------------------- ##
AT_SETUP([%expect-rr too much in grammar rule])
AT_DATA([input.y],
[[%glr-parser
%expect-rr 3
%%
exp
: a '1'
| a '2'
| a '3'
| b '1'
| b '2'
| b '3'
a:
b: %expect-rr 4
]])
AT_BISON_CHECK([-fcaret -o input.c input.y], 1, [],
[[input.y:12.4-15: error: reduce/reduce conflicts for rule 8: 3 found, 4 expected
b: %expect-rr 4
^^^^^^^^^^^^
]])
AT_CLEANUP
## --------------------------------------- ##
## %expect-rr not enough in grammar rule. ##
## --------------------------------------- ##
AT_SETUP([%expect-rr not enough in grammar rule])
AT_DATA([input.y],
[[%glr-parser
%expect-rr 3
%%
exp
: a '1'
| a '2'
| a '3'
| b '1'
| b '2'
| b '3'
a:
b: %expect-rr 2
]])
AT_BISON_CHECK([-fcaret -o input.c input.y], 1, [],
[[input.y:12.4-15: error: reduce/reduce conflicts for rule 8: 3 found, 2 expected
b: %expect-rr 2
^^^^^^^^^^^^
]])
AT_CLEANUP
## ------------------------- ##
## %prec with user strings. ##
## ------------------------- ##