mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-13 06:13:02 +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
@@ -5254,6 +5254,53 @@ in GLR parsers, using the declaration:
|
||||
%expect-rr @var{n}
|
||||
@end example
|
||||
|
||||
You may wish to be more specific in your
|
||||
specification of expected conflicts. To this end, you can also attach
|
||||
@code{%expect} and @code{%expect-rr} modifiers to individual rules.
|
||||
The interpretation of these modifiers differs from their use as
|
||||
declarations. When attached to rules, they indicate the number of states
|
||||
in which the rule is involved in a conflict. You will need to consult the
|
||||
output resulting from @samp{-v} to determine appropriate numbers to use.
|
||||
For example, for the following grammar fragment, the first rule for
|
||||
@code{empty_dims} appears in two states in which the @samp{[} token is a
|
||||
lookahead. Having determined that, you can document this fact with an
|
||||
@code{%expect} modifier as follows:
|
||||
|
||||
@example
|
||||
dims:
|
||||
empty_dims
|
||||
| '[' expr ']' dims
|
||||
;
|
||||
|
||||
empty_dims:
|
||||
%empty %expect 2
|
||||
| empty_dims '[' ']'
|
||||
;
|
||||
@end example
|
||||
|
||||
Mid-rule actions generate implicit rules that are also subject to conflicts
|
||||
(@pxref{Midrule Conflicts,, Conflicts due to Midrule Actions}). To attach
|
||||
an @code{%expect} or @code{%expect-rr} annotation to an implicit
|
||||
mid-rule action's rule, put it before the action. For example,
|
||||
|
||||
@example
|
||||
%glr-parser
|
||||
%expect-rr 1
|
||||
|
||||
%%
|
||||
|
||||
clause:
|
||||
"condition" %expect-rr 1 @{ value_mode(); @} '(' exprs ')'
|
||||
| "condition" %expect-rr 1 @{ class_mode(); @} '(' types ')'
|
||||
;
|
||||
@end example
|
||||
|
||||
@noindent
|
||||
Here, the appropriate mid-rule action will not be determined until after
|
||||
the @samp{(} token is shifted. Thus,
|
||||
the two actions will clash with each other, and we should expect one
|
||||
reduce/reduce conflict for each.
|
||||
|
||||
In general, using @code{%expect} involves these steps:
|
||||
|
||||
@itemize @bullet
|
||||
@@ -5269,8 +5316,17 @@ go back to the beginning.
|
||||
|
||||
@item
|
||||
Add an @code{%expect} declaration, copying the number @var{n} from the
|
||||
number which Bison printed. With GLR parsers, add an
|
||||
number that Bison printed. With GLR parsers, add an
|
||||
@code{%expect-rr} declaration as well.
|
||||
|
||||
@item
|
||||
Optionally, count up the number of states in which one or more
|
||||
conflicted reductions for particular rules appear and add these numbers
|
||||
to the affected rules as @code{%expect-rr} or @code{%expect} modifiers
|
||||
as appropriate. Rules that are in conflict appear in the output listing
|
||||
surrounded by square brackets or, in the case of reduce/reduce conflicts,
|
||||
as reductions having the same lookahead symbol as a square-bracketed
|
||||
reduction in the same state.
|
||||
@end itemize
|
||||
|
||||
Now Bison will report an error if you introduce an unexpected conflict,
|
||||
@@ -5491,7 +5547,14 @@ Start-Symbol}).
|
||||
@end deffn
|
||||
|
||||
@deffn {Directive} %expect
|
||||
Declare the expected number of shift-reduce conflicts
|
||||
Declare the expected number of shift-reduce conflicts, either overall or
|
||||
for a given rule
|
||||
(@pxref{Expect Decl, ,Suppressing Conflict Warnings}).
|
||||
@end deffn
|
||||
|
||||
@deffn {Directive} %expect-rr
|
||||
Declare the expected number of reduce-reduce conflicts, either overall or
|
||||
for a given rule
|
||||
(@pxref{Expect Decl, ,Suppressing Conflict Warnings}).
|
||||
@end deffn
|
||||
|
||||
|
||||
Reference in New Issue
Block a user