mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-09 12:23:04 +00:00
yysyntax_error: fix for consistent error with lookahead.
* NEWS (2.5): Document. * data/yacc.c (yysyntax_error): In a verbose syntax error message while in a consistent state with a default action (which must be an error action given that yysyntax_error is being invoked), continue to drop the expected token list, but don't drop the unexpected token unless there actually is no lookahead. Moreover, handle that internally instead of returning 1 to tell the caller to do it. With that meaning of 1 gone, renumber return codes more usefully. (yyparse, yypush_parse): Update yysyntax_error usage. Most importantly, set yytoken to YYEMPTY when there's no lookahead. * data/glr.c (yyreportSyntaxError): As in yacc.c, don't drop the unexpected token unless there actually is no lookahead. * data/lalr1.cc (yy::parser::parse): If there's no lookahead, pass yyempty_ not yyla.type to yysyntax_error_. (yy::parser::yysyntax_error_): Again, don't drop the unexpected token unless there actually is no lookahead. * data/lalr1.java (YYParser::parse): If there's no lookahead, set yytoken to yyempty_ before invoking yysyntax_error. (YYParser::yysyntax_error): Again, don't drop the unexpected token unless there actually is no lookahead. * tests/conflicts.at (parse.error=verbose and consistent errors): Extend test group to further reveal how the previous use of the simple "syntax error" message was too general. Test yacc.c, glr.c, lalr1.cc, and lalr1.java. No longer an expected failure. * tests/java.at (AT_JAVA_COMPILE, AT_JAVA_PARSER_CHECK): Move to... * tests/local.at: ... here. (_AT_BISON_OPTION_PUSHDEFS): Push AT_SKEL_JAVA_IF definition. (AT_BISON_OPTION_POPDEFS): Pop it. (AT_FULL_COMPILE): Extend to handle Java.
This commit is contained in:
52
data/glr.c
52
data/glr.c
@@ -2081,11 +2081,7 @@ yyreportSyntaxError (yyGLRStack* yystackp]b4_user_formals[)
|
||||
#if ! YYERROR_VERBOSE
|
||||
yyerror (]b4_lyyerror_args[YY_("syntax error"));
|
||||
#else
|
||||
int yyn;
|
||||
yyn = yypact[yystackp->yytops.yystates[0]->yylrState];
|
||||
if (YYPACT_NINF < yyn && yyn <= YYLAST)
|
||||
{
|
||||
yySymbol yytoken = YYTRANSLATE (yychar);
|
||||
yySymbol yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
|
||||
size_t yysize0 = yytnamerr (NULL, yytokenName (yytoken));
|
||||
size_t yysize = yysize0;
|
||||
size_t yysize1;
|
||||
@@ -2096,23 +2092,47 @@ if (YYPACT_NINF < yyn && yyn <= YYLAST)
|
||||
const char *yyformat = 0;
|
||||
/* Arguments of yyformat. */
|
||||
char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
|
||||
/* Number of reported tokens (one for the "unexpected", one per
|
||||
"expected"). */
|
||||
int yycount = 0;
|
||||
|
||||
/* There are many possibilities here to consider:
|
||||
- If this state is a consistent state with a default action, then
|
||||
the only way this function was invoked is if the default action
|
||||
is an error action. In that case, don't check for expected
|
||||
tokens because there are none.
|
||||
- The only way there can be no lookahead present (in yychar) is if
|
||||
this state is a consistent state with a default action. Thus,
|
||||
detecting the absence of a lookahead is sufficient to determine
|
||||
that there is no unexpected or expected token to report. In that
|
||||
case, just report a simple "syntax error".
|
||||
- Don't assume there isn't a lookahead just because this state is a
|
||||
consistent state with a default action. There might have been a
|
||||
previous inconsistent state, consistent state with a non-default
|
||||
action, or user semantic action that manipulated yychar.
|
||||
- Of course, the expected token list depends on states to have
|
||||
correct lookahead information, and it depends on the parser not
|
||||
to perform extra reductions after fetching a lookahead from the
|
||||
scanner and before detecting a syntax error. Thus, state merging
|
||||
(from LALR or IELR) and default reductions corrupt the expected
|
||||
token list. However, the list is correct for canonical LR with
|
||||
one exception: it will still contain any token that will not be
|
||||
accepted due to an error action in a later state.
|
||||
*/
|
||||
if (yytoken != YYEMPTY)
|
||||
{
|
||||
int yyn = yypact[yystackp->yytops.yystates[0]->yylrState];
|
||||
yyarg[yycount++] = yytokenName (yytoken);
|
||||
if (!yypact_value_is_default (yyn))
|
||||
{
|
||||
/* Start YYX at -YYN if negative to avoid negative indexes in
|
||||
YYCHECK. In other words, skip the first -YYN actions for this
|
||||
state because they are default actions. */
|
||||
int yyxbegin = yyn < 0 ? -yyn : 0;
|
||||
|
||||
/* Stay within bounds of both yycheck and yytname. */
|
||||
int yychecklim = YYLAST - yyn + 1;
|
||||
int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
|
||||
|
||||
/* Number of reported tokens (one for the "unexpected", one per
|
||||
"expected"). */
|
||||
int yycount = 0;
|
||||
int yyx;
|
||||
|
||||
yyarg[yycount++] = yytokenName (yytoken);
|
||||
|
||||
for (yyx = yyxbegin; yyx < yyxend; ++yyx)
|
||||
if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
|
||||
&& !yytable_value_is_error (yytable[yyx + yyn]))
|
||||
@@ -2128,6 +2148,8 @@ if (YYPACT_NINF < yyn && yyn <= YYLAST)
|
||||
yysize_overflow |= yysize1 < yysize;
|
||||
yysize = yysize1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (yycount)
|
||||
{
|
||||
@@ -2135,6 +2157,7 @@ if (YYPACT_NINF < yyn && yyn <= YYLAST)
|
||||
case N: \
|
||||
yyformat = S; \
|
||||
break
|
||||
YYCASE_(0, YY_("syntax error"));
|
||||
YYCASE_(1, YY_("syntax error, unexpected %s"));
|
||||
YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
|
||||
YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
|
||||
@@ -2175,9 +2198,6 @@ if (YYPACT_NINF < yyn && yyn <= YYLAST)
|
||||
yyerror (]b4_lyyerror_args[YY_("syntax error"));
|
||||
yyMemoryExhausted (yystackp);
|
||||
}
|
||||
}
|
||||
else
|
||||
yyerror (]b4_lyyerror_args[YY_("syntax error"));
|
||||
#endif /* YYERROR_VERBOSE */
|
||||
yynerrs += 1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user