From e51fd547ca70894069d8b9d7100ec5309f6c0e3f Mon Sep 17 00:00:00 2001 From: Akim Demaille Date: Wed, 7 Nov 2018 22:27:35 +0100 Subject: [PATCH] %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. --- src/conflicts.c | 28 ++++++++++++++++------------ tests/conflicts.at | 19 +++++++++++++++++++ 2 files changed, 35 insertions(+), 12 deletions(-) diff --git a/src/conflicts.c b/src/conflicts.c index 5e7268a7..2838243e 100644 --- a/src/conflicts.c +++ b/src/conflicts.c @@ -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 | -| in shift/reduce conflicts. | -`----------------------------------------------------------------------*/ +/*------------------------------------------------------------------. +| For a given rule, the number of shift/reduce conflicts in a given | +| state. | +`------------------------------------------------------------------*/ -static bool -rule_has_state_sr_conflicts (rule *r, state *s) +static size_t +count_rule_state_sr_conflicts (rule *r, state *s) { + size_t res = 0; transitions *trans = s->transitions; reductions *reds = s->reductions; @@ -521,21 +522,24 @@ rule_has_state_sr_conflicts (rule *r, state *s) bitset lookaheads = reds->lookahead_tokens[i]; int j; FOR_EACH_SHIFT (trans, j) - if (bitset_test (lookaheads, TRANSITION_SYMBOL (trans, j))) - return true; - break; + res += bitset_test (lookaheads, TRANSITION_SYMBOL (trans, j)); } - 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 count_rule_sr_conflicts (rule *r) { size_t res = 0; for (state_number i = 0; i < nstates; ++i) - if (conflicts[i] && rule_has_state_sr_conflicts (r, states[i])) - res++; + if (conflicts[i]) + res += count_rule_state_sr_conflicts (r, states[i]); return res; } diff --git a/tests/conflicts.at b/tests/conflicts.at index 91cf9e77..c5fd512f 100644 --- a/tests/conflicts.at +++ b/tests/conflicts.at @@ -1280,6 +1280,25 @@ AT_BISON_CHECK([-o input.c input.y]) 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. ## ## ---------------------------------- ##