mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-10 04:43:03 +00:00
Implement the FIXME that ends an user action with a semicolon
if it seems necessary.
* src/scan-code.l (flex rules section): Flag cpp directive from
any `#' to the first unescaped end-of-line. Semicolon is not
needed after `;', `{', '}', or cpp directives and is needed after
any other token (whitespaces and comments have no effect).
* tests/actions.at (Fix user actions without a trailing semicolon):
New test.
* tests/input.at (AT_CHECK_UNUSED_VALUES): Add semicolons to
to make user actions complete statements.
Adjust column numbers in error messages.
* tests/regression.at (Fix user actions without a trailing semicolon):
Remove. Covered by new test.
This commit is contained in:
@@ -81,6 +81,19 @@ splice (\\[ \f\t\v]*\n)*
|
||||
/* Nesting level of the current code in braces. */
|
||||
int braces_level = 0;
|
||||
|
||||
/* Whether a semicolon is probably needed.
|
||||
The heuristic is that a semicolon is not needed after `{', `}', `;',
|
||||
or a C preprocessor directive, and that whitespaces and comments
|
||||
do not affect this flag.
|
||||
Note that `{' does not need a semicolon because of `{}'.
|
||||
A semicolon may be needed before a cpp direcive, but don't bother. */
|
||||
bool need_semicolon = false;
|
||||
|
||||
/* Whether in a C preprocessor directive. Don't use a start condition
|
||||
for this because, at the end of strings and comments, we still need
|
||||
to know whether we're in a directive. */
|
||||
bool in_cpp = false;
|
||||
|
||||
/* This scanner is special: it is invoked only once, henceforth
|
||||
is expected to return only once. This initialization is
|
||||
therefore done once per action to translate. */
|
||||
@@ -135,10 +148,12 @@ splice (\\[ \f\t\v]*\n)*
|
||||
"'" {
|
||||
STRING_GROW;
|
||||
BEGIN SC_CHARACTER;
|
||||
need_semicolon = true;
|
||||
}
|
||||
"\"" {
|
||||
STRING_GROW;
|
||||
BEGIN SC_STRING;
|
||||
need_semicolon = true;
|
||||
}
|
||||
"/"{splice}"*" {
|
||||
STRING_GROW;
|
||||
@@ -154,46 +169,63 @@ splice (\\[ \f\t\v]*\n)*
|
||||
{
|
||||
"$"("<"{tag}">")?(-?[0-9]+|"$") {
|
||||
handle_action_dollar (self->rule, yytext, *loc);
|
||||
need_semicolon = true;
|
||||
}
|
||||
"@"(-?[0-9]+|"$") {
|
||||
handle_action_at (self->rule, yytext, *loc);
|
||||
need_semicolon = true;
|
||||
}
|
||||
|
||||
"$" {
|
||||
warn_at (*loc, _("stray `$'"));
|
||||
obstack_sgrow (&obstack_for_string, "$][");
|
||||
need_semicolon = true;
|
||||
}
|
||||
"@" {
|
||||
warn_at (*loc, _("stray `@'"));
|
||||
obstack_sgrow (&obstack_for_string, "@@");
|
||||
need_semicolon = true;
|
||||
}
|
||||
"[" {
|
||||
obstack_sgrow (&obstack_for_string, "@{");
|
||||
need_semicolon = true;
|
||||
}
|
||||
"]" {
|
||||
obstack_sgrow (&obstack_for_string, "@}");
|
||||
need_semicolon = true;
|
||||
}
|
||||
|
||||
"{" STRING_GROW; ++braces_level;
|
||||
";" STRING_GROW; need_semicolon = false;
|
||||
"{" STRING_GROW; ++braces_level; need_semicolon = false;
|
||||
"}" {
|
||||
bool outer_brace = --braces_level == 0;
|
||||
|
||||
/* As an undocumented Bison extension, append `;' before the last
|
||||
brace in braced code, so that the user code can omit trailing
|
||||
`;'. But do not append `;' if emulating Yacc, since Yacc does
|
||||
not append one. Also, some output languages (like Java) do not
|
||||
accept an extra semicolon, so don't append if the user specified
|
||||
a skeleton or language.
|
||||
|
||||
FIXME: Bison should warn if a semicolon seems to be necessary
|
||||
here, and should omit the semicolon if it seems unnecessary
|
||||
(e.g., after ';', '{', or '}', each followed by comments or
|
||||
white space). Such a warning shouldn't depend on --yacc; it
|
||||
should depend on a new --pedantic option, which would cause
|
||||
Bison to warn if it detects an extension to POSIX. --pedantic
|
||||
should also diagnose other Bison extensions like %yacc.
|
||||
Perhaps there should also be a GCC-style --pedantic-errors
|
||||
option, so that such warnings are diagnosed as errors. */
|
||||
not append one. */
|
||||
if (outer_brace && !yacc_flag && language_prio == default_prio
|
||||
&& skeleton_prio == default_prio)
|
||||
obstack_1grow (&obstack_for_string, ';');
|
||||
&& skeleton_prio == default_prio && need_semicolon && ! in_cpp)
|
||||
{
|
||||
warn_at (*loc, _("a `;' might be needed at the end of action code"));
|
||||
warn_at (*loc, _("future versions of Bison will not add the `;'"));
|
||||
obstack_1grow (&obstack_for_string, ';');
|
||||
}
|
||||
|
||||
STRING_GROW;
|
||||
need_semicolon = false;
|
||||
}
|
||||
|
||||
/* Preprocessing directives should only be recognized at the beginning
|
||||
of lines, allowing whitespace including comments, but in C/C++,
|
||||
`#' can only be the start of preprocessor directives or within
|
||||
`#define' directives anyway, so don't bother with begin of line. */
|
||||
"#" STRING_GROW; in_cpp = true;
|
||||
|
||||
{splice} STRING_GROW;
|
||||
[\n\r] STRING_GROW; if (in_cpp) in_cpp = need_semicolon = false;
|
||||
[ \t\f] STRING_GROW;
|
||||
. STRING_GROW; need_semicolon = true;
|
||||
}
|
||||
|
||||
<SC_SYMBOL_ACTION>
|
||||
|
||||
Reference in New Issue
Block a user