During error recovery, when discarding the lookeahead, we don't
destroy it, which is caught by parse.assert assertions.
Reported by Antonio Silva Correia.
With an analysis and suggested patch from Michel d'Hooge.
<http://savannah.gnu.org/support/?108481>
* tests/c++.at (Variants): Strengthen the test to try syntax errors
with discarded lookahead.
else if (!yyempty)
{
yy_destroy_ ("Error: discarding", yyla);
else if (!yyempty)
{
yy_destroy_ ("Error: discarding", yyla);
## Variants. ##
## ---------- ##
## Variants. ##
## ---------- ##
+# Check that the variants are properly supported, including in error
+# recovery.
+
# AT_TEST([DIRECTIVES])
# ---------------------
# Check the support of variants in C++, with the additional DIRECTIVES.
# AT_TEST([DIRECTIVES])
# ---------------------
# Check the support of variants in C++, with the additional DIRECTIVES.
%token <::std::string> TEXT;
%token <int> NUMBER;
%token END_OF_FILE 0;
%token <::std::string> TEXT;
%token <int> NUMBER;
%token END_OF_FILE 0;
%type <::std::string> item;
// Using the template type to exercize its parsing.
%type <::std::string> item;
// Using the template type to exercize its parsing.
- /* nothing */ { /* Generates an empty string list */ }
-| list item { std::swap ($$,$][1); $$.push_back ($][2); }
-| list error { std::swap ($$,$][1); }
+ item { $$.push_back ($][1); }
+| list "," item { std::swap ($$, $][1); $$.push_back ($][3); }
+| list error { std::swap ($$, $][1); }
- TEXT { std::swap ($$,$][1); }
+ TEXT { std::swap ($$, $][1); }
| NUMBER { if ($][1 == 3) YYERROR; else $$ = to_string ($][1); }
;
%%
| NUMBER { if ($][1 == 3) YYERROR; else $$ = to_string ($][1); }
;
%%
parser::location_type* yylloc])[)]])[
{]AT_LOCATION_IF([
typedef parser::location_type location;])[
parser::location_type* yylloc])[)]])[
{]AT_LOCATION_IF([
typedef parser::location_type location;])[
- static int stage = -1;
- ++stage;
- if (stage == STAGE_MAX)
- {]AT_TOKEN_CTOR_IF([[
+ // The 5 is a syntax error whose recovery requires that we discard
+ // the lookahead. This tests a regression, see
+ // <http://savannah.gnu.org/support/?108481>.
+ static char const *input = "0,1,2,3,45,6";
+ switch (int stage = *input++)
+ {
+ case 0:]AT_TOKEN_CTOR_IF([[
return parser::make_END_OF_FILE (]AT_LOCATION_IF([location ()])[);]],
[AT_LOCATION_IF([
*yylloc = location ();])[
return parser::token::END_OF_FILE;]])[
return parser::make_END_OF_FILE (]AT_LOCATION_IF([location ()])[);]],
[AT_LOCATION_IF([
*yylloc = location ();])[
return parser::token::END_OF_FILE;]])[
- }
- else if (stage % 2)
- {]AT_TOKEN_CTOR_IF([[
- return parser::make_NUMBER (stage]AT_LOCATION_IF([, location ()])[);]],
-[[
- yylval->BUILD (int, stage);]AT_LOCATION_IF([
- *yylloc = location ();])[
- return parser::token::NUMBER;]])[
- }
- else
- {]AT_TOKEN_CTOR_IF([[
- return parser::make_TEXT (to_string (stage)]AT_LOCATION_IF([, location ()])[);]], [[
- yylval->BUILD (std::string, to_string (stage));]AT_LOCATION_IF([
+
+ case ',':
+ ]AT_TOKEN_CTOR_IF([[
+ return parser::make_COMMA (]AT_LOCATION_IF([location ()])[);]], [[
+]AT_LOCATION_IF([
*yylloc = location ();])[
*yylloc = location ();])[
- return parser::token::TEXT;]])[
- }
+ return parser::token::COMMA;]])[
+
+ default:
+ stage = stage - '0';
+ if (stage % 2)
+ {]AT_TOKEN_CTOR_IF([[
+ return parser::make_NUMBER (stage]AT_LOCATION_IF([, location ()])[);]], [[
+ yylval->BUILD (int, stage);]AT_LOCATION_IF([
+ *yylloc = location ();])[
+ return parser::token::NUMBER;]])[
+ }
+ else
+ {]AT_TOKEN_CTOR_IF([[
+ return parser::make_TEXT (to_string (stage)]AT_LOCATION_IF([, location ()])[);]], [[
+ yylval->BUILD (std::string, to_string (stage));]AT_LOCATION_IF([
+ *yylloc = location ();])[
+ return parser::token::TEXT;]])[
+ }
+ }
+
AT_FULL_COMPILE([list])
AT_PARSER_CHECK([./list], 0,
AT_FULL_COMPILE([list])
AT_PARSER_CHECK([./list], 0,
])
AT_BISON_OPTION_POPDEFS
])
AT_BISON_OPTION_POPDEFS
AT_TEST([[%skeleton "lalr1.cc" ]])
AT_TEST([[%skeleton "lalr1.cc" %define parse.assert]])
AT_TEST([[%skeleton "lalr1.cc" ]])
AT_TEST([[%skeleton "lalr1.cc" %define parse.assert]])
-AT_TEST([[%skeleton "lalr1.cc" %locations %define parse.assert]])
+AT_TEST([[%skeleton "lalr1.cc" %define parse.assert %locations]])
AT_TEST([[%skeleton "lalr1.cc" %define parse.assert %code {\n#define TWO_STAGE_BUILD\n}]])
AT_TEST([[%skeleton "lalr1.cc" %define parse.assert %define api.token.constructor]])
AT_TEST([[%skeleton "lalr1.cc" %define parse.assert %define api.token.constructor %define api.token.prefix {TOK_}]])
AT_TEST([[%skeleton "lalr1.cc" %define parse.assert %code {\n#define TWO_STAGE_BUILD\n}]])
AT_TEST([[%skeleton "lalr1.cc" %define parse.assert %define api.token.constructor]])
AT_TEST([[%skeleton "lalr1.cc" %define parse.assert %define api.token.constructor %define api.token.prefix {TOK_}]])
-AT_TEST([[%skeleton "lalr1.cc" %locations %define parse.assert %define api.token.constructor %define api.token.prefix {TOK_}]])
+AT_TEST([[%skeleton "lalr1.cc" %define parse.assert %define api.token.constructor %define api.token.prefix {TOK_} %locations]])