mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-18 00:33:03 +00:00
generate the default semantic action
Currently, in C, the default semantic action is implemented by being always run before running the actual user semantic action. As a consequence, when the user action is run, $$ is already set as $1. In C++ with variants, we don't do that, since we cannot manipulate the semantic value without knowing its exact type. When variants are enabled, the only guarantee is that $$ is default contructed and ready to the used. Some users still would like the default action to be run with variants. Frank Heckenbach's parser in C++17 (http://lists.gnu.org/archive/html/bug-bison/2018-04/msg00011.html) provides this feature, but relying on std::variant's dynamic typing, which we forbid in lalr1.cc. The simplest seems to be actually generating the default semantic action (in all languages/skeletons). This makes the pre-action (that sets $$ to $1) useless. But... maybe some users depend on this, in spite of the comments that clearly warn againt this. So let's not turn this off just yet. * src/reader.c (grammar_rule_check_and_complete): Rename as... (grammar_rule_check_and_complete): this. Install the default semantic action when applicable. * examples/variant-11.yy, examples/variant.yy, tests/calc.at: Exercise the default semantic action, even with variants.
This commit is contained in:
21
NEWS
21
NEWS
@@ -68,6 +68,27 @@ GNU Bison NEWS
|
|||||||
|
|
||||||
The new examples/variant-11.yy shows these features in action.
|
The new examples/variant-11.yy shows these features in action.
|
||||||
|
|
||||||
|
*** C++: The implicit default semantic action is always run
|
||||||
|
|
||||||
|
When variants are enabled, the default action was not run, so
|
||||||
|
|
||||||
|
exp: "number"
|
||||||
|
|
||||||
|
was equivalent to
|
||||||
|
|
||||||
|
exp: "number" {}
|
||||||
|
|
||||||
|
It now behaves like in all the other cases, as
|
||||||
|
|
||||||
|
exp: "number" { $$ = $1; }
|
||||||
|
|
||||||
|
possibly using std::move if automove is enabled.
|
||||||
|
|
||||||
|
We do not expect backward compatibility issues. However, beware of
|
||||||
|
forward compatibility issues: if you rely on default actions with
|
||||||
|
variants, be sure to '%require "3.2"' to avoid older versions of Bison to
|
||||||
|
generate incorrect parsers.
|
||||||
|
|
||||||
*** C++: Renaming location.hh
|
*** C++: Renaming location.hh
|
||||||
|
|
||||||
When both %defines and %locations are enabled, Bison generates a
|
When both %defines and %locations are enabled, Bison generates a
|
||||||
|
|||||||
@@ -6348,8 +6348,7 @@ Obsoleted by @code{api.namespace}
|
|||||||
|
|
||||||
@item Purpose: Issue runtime assertions to catch invalid uses.
|
@item Purpose: Issue runtime assertions to catch invalid uses.
|
||||||
In C++, when variants are used (@pxref{C++ Variants}), symbols must be
|
In C++, when variants are used (@pxref{C++ Variants}), symbols must be
|
||||||
constructed and
|
constructed and destroyed properly. This option checks these constraints.
|
||||||
destroyed properly. This option checks these constraints.
|
|
||||||
|
|
||||||
@item Accepted Values: Boolean
|
@item Accepted Values: Boolean
|
||||||
|
|
||||||
@@ -11594,13 +11593,13 @@ assignment:
|
|||||||
%left "+" "-";
|
%left "+" "-";
|
||||||
%left "*" "/";
|
%left "*" "/";
|
||||||
exp:
|
exp:
|
||||||
exp "+" exp @{ $$ = $1 + $3; @}
|
"number"
|
||||||
|
| "identifier" @{ $$ = drv.variables[$1]; @}
|
||||||
|
| exp "+" exp @{ $$ = $1 + $3; @}
|
||||||
| exp "-" exp @{ $$ = $1 - $3; @}
|
| exp "-" exp @{ $$ = $1 - $3; @}
|
||||||
| exp "*" exp @{ $$ = $1 * $3; @}
|
| exp "*" exp @{ $$ = $1 * $3; @}
|
||||||
| exp "/" exp @{ $$ = $1 / $3; @}
|
| exp "/" exp @{ $$ = $1 / $3; @}
|
||||||
| "(" exp ")" @{ std::swap ($$, $2); @}
|
| "(" exp ")" @{ std::swap ($$, $2); @}
|
||||||
| "identifier" @{ $$ = drv.variables[$1]; @}
|
|
||||||
| "number" @{ std::swap ($$, $1); @};
|
|
||||||
%%
|
%%
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ list:
|
|||||||
;
|
;
|
||||||
|
|
||||||
item:
|
item:
|
||||||
TEXT { $$ = $1; }
|
TEXT
|
||||||
| NUMBER { $$ = make_string_uptr (to_string ($1)); }
|
| NUMBER { $$ = make_string_uptr (to_string ($1)); }
|
||||||
;
|
;
|
||||||
%%
|
%%
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ list:
|
|||||||
;
|
;
|
||||||
|
|
||||||
item:
|
item:
|
||||||
TEXT { std::swap ($$, $1); }
|
TEXT
|
||||||
| NUMBER { $$ = to_string ($1); }
|
| NUMBER { $$ = to_string ($1); }
|
||||||
;
|
;
|
||||||
%%
|
%%
|
||||||
|
|||||||
52
src/reader.c
52
src/reader.c
@@ -275,13 +275,14 @@ symbol_should_be_used (symbol_list const *s, bool *midrule_warning)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------.
|
/*-----------------------------------------------------------------.
|
||||||
| Check that the rule R is properly defined. For instance, there |
|
| Check that the rule R is properly defined. For instance, there |
|
||||||
| should be no type clash on the default action. |
|
| should be no type clash on the default action. Possibly install |
|
||||||
`----------------------------------------------------------------*/
|
| the default action. |
|
||||||
|
`-----------------------------------------------------------------*/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
grammar_rule_check (const symbol_list *r)
|
grammar_rule_check_and_complete (symbol_list *r)
|
||||||
{
|
{
|
||||||
/* Type check.
|
/* Type check.
|
||||||
|
|
||||||
@@ -303,6 +304,16 @@ grammar_rule_check (const symbol_list *r)
|
|||||||
complain (&r->location, Wother,
|
complain (&r->location, Wother,
|
||||||
_("type clash on default action: <%s> != <%s>"),
|
_("type clash on default action: <%s> != <%s>"),
|
||||||
lhs_type, rhs_type);
|
lhs_type, rhs_type);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Install the default action. */
|
||||||
|
code_props_rule_action_init (&r->action_props, "{ $$ = $1; }",
|
||||||
|
r->location, r,
|
||||||
|
/* name */ NULL,
|
||||||
|
/* type */ NULL,
|
||||||
|
/* is_predicate */ false);
|
||||||
|
code_props_translate_code (&r->action_props);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* Warn if there is no default for $$ but we need one. */
|
/* Warn if there is no default for $$ but we need one. */
|
||||||
else
|
else
|
||||||
@@ -439,14 +450,14 @@ grammar_current_rule_prec_set (symbol *precsym, location loc)
|
|||||||
{
|
{
|
||||||
/* POSIX says that any identifier is a nonterminal if it does not
|
/* POSIX says that any identifier is a nonterminal if it does not
|
||||||
appear on the LHS of a grammar rule and is not defined by %token
|
appear on the LHS of a grammar rule and is not defined by %token
|
||||||
or by one of the directives that assigns precedence to a token. We
|
or by one of the directives that assigns precedence to a token.
|
||||||
ignore this here because the only kind of identifier that POSIX
|
We ignore this here because the only kind of identifier that
|
||||||
allows to follow a %prec is a token and because assuming it's a
|
POSIX allows to follow a %prec is a token and because assuming
|
||||||
token now can produce more logical error messages. Nevertheless,
|
it's a token now can produce more logical error messages.
|
||||||
grammar_rule_check does obey what we believe is the real intent of
|
Nevertheless, grammar_rule_check_and_complete does obey what we
|
||||||
POSIX here: that an error be reported for any identifier that
|
believe is the real intent of POSIX here: that an error be
|
||||||
appears after %prec but that is not defined separately as a
|
reported for any identifier that appears after %prec but that is
|
||||||
token. */
|
not defined separately as a token. */
|
||||||
symbol_class_set (precsym, token_sym, loc, false);
|
symbol_class_set (precsym, token_sym, loc, false);
|
||||||
if (current_rule->ruleprec)
|
if (current_rule->ruleprec)
|
||||||
duplicate_directive ("%prec",
|
duplicate_directive ("%prec",
|
||||||
@@ -593,7 +604,7 @@ packgram (void)
|
|||||||
symbols may appear unused, but the parsing algorithm ensures that
|
symbols may appear unused, but the parsing algorithm ensures that
|
||||||
%destructor's are invoked appropriately. */
|
%destructor's are invoked appropriately. */
|
||||||
if (p != grammar)
|
if (p != grammar)
|
||||||
grammar_rule_check (p);
|
grammar_rule_check_and_complete (p);
|
||||||
|
|
||||||
rules[ruleno].user_number = ruleno;
|
rules[ruleno].user_number = ruleno;
|
||||||
rules[ruleno].number = ruleno;
|
rules[ruleno].number = ruleno;
|
||||||
@@ -799,12 +810,13 @@ check_and_convert_grammar (void)
|
|||||||
symbols_pack above) so that token types are set correctly before the rule
|
symbols_pack above) so that token types are set correctly before the rule
|
||||||
action type checking.
|
action type checking.
|
||||||
|
|
||||||
Before invoking grammar_rule_check (in packgram below) on any rule, make
|
Before invoking grammar_rule_check_and_complete (in packgram
|
||||||
sure all actions have already been scanned in order to set 'used' flags.
|
below) on any rule, make sure all actions have already been
|
||||||
Otherwise, checking that a midrule's $$ should be set will not always work
|
scanned in order to set 'used' flags. Otherwise, checking that a
|
||||||
properly because the check must forward-reference the midrule's parent
|
midrule's $$ should be set will not always work properly because
|
||||||
rule. For the same reason, all the 'used' flags must be set before
|
the check must forward-reference the midrule's parent rule. For
|
||||||
checking whether to remove '$' from any midrule symbol name (also in
|
the same reason, all the 'used' flags must be set before checking
|
||||||
|
whether to remove '$' from any midrule symbol name (also in
|
||||||
packgram). */
|
packgram). */
|
||||||
for (symbol_list *sym = grammar; sym; sym = sym->next)
|
for (symbol_list *sym = grammar; sym; sym = sym->next)
|
||||||
code_props_translate_code (&sym->action_props);
|
code_props_translate_code (&sym->action_props);
|
||||||
|
|||||||
@@ -303,7 +303,7 @@ line:
|
|||||||
;
|
;
|
||||||
|
|
||||||
exp:
|
exp:
|
||||||
NUM { $$ = $1; }
|
NUM
|
||||||
| exp '=' exp
|
| exp '=' exp
|
||||||
{
|
{
|
||||||
if ($1 != $3)
|
if ($1 != $3)
|
||||||
|
|||||||
Reference in New Issue
Block a user