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:
Paul Hilfinger
2013-02-26 16:28:36 -08:00
committed by Akim Demaille
parent 487a2a9eca
commit b34b12c4f9
9 changed files with 282 additions and 8 deletions

View File

@@ -1244,6 +1244,61 @@ AT_BISON_CHECK([-o input.c input.y], 1, [],
AT_CLEANUP
## ------------------------------------ ##
## %expect in grammar rule not enough. ##
## ------------------------------------ ##
AT_SETUP([%expect in grammar rule not enough])
AT_DATA([input.y],
[[%token NUM OP
%expect 1
%%
exp: exp OP exp %expect 0 | NUM;
]])
AT_BISON_CHECK([-o input.c input.y], 1, [],
[[input.y:4.6-25: error: shift/reduce conflicts for rule 1: 1 found, 0 expected
]])
AT_CLEANUP
## ------------------------------- ##
## %expect in grammar rule right. ##
## ------------------------------- ##
AT_SETUP([%expect in grammar rule right])
AT_DATA([input.y],
[[%token NUM OP
%expect 1
%%
exp: exp OP exp %expect 1 | NUM;
]])
AT_BISON_CHECK([-o input.c input.y])
AT_CLEANUP
## ---------------------------------- ##
## %expect in grammar rule too much. ##
## ---------------------------------- ##
AT_SETUP([%expect in grammar rule too much])
AT_DATA([input.y],
[[%token NUM OP
%expect 1
%%
exp: exp OP exp | NUM %expect 1;
]])
AT_BISON_CHECK([-o input.c input.y], 1, [],
[[input.y:4.19-31: error: shift/reduce conflicts for rule 2: 0 found, 1 expected
]])
AT_CLEANUP
## ------------------------- ##
## %prec with user strings. ##
## ------------------------- ##