mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-11 05:13:04 +00:00
allow %expect and %expect-rr modifiers on individual rules
This change allows one to document (and check) which rules participate
in shift/reduce and reduce/reduce conflicts. This is particularly
important GLR parsers, where conflicts are a normal occurrence. For
example,
%glr-parser
%expect 1
%%
...
argument_list:
arguments %expect 1
| arguments ','
| %empty
;
arguments:
expression
| argument_list ',' expression
;
...
Looking at the output from -v, one can see that the shift-reduce
conflict here is due to the fact that the parser does not know whether
to reduce arguments to argument_list until it sees the token AFTER the
following ','. By marking the rule with %expect 1 (because there is a
conflict in one state), we document the source of the 1 overall shift-
reduce conflict.
In GLR parsers, we can use %expect-rr in a rule for reduce/reduce
conflicts. In this case, we mark each of the conflicting rules. For
example,
%glr-parser
%expect-rr 1
%%
stmt:
target_list '=' expr ';'
| expr_list ';'
;
target_list:
target
| target ',' target_list
;
target:
ID %expect-rr 1
;
expr_list:
expr
| expr ',' expr_list
;
expr:
ID %expect-rr 1
| ...
;
In a statement such as
x, y = 3, 4;
the parser must reduce x to a target or an expr, but does not know
which until it sees the '='. So we notate the two possible reductions
to indicate that each conflicts in one rule.
See https://lists.gnu.org/archive/html/bison-patches/2013-02/msg00105.html.
* doc/bison.texi (Suppressing Conflict Warnings): Document %expect,
%expect-rr in grammar rules.
* src/conflicts.c (count_state_rr_conflicts): Adjust comment.
(rule_has_state_sr_conflicts): New static function.
(count_rule_sr_conflicts): New static function.
(rule_nast_state_rr_conflicts): New static function.
(count_rule_rr_conflicts): New static function.
(rule_conflicts_print): New static function.
(conflicts_print): Also use rule_conflicts_print to report on individual
rules.
* src/gram.h (struct rule): Add new fields expected_sr_conflicts,
expected_rr_conflicts.
* src/reader.c (grammar_midrule_action): Transfer expected_sr_conflicts,
expected_rr_conflicts to new rule, and turn off in current_rule.
(grammar_current_rule_expect_sr): New function.
(grammar_current_rule_expect_rr): New function.
(packgram): Transfer expected_sr_conflicts, expected_rr_conflicts
to new rule.
* src/reader.h (grammar_current_rule_expect_sr): New function.
(grammar_current_rule_expect_rr): New function.
* src/symlist.c (symbol_list_sym_new): Initialize expected_sr_conflicts,
expected_rr_conflicts.
* src/symlist.h (struct symbol_list): Add new fields expected_sr_conflicts,
expected_rr_conflicts.
* tests/conflicts.at: Add tests "%expect in grammar rule not enough",
"%expect in grammar rule right.", "%expect in grammar rule too much."
This commit is contained in:
committed by
Akim Demaille
parent
487a2a9eca
commit
b34b12c4f9
27
src/reader.c
27
src/reader.c
@@ -430,6 +430,11 @@ grammar_midrule_action (void)
|
||||
current_rule->action_props.is_predicate);
|
||||
code_props_none_init (¤t_rule->action_props);
|
||||
|
||||
midrule->expected_sr_conflicts = current_rule->expected_sr_conflicts;
|
||||
midrule->expected_rr_conflicts = current_rule->expected_rr_conflicts;
|
||||
current_rule->expected_sr_conflicts = -1;
|
||||
current_rule->expected_rr_conflicts = -1;
|
||||
|
||||
if (previous_rule_end)
|
||||
previous_rule_end->next = midrule;
|
||||
else
|
||||
@@ -573,6 +578,26 @@ grammar_current_rule_predicate_append (const char *pred, location loc)
|
||||
/* is_predicate */ true);
|
||||
}
|
||||
|
||||
/* Set the expected number of shift-reduce (reduce-reduce) conflicts for
|
||||
* the current rule. If a midrule is encountered later, the count
|
||||
* is transferred to it and reset in the current rule to -1. */
|
||||
|
||||
void
|
||||
grammar_current_rule_expect_sr (int count, location loc)
|
||||
{
|
||||
current_rule->expected_sr_conflicts = count;
|
||||
}
|
||||
|
||||
void
|
||||
grammar_current_rule_expect_rr (int count, location loc)
|
||||
{
|
||||
if (! glr_parser)
|
||||
complain (&loc, Wother, _("%s affects only GLR parsers"),
|
||||
"%expect-rr");
|
||||
else
|
||||
current_rule->expected_rr_conflicts = count;
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------.
|
||||
| Convert the rules into the representation using RRHS, RLHS and |
|
||||
@@ -626,6 +651,8 @@ packgram (void)
|
||||
rules[ruleno].action = lhs->action_props.code;
|
||||
rules[ruleno].action_location = lhs->action_props.location;
|
||||
rules[ruleno].is_predicate = lhs->action_props.is_predicate;
|
||||
rules[ruleno].expected_sr_conflicts = p->expected_sr_conflicts;
|
||||
rules[ruleno].expected_rr_conflicts = p->expected_rr_conflicts;
|
||||
|
||||
/* Traverse the rhs. */
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user