%expect: tune the number of conflicts per rule

Currently on a grammar such as

    exp: "number" | exp "+" exp | exp "*" exp

we count only one sr-conflict for both binary rules, i.e., we expect:

    exp: "number" | exp "+" exp  %expect 1 | exp "*" exp  %expect 1

although there are 4 conflicts in total.  That's because in the states
in conflict, for instance that for the "+" rule:

    State 6

        2 exp: exp . "+" exp
        2    | exp "+" exp .  [$end, "+", "*"]
        3    | exp . "*" exp

        "+"  shift, and go to state 4
        "*"  shift, and go to state 5

        "+"       [reduce using rule 2 (exp)]
        "*"       [reduce using rule 2 (exp)]
        $default  reduce using rule 2 (exp)

we count only a single conflict, although there are two (one on "+"
and another with "*").

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

* src/conflicts.c (rule_has_state_sr_conflicts): Rename as...
(count_rule_state_sr_conflicts): this.
DWIM.
(count_rule_sr_conflicts): Adjust.
* tests/conflicts.at (%expect in grammar rules): New.
This commit is contained in:
Akim Demaille
2018-11-07 22:27:35 +01:00
parent 4ebebcc438
commit e51fd547ca
2 changed files with 35 additions and 12 deletions

View File

@@ -504,14 +504,15 @@ count_rr_conflicts (bool one_per_token)
} }
/*----------------------------------------------------------------------. /*------------------------------------------------------------------.
| For a given rule, count the number of states for which it is involved | | For a given rule, the number of shift/reduce conflicts in a given |
| in shift/reduce conflicts. | | state. |
`----------------------------------------------------------------------*/ `------------------------------------------------------------------*/
static bool static size_t
rule_has_state_sr_conflicts (rule *r, state *s) count_rule_state_sr_conflicts (rule *r, state *s)
{ {
size_t res = 0;
transitions *trans = s->transitions; transitions *trans = s->transitions;
reductions *reds = s->reductions; reductions *reds = s->reductions;
@@ -521,21 +522,24 @@ rule_has_state_sr_conflicts (rule *r, state *s)
bitset lookaheads = reds->lookahead_tokens[i]; bitset lookaheads = reds->lookahead_tokens[i];
int j; int j;
FOR_EACH_SHIFT (trans, j) FOR_EACH_SHIFT (trans, j)
if (bitset_test (lookaheads, TRANSITION_SYMBOL (trans, j))) res += bitset_test (lookaheads, TRANSITION_SYMBOL (trans, j));
return true;
break;
} }
return false; return res;
} }
/*----------------------------------------------------------------------.
| For a given rule, count the number of states for which it is involved |
| in shift/reduce conflicts. |
`----------------------------------------------------------------------*/
static size_t static size_t
count_rule_sr_conflicts (rule *r) count_rule_sr_conflicts (rule *r)
{ {
size_t res = 0; size_t res = 0;
for (state_number i = 0; i < nstates; ++i) for (state_number i = 0; i < nstates; ++i)
if (conflicts[i] && rule_has_state_sr_conflicts (r, states[i])) if (conflicts[i])
res++; res += count_rule_state_sr_conflicts (r, states[i]);
return res; return res;
} }

View File

@@ -1280,6 +1280,25 @@ AT_BISON_CHECK([-o input.c input.y])
AT_CLEANUP AT_CLEANUP
## -------------------------- ##
## %expect in grammar rules. ##
## -------------------------- ##
AT_SETUP([%expect in grammar rules])
AT_DATA([input.y],
[[%expect 4
%%
exp:
"number"
| exp "+" exp %expect 2
| exp "*" exp %expect 2
]])
AT_BISON_CHECK([-o input.c -rall input.y])
AT_CLEANUP
## ---------------------------------- ## ## ---------------------------------- ##
## %expect in grammar rule too much. ## ## %expect in grammar rule too much. ##
## ---------------------------------- ## ## ---------------------------------- ##