From d2060f0634f4adfb5db74cce540a9d27806091fe Mon Sep 17 00:00:00 2001 From: "Joel E. Denny" Date: Sun, 7 Nov 2010 16:01:56 -0500 Subject: [PATCH] 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. --- ChangeLog | 36 +++ NEWS | 43 +++- data/glr.c | 52 ++-- data/lalr1.cc | 60 +++-- data/lalr1.java | 53 +++- data/yacc.c | 84 +++--- src/parse-gram.c | 630 +++++++++++++++++++++++---------------------- src/parse-gram.h | 10 +- tests/conflicts.at | 200 ++++++++++++-- tests/java.at | 19 -- tests/local.at | 47 +++- 11 files changed, 785 insertions(+), 449 deletions(-) diff --git a/ChangeLog b/ChangeLog index 019c2384..41ba7e5e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,39 @@ +2010-11-07 Joel E. Denny + + 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. + 2010-11-07 Joel E. Denny yysyntax_error: more preparation for readability of next patch. diff --git a/NEWS b/NEWS index 177fbbb6..c8188395 100644 --- a/NEWS +++ b/NEWS @@ -223,14 +223,41 @@ Bison News Bison now warns when a character literal is not of length one. In some future release, Bison will report an error instead. -** Verbose error messages fixed for nonassociative tokens. - - When %error-verbose is specified, syntax error messages produced by - the generated parser include the unexpected token as well as a list of - expected tokens. Previously, this list erroneously included tokens - that would actually induce a syntax error because conflicts for them - were resolved with %nonassoc. Such tokens are now properly omitted - from the list. +** Verbose syntax error message fixes: + + When %error-verbose or `#define YYERROR_VERBOSE' is specified, syntax + error messages produced by the generated parser include the unexpected + token as well as a list of expected tokens. The effect of %nonassoc + on these verbose messages has been corrected in two ways, but + additional fixes are still being implemented: + +*** When %nonassoc is used, there can exist parser states that accept no + tokens, and so the parser does not always require a lookahead token + in order to detect a syntax error. Because no unexpected token or + expected tokens can then be reported, the verbose syntax error + message described above is suppressed, and the parser instead + reports the simpler message, "syntax error". Previously, this + suppression was sometimes erroneously triggered by %nonassoc when a + lookahead was actually required. Now verbose messages are + suppressed only when all previous lookaheads have already been + shifted or discarded. + +*** Previously, the list of expected tokens erroneously included tokens + that would actually induce a syntax error because conflicts for them + were resolved with %nonassoc in the current parser state. Such + tokens are now properly omitted from the list. + +*** Expected token lists are still often wrong due to state merging + (from LALR or IELR) and default reductions, which can both add and + subtract valid tokens. Canonical LR almost completely fixes this + problem by eliminating state merging and default reductions. + However, there is one minor problem left even when using canonical + LR and even after the fixes above. That is, if the resolution of a + conflict with %nonassoc appears in a later parser state than the one + at which some syntax error is discovered, the conflicted token is + still erroneously included in the expected token list. We are + currently working on a fix to eliminate this problem and to + eliminate the need for canonical LR. ** Destructor calls fixed for lookaheads altered in semantic actions. diff --git a/data/glr.c b/data/glr.c index 93ed5128..d8b96047 100644 --- a/data/glr.c +++ b/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; } diff --git a/data/lalr1.cc b/data/lalr1.cc index a3b22320..a18721e2 100644 --- a/data/lalr1.cc +++ b/data/lalr1.cc @@ -862,7 +862,8 @@ m4_ifdef([b4_lex_param], [, ]b4_lex_param)));])[ { ++yynerrs_; error (]b4_args(b4_locations_if([yyla.location]), - [[yysyntax_error_ (yystack_[0].state, yyla.type)]])[); + [[yysyntax_error_ (yystack_[0].state, + yyempty ? yyempty_ : yyla.type)]])[); } ]b4_locations_if([[ @@ -979,26 +980,52 @@ b4_error_verbose_if([state_type yystate, int yytoken], [int, int])[) {]b4_error_verbose_if([[ std::string yyres; - int yyn = yypact_[yystate]; - if (yypact_ninf_ < yyn && yyn <= yylast_) + // Number of reported tokens (one for the "unexpected", one per + // "expected"). + size_t yycount = 0; + // Its maximum. + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + // Arguments of yyformat. + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + + /* 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 yytoken) 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 + yyla. (However, yyla is currently not documented for users.) + - 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_) { + yyarg[yycount++] = yytname_[yytoken]; + int yyn = yypact_[yystate]; + if (!yy_pact_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"). - size_t yycount = 0; - // Its maximum. - enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; - // Arguments of yyformat. - char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; - yyarg[yycount++] = yytname_[yytoken]; for (int yyx = yyxbegin; yyx < yyxend; ++yyx) if (yycheck_[yyx + yyn] == yyx && yyx != yyterror_ && !yy_table_value_is_error_ (yytable_[yyx + yyn])) @@ -1011,6 +1038,8 @@ b4_error_verbose_if([state_type yystate, int yytoken], else yyarg[yycount++] = yytname_[yyx]; } + } + } char const* yyformat = 0; switch (yycount) @@ -1019,6 +1048,7 @@ b4_error_verbose_if([state_type yystate, int yytoken], 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")); @@ -1026,6 +1056,7 @@ b4_error_verbose_if([state_type yystate, int yytoken], YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); #undef YYCASE_ } + // Argument number. size_t yyi = 0; for (char const* yyp = yyformat; *yyp; ++yyp) @@ -1036,9 +1067,6 @@ b4_error_verbose_if([state_type yystate, int yytoken], } else yyres += *yyp; - } - else - yyres = YY_("syntax error"); return yyres;]], [[ return YY_("syntax error");]])[ } diff --git a/data/lalr1.java b/data/lalr1.java index 27256e1d..a2772ff7 100644 --- a/data/lalr1.java +++ b/data/lalr1.java @@ -627,6 +627,8 @@ m4_popdef([b4_at_dollar])])dnl if (yyerrstatus_ == 0) { ++yynerrs_; + if (yychar == yyempty_) + yytoken = yyempty_; yyerror (]b4_locations_if([yylloc, ])[yysyntax_error (yystate, yytoken)); } @@ -727,17 +729,52 @@ m4_popdef([b4_at_dollar])])dnl {]b4_error_verbose_if([[ if (yyErrorVerbose) { - int yyn = yypact_[yystate]; - if (yypact_ninf_ < yyn && yyn <= yylast_) + /* There are many possibilities here to consider: + - Assume YYFAIL is not used. It's too flawed to consider. + See + + for details. YYERROR is fine as it does not invoke this + function. + - 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 tok) 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. (However, yychar is currently out + of scope during semantic actions.) + - 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 (tok != yyempty_) { - StringBuffer res; - + // FIXME: This method of building the message is not compatible + // with internationalization. + StringBuffer res = + new StringBuffer ("syntax error, unexpected "); + res.append (yytnamerr_ (yytname_[tok])); + int yyn = yypact_[yystate]; + if (!yy_pact_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_; @@ -746,11 +783,6 @@ m4_popdef([b4_at_dollar])])dnl if (yycheck_[x + yyn] == x && x != yyterror_ && !yy_table_value_is_error_ (yytable_[x + yyn])) ++count; - - // FIXME: This method of building the message is not compatible - // with internationalization. - res = new StringBuffer ("syntax error, unexpected "); - res.append (yytnamerr_ (yytname_[tok])); if (count < 5) { count = 0; @@ -762,6 +794,7 @@ m4_popdef([b4_at_dollar])])dnl res.append (yytnamerr_ (yytname_[x])); } } + } return res.toString (); } } diff --git a/data/yacc.c b/data/yacc.c index d1715367..5cf15eed 100644 --- a/data/yacc.c +++ b/data/yacc.c @@ -906,20 +906,13 @@ yytnamerr (char *yyres, const char *yystr) /* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message about the unexpected token YYTOKEN while in state YYSTATE. - Return 0 if *YYMSG was successfully written. Return 1 if an ordinary - "syntax error" message will suffice instead. Return 2 if *YYMSG is - not large enough to hold the message. In the last case, also set - *YYMSG_ALLOC to either (a) the required number of bytes or (b) zero - if the required number of bytes is too large to store. */ + Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is + not large enough to hold the message. In that case, also set + *YYMSG_ALLOC to the required number of bytes. Return 2 if the + required number of bytes is too large to store. */ static int yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, int yystate, int yytoken) -{ - int yyn = yypact[yystate]; - - if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) - return 1; - else { YYSIZE_T yysize0 = yytnamerr (0, yytname[yytoken]); YYSIZE_T yysize = yysize0; @@ -929,22 +922,51 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, 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: + - Assume YYFAIL is not used. It's too flawed to consider. See + + for details. YYERROR is fine as it does not invoke this + function. + - 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[yystate]; + yyarg[yycount++] = yytname[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++] = yytname[yytoken]; - for (yyx = yyxbegin; yyx < yyxend; ++yyx) if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR && !yytable_value_is_error (yytable[yyx + yyn])) @@ -957,14 +979,13 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, } yyarg[yycount++] = yytname[yyx]; yysize1 = yysize + yytnamerr (0, yytname[yyx]); - if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) - { - /* Overflow. */ - *yymsg_alloc = 0; - return 2; - } + if (! (yysize <= yysize1 + && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; yysize = yysize1; } + } + } switch (yycount) { @@ -972,6 +993,7 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, 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")); @@ -982,11 +1004,7 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, yysize1 = yysize + yystrlen (yyformat); if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) - { - /* Overflow. */ - *yymsg_alloc = 0; - return 2; - } + return 2; yysize = yysize1; if (*yymsg_alloc < yysize) @@ -995,7 +1013,7 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, if (! (yysize <= *yymsg_alloc && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; - return 2; + return 1; } /* Avoid sprintf, as that infringes on the user's name space. @@ -1018,7 +1036,6 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, } return 0; } -} #endif /* YYERROR_VERBOSE */ @@ -1467,7 +1484,7 @@ yyreduce: yyerrlab: /* Make sure we have latest lookahead translation. See comments at user semantic actions for why this is necessary. */ - yytoken = YYTRANSLATE (yychar); + yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar); /* If not already recovering from an error, report this error. */ if (!yyerrstatus) @@ -1483,7 +1500,7 @@ yyerrlab: int yysyntax_error_status = YYSYNTAX_ERROR; if (yysyntax_error_status == 0) yymsgp = yymsg; - else if (yysyntax_error_status == 2 && 0 < yymsg_alloc) + else if (yysyntax_error_status == 1) { if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); @@ -1492,6 +1509,7 @@ yyerrlab: { yymsg = yymsgbuf; yymsg_alloc = sizeof yymsgbuf; + yysyntax_error_status = 2; } else { diff --git a/src/parse-gram.c b/src/parse-gram.c index 5072a8eb..f55a15b6 100644 --- a/src/parse-gram.c +++ b/src/parse-gram.c @@ -1461,20 +1461,13 @@ yytnamerr (char *yyres, const char *yystr) /* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message about the unexpected token YYTOKEN while in state YYSTATE. - Return 0 if *YYMSG was successfully written. Return 1 if an ordinary - "syntax error" message will suffice instead. Return 2 if *YYMSG is - not large enough to hold the message. In the last case, also set - *YYMSG_ALLOC to either (a) the required number of bytes or (b) zero - if the required number of bytes is too large to store. */ + Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is + not large enough to hold the message. In that case, also set + *YYMSG_ALLOC to the required number of bytes. Return 2 if the + required number of bytes is too large to store. */ static int yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, int yystate, int yytoken) -{ - int yyn = yypact[yystate]; - - if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) - return 1; - else { YYSIZE_T yysize0 = yytnamerr (0, yytname[yytoken]); YYSIZE_T yysize = yysize0; @@ -1484,22 +1477,51 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, 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: + - Assume YYFAIL is not used. It's too flawed to consider. See + + for details. YYERROR is fine as it does not invoke this + function. + - 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[yystate]; + yyarg[yycount++] = yytname[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++] = yytname[yytoken]; - for (yyx = yyxbegin; yyx < yyxend; ++yyx) if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR && !yytable_value_is_error (yytable[yyx + yyn])) @@ -1512,14 +1534,13 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, } yyarg[yycount++] = yytname[yyx]; yysize1 = yysize + yytnamerr (0, yytname[yyx]); - if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) - { - /* Overflow. */ - *yymsg_alloc = 0; - return 2; - } + if (! (yysize <= yysize1 + && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; yysize = yysize1; } + } + } switch (yycount) { @@ -1527,6 +1548,7 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, 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")); @@ -1537,11 +1559,7 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, yysize1 = yysize + yystrlen (yyformat); if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) - { - /* Overflow. */ - *yymsg_alloc = 0; - return 2; - } + return 2; yysize = yysize1; if (*yymsg_alloc < yysize) @@ -1550,7 +1568,7 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, if (! (yysize <= *yymsg_alloc && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; - return 2; + return 1; } /* Avoid sprintf, as that infringes on the user's name space. @@ -1573,7 +1591,6 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, } return 0; } -} #endif /* YYERROR_VERBOSE */ @@ -1748,7 +1765,7 @@ YYLTYPE yylloc; #endif /* User initialization code. */ -/* Line 1213 of yacc.c */ +/* Line 1230 of yacc.c */ #line 80 "src/parse-gram.y" { /* Bison's grammar can initial empty locations, hence a default @@ -1756,8 +1773,8 @@ YYLTYPE yylloc; boundary_set (&yylloc.start, current_file, 1, 1); boundary_set (&yylloc.end, current_file, 1, 1); } -/* Line 1213 of yacc.c */ -#line 1761 "src/parse-gram.c" +/* Line 1230 of yacc.c */ +#line 1778 "src/parse-gram.c" yylsp[0] = yylloc; goto yysetstate; @@ -1943,7 +1960,7 @@ yyreduce: switch (yyn) { case 6: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 267 "src/parse-gram.y" { code_props plain_code; @@ -1954,106 +1971,106 @@ yyreduce: plain_code.code, (yylsp[0])); code_scanner_last_string_free (); } -/* Line 1426 of yacc.c */ -#line 1959 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 1976 "src/parse-gram.c" break; case 7: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 277 "src/parse-gram.y" { muscle_percent_define_ensure ((yyvsp[0].uniqstr), (yylsp[0]), true); } -/* Line 1426 of yacc.c */ -#line 1969 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 1986 "src/parse-gram.c" break; case 8: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 281 "src/parse-gram.y" { muscle_percent_define_insert ((yyvsp[-1].uniqstr), (yylsp[-1]), (yyvsp[0].chars), MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE); } -/* Line 1426 of yacc.c */ -#line 1980 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 1997 "src/parse-gram.c" break; case 9: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 285 "src/parse-gram.y" { defines_flag = true; } -/* Line 1426 of yacc.c */ -#line 1988 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2005 "src/parse-gram.c" break; case 10: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 287 "src/parse-gram.y" { defines_flag = true; spec_defines_file = xstrdup ((yyvsp[0].chars)); } -/* Line 1426 of yacc.c */ -#line 1999 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2016 "src/parse-gram.c" break; case 11: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 292 "src/parse-gram.y" { muscle_percent_define_insert ("parse.error", (yylsp[0]), "verbose", MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE); } -/* Line 1426 of yacc.c */ -#line 2010 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2027 "src/parse-gram.c" break; case 12: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 296 "src/parse-gram.y" { expected_sr_conflicts = (yyvsp[0].integer); } -/* Line 1426 of yacc.c */ -#line 2018 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2035 "src/parse-gram.c" break; case 13: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 297 "src/parse-gram.y" { expected_rr_conflicts = (yyvsp[0].integer); } -/* Line 1426 of yacc.c */ -#line 2026 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2043 "src/parse-gram.c" break; case 14: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 298 "src/parse-gram.y" { spec_file_prefix = (yyvsp[0].chars); } -/* Line 1426 of yacc.c */ -#line 2034 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2051 "src/parse-gram.c" break; case 15: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 299 "src/parse-gram.y" { spec_file_prefix = (yyvsp[0].chars); } -/* Line 1426 of yacc.c */ -#line 2042 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2059 "src/parse-gram.c" break; case 16: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 301 "src/parse-gram.y" { nondeterministic_parser = true; glr_parser = true; } -/* Line 1426 of yacc.c */ -#line 2053 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2070 "src/parse-gram.c" break; case 17: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 306 "src/parse-gram.y" { code_props action; @@ -2063,92 +2080,92 @@ yyreduce: muscle_code_grow ("initial_action", action.code, (yylsp[0])); code_scanner_last_string_free (); } -/* Line 1426 of yacc.c */ -#line 2068 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2085 "src/parse-gram.c" break; case 18: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 314 "src/parse-gram.y" { language_argmatch ((yyvsp[0].chars), grammar_prio, (yylsp[-1])); } -/* Line 1426 of yacc.c */ -#line 2076 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2093 "src/parse-gram.c" break; case 19: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 315 "src/parse-gram.y" { spec_name_prefix = (yyvsp[0].chars); } -/* Line 1426 of yacc.c */ -#line 2084 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2101 "src/parse-gram.c" break; case 20: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 316 "src/parse-gram.y" { spec_name_prefix = (yyvsp[0].chars); } -/* Line 1426 of yacc.c */ -#line 2092 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2109 "src/parse-gram.c" break; case 21: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 317 "src/parse-gram.y" { no_lines_flag = true; } -/* Line 1426 of yacc.c */ -#line 2100 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2117 "src/parse-gram.c" break; case 22: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 318 "src/parse-gram.y" { nondeterministic_parser = true; } -/* Line 1426 of yacc.c */ -#line 2108 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2125 "src/parse-gram.c" break; case 23: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 319 "src/parse-gram.y" { spec_outfile = (yyvsp[0].chars); } -/* Line 1426 of yacc.c */ -#line 2116 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2133 "src/parse-gram.c" break; case 24: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 320 "src/parse-gram.y" { spec_outfile = (yyvsp[0].chars); } -/* Line 1426 of yacc.c */ -#line 2124 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2141 "src/parse-gram.c" break; case 25: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 321 "src/parse-gram.y" { current_param = (yyvsp[0].param); } -/* Line 1426 of yacc.c */ -#line 2132 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2149 "src/parse-gram.c" break; case 26: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 321 "src/parse-gram.y" { current_param = param_none; } -/* Line 1426 of yacc.c */ -#line 2140 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2157 "src/parse-gram.c" break; case 27: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 322 "src/parse-gram.y" { version_check (&(yylsp[0]), (yyvsp[0].chars)); } -/* Line 1426 of yacc.c */ -#line 2148 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2165 "src/parse-gram.c" break; case 28: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 324 "src/parse-gram.y" { char const *skeleton_user = (yyvsp[0].chars); @@ -2173,62 +2190,62 @@ yyreduce: } skeleton_arg (skeleton_user, grammar_prio, (yylsp[-1])); } -/* Line 1426 of yacc.c */ -#line 2178 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2195 "src/parse-gram.c" break; case 29: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 347 "src/parse-gram.y" { token_table_flag = true; } -/* Line 1426 of yacc.c */ -#line 2186 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2203 "src/parse-gram.c" break; case 30: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 348 "src/parse-gram.y" { report_flag |= report_states; } -/* Line 1426 of yacc.c */ -#line 2194 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2211 "src/parse-gram.c" break; case 31: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 349 "src/parse-gram.y" { yacc_flag = true; } -/* Line 1426 of yacc.c */ -#line 2202 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2219 "src/parse-gram.c" break; case 33: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 354 "src/parse-gram.y" { add_param (current_param, (yyvsp[0].code), (yylsp[0])); } -/* Line 1426 of yacc.c */ -#line 2210 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2227 "src/parse-gram.c" break; case 34: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 355 "src/parse-gram.y" { add_param (current_param, (yyvsp[0].code), (yylsp[0])); } -/* Line 1426 of yacc.c */ -#line 2218 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2235 "src/parse-gram.c" break; case 37: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 367 "src/parse-gram.y" { grammar_start_symbol_set ((yyvsp[0].symbol), (yylsp[0])); } -/* Line 1426 of yacc.c */ -#line 2228 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2245 "src/parse-gram.c" break; case 38: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 371 "src/parse-gram.y" { symbol_list *list; @@ -2236,12 +2253,12 @@ yyreduce: symbol_list_destructor_set (list, (yyvsp[-1].code), (yylsp[-1])); symbol_list_free ((yyvsp[0].list)); } -/* Line 1426 of yacc.c */ -#line 2241 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2258 "src/parse-gram.c" break; case 39: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 378 "src/parse-gram.y" { symbol_list *list; @@ -2249,32 +2266,32 @@ yyreduce: symbol_list_printer_set (list, (yyvsp[-1].code), (yylsp[-1])); symbol_list_free ((yyvsp[0].list)); } -/* Line 1426 of yacc.c */ -#line 2254 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2271 "src/parse-gram.c" break; case 40: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 385 "src/parse-gram.y" { default_prec = true; } -/* Line 1426 of yacc.c */ -#line 2264 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2281 "src/parse-gram.c" break; case 41: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 389 "src/parse-gram.y" { default_prec = false; } -/* Line 1426 of yacc.c */ -#line 2274 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2291 "src/parse-gram.c" break; case 42: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 393 "src/parse-gram.y" { /* Do not invoke muscle_percent_code_grow here since it invokes @@ -2282,89 +2299,89 @@ yyreduce: muscle_code_grow ("percent_code()", (yyvsp[0].chars), (yylsp[0])); code_scanner_last_string_free (); } -/* Line 1426 of yacc.c */ -#line 2287 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2304 "src/parse-gram.c" break; case 43: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 400 "src/parse-gram.y" { muscle_percent_code_grow ((yyvsp[-1].uniqstr), (yylsp[-1]), (yyvsp[0].chars), (yylsp[0])); code_scanner_last_string_free (); } -/* Line 1426 of yacc.c */ -#line 2298 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2315 "src/parse-gram.c" break; case 44: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 414 "src/parse-gram.y" {} -/* Line 1426 of yacc.c */ -#line 2306 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2323 "src/parse-gram.c" break; case 45: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 415 "src/parse-gram.y" { muscle_code_grow ("union_name", (yyvsp[0].uniqstr), (yylsp[0])); } -/* Line 1426 of yacc.c */ -#line 2314 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2331 "src/parse-gram.c" break; case 46: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 420 "src/parse-gram.y" { union_seen = true; muscle_code_grow ("stype", (yyvsp[0].chars), (yylsp[0])); code_scanner_last_string_free (); } -/* Line 1426 of yacc.c */ -#line 2326 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2343 "src/parse-gram.c" break; case 47: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 431 "src/parse-gram.y" { current_class = nterm_sym; } -/* Line 1426 of yacc.c */ -#line 2334 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2351 "src/parse-gram.c" break; case 48: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 432 "src/parse-gram.y" { current_class = unknown_sym; current_type = NULL; } -/* Line 1426 of yacc.c */ -#line 2345 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2362 "src/parse-gram.c" break; case 49: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 436 "src/parse-gram.y" { current_class = token_sym; } -/* Line 1426 of yacc.c */ -#line 2353 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2370 "src/parse-gram.c" break; case 50: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 437 "src/parse-gram.y" { current_class = unknown_sym; current_type = NULL; } -/* Line 1426 of yacc.c */ -#line 2364 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2381 "src/parse-gram.c" break; case 51: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 442 "src/parse-gram.y" { symbol_list *list; @@ -2373,12 +2390,12 @@ yyreduce: symbol_type_set (list->content.sym, (yyvsp[-1].uniqstr), (yylsp[-1])); symbol_list_free ((yyvsp[0].list)); } -/* Line 1426 of yacc.c */ -#line 2378 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2395 "src/parse-gram.c" break; case 52: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 453 "src/parse-gram.y" { symbol_list *list; @@ -2391,202 +2408,202 @@ yyreduce: symbol_list_free ((yyvsp[0].list)); current_type = NULL; } -/* Line 1426 of yacc.c */ -#line 2396 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2413 "src/parse-gram.c" break; case 53: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 467 "src/parse-gram.y" { (yyval.assoc) = left_assoc; } -/* Line 1426 of yacc.c */ -#line 2404 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2421 "src/parse-gram.c" break; case 54: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 468 "src/parse-gram.y" { (yyval.assoc) = right_assoc; } -/* Line 1426 of yacc.c */ -#line 2412 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2429 "src/parse-gram.c" break; case 55: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 469 "src/parse-gram.y" { (yyval.assoc) = non_assoc; } -/* Line 1426 of yacc.c */ -#line 2420 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2437 "src/parse-gram.c" break; case 56: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 470 "src/parse-gram.y" { (yyval.assoc) = precedence_assoc; } -/* Line 1426 of yacc.c */ -#line 2428 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2445 "src/parse-gram.c" break; case 57: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 474 "src/parse-gram.y" { current_type = NULL; } -/* Line 1426 of yacc.c */ -#line 2436 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2453 "src/parse-gram.c" break; case 58: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 475 "src/parse-gram.y" { current_type = (yyvsp[0].uniqstr); tag_seen = true; } -/* Line 1426 of yacc.c */ -#line 2444 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2461 "src/parse-gram.c" break; case 59: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 481 "src/parse-gram.y" { (yyval.list) = symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0])); } -/* Line 1426 of yacc.c */ -#line 2452 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2469 "src/parse-gram.c" break; case 60: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 483 "src/parse-gram.y" { (yyval.list) = symbol_list_prepend ((yyvsp[-1].list), symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0]))); } -/* Line 1426 of yacc.c */ -#line 2460 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2477 "src/parse-gram.c" break; case 61: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 487 "src/parse-gram.y" { (yyval.symbol) = (yyvsp[0].symbol); } -/* Line 1426 of yacc.c */ -#line 2468 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2485 "src/parse-gram.c" break; case 62: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 488 "src/parse-gram.y" { (yyval.symbol) = (yyvsp[-1].symbol); symbol_user_token_number_set ((yyvsp[-1].symbol), (yyvsp[0].integer), (yylsp[0])); } -/* Line 1426 of yacc.c */ -#line 2476 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2493 "src/parse-gram.c" break; case 63: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 494 "src/parse-gram.y" { (yyval.list) = symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0])); } -/* Line 1426 of yacc.c */ -#line 2484 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2501 "src/parse-gram.c" break; case 64: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 496 "src/parse-gram.y" { (yyval.list) = symbol_list_prepend ((yyvsp[-1].list), symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0]))); } -/* Line 1426 of yacc.c */ -#line 2492 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2509 "src/parse-gram.c" break; case 65: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 500 "src/parse-gram.y" { (yyval.list) = (yyvsp[0].list); } -/* Line 1426 of yacc.c */ -#line 2500 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2517 "src/parse-gram.c" break; case 66: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 501 "src/parse-gram.y" { (yyval.list) = symbol_list_prepend ((yyvsp[-1].list), (yyvsp[0].list)); } -/* Line 1426 of yacc.c */ -#line 2508 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2525 "src/parse-gram.c" break; case 67: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 505 "src/parse-gram.y" { (yyval.list) = symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0])); } -/* Line 1426 of yacc.c */ -#line 2516 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2533 "src/parse-gram.c" break; case 68: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 506 "src/parse-gram.y" { (yyval.list) = symbol_list_type_new ((yyvsp[0].uniqstr), (yylsp[0])); } -/* Line 1426 of yacc.c */ -#line 2524 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2541 "src/parse-gram.c" break; case 69: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 507 "src/parse-gram.y" { (yyval.list) = symbol_list_default_tagged_new ((yylsp[0])); } -/* Line 1426 of yacc.c */ -#line 2532 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2549 "src/parse-gram.c" break; case 70: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 508 "src/parse-gram.y" { (yyval.list) = symbol_list_default_tagless_new ((yylsp[0])); } -/* Line 1426 of yacc.c */ -#line 2540 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2557 "src/parse-gram.c" break; case 71: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 514 "src/parse-gram.y" { current_type = (yyvsp[0].uniqstr); tag_seen = true; } -/* Line 1426 of yacc.c */ -#line 2551 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2568 "src/parse-gram.c" break; case 72: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 519 "src/parse-gram.y" { symbol_class_set ((yyvsp[0].symbol), current_class, (yylsp[0]), true); symbol_type_set ((yyvsp[0].symbol), current_type, (yylsp[0])); } -/* Line 1426 of yacc.c */ -#line 2562 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2579 "src/parse-gram.c" break; case 73: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 524 "src/parse-gram.y" { symbol_class_set ((yyvsp[-1].symbol), current_class, (yylsp[-1]), true); symbol_type_set ((yyvsp[-1].symbol), current_type, (yylsp[-1])); symbol_user_token_number_set ((yyvsp[-1].symbol), (yyvsp[0].integer), (yylsp[0])); } -/* Line 1426 of yacc.c */ -#line 2574 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2591 "src/parse-gram.c" break; case 74: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 530 "src/parse-gram.y" { symbol_class_set ((yyvsp[-1].symbol), current_class, (yylsp[-1]), true); symbol_type_set ((yyvsp[-1].symbol), current_type, (yylsp[-1])); symbol_make_alias ((yyvsp[-1].symbol), (yyvsp[0].symbol), (yyloc)); } -/* Line 1426 of yacc.c */ -#line 2586 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2603 "src/parse-gram.c" break; case 75: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 536 "src/parse-gram.y" { symbol_class_set ((yyvsp[-2].symbol), current_class, (yylsp[-2]), true); @@ -2594,144 +2611,144 @@ yyreduce: symbol_user_token_number_set ((yyvsp[-2].symbol), (yyvsp[-1].integer), (yylsp[-1])); symbol_make_alias ((yyvsp[-2].symbol), (yyvsp[0].symbol), (yyloc)); } -/* Line 1426 of yacc.c */ -#line 2599 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2616 "src/parse-gram.c" break; case 82: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 566 "src/parse-gram.y" { yyerrok; } -/* Line 1426 of yacc.c */ -#line 2609 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2626 "src/parse-gram.c" break; case 83: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 572 "src/parse-gram.y" { current_lhs = (yyvsp[-1].symbol); current_lhs_location = (yylsp[-1]); current_lhs_named_ref = (yyvsp[0].named_ref); } -/* Line 1426 of yacc.c */ -#line 2618 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2635 "src/parse-gram.c" break; case 85: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 577 "src/parse-gram.y" { grammar_current_rule_end ((yylsp[0])); } -/* Line 1426 of yacc.c */ -#line 2626 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2643 "src/parse-gram.c" break; case 86: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 578 "src/parse-gram.y" { grammar_current_rule_end ((yylsp[0])); } -/* Line 1426 of yacc.c */ -#line 2634 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2651 "src/parse-gram.c" break; case 88: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 584 "src/parse-gram.y" { grammar_current_rule_begin (current_lhs, current_lhs_location, current_lhs_named_ref); } -/* Line 1426 of yacc.c */ -#line 2643 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2660 "src/parse-gram.c" break; case 89: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 587 "src/parse-gram.y" { grammar_current_rule_symbol_append ((yyvsp[-1].symbol), (yylsp[-1]), (yyvsp[0].named_ref)); } -/* Line 1426 of yacc.c */ -#line 2651 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2668 "src/parse-gram.c" break; case 90: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 589 "src/parse-gram.y" { grammar_current_rule_action_append ((yyvsp[-1].code), (yylsp[-1]), (yyvsp[0].named_ref), false); } -/* Line 1426 of yacc.c */ -#line 2659 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2676 "src/parse-gram.c" break; case 91: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 591 "src/parse-gram.y" { grammar_current_rule_action_append ((yyvsp[0].code), (yylsp[0]), NULL, true); } -/* Line 1426 of yacc.c */ -#line 2667 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2684 "src/parse-gram.c" break; case 92: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 593 "src/parse-gram.y" { grammar_current_rule_prec_set ((yyvsp[0].symbol), (yylsp[0])); } -/* Line 1426 of yacc.c */ -#line 2675 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2692 "src/parse-gram.c" break; case 93: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 595 "src/parse-gram.y" { grammar_current_rule_dprec_set ((yyvsp[0].integer), (yylsp[0])); } -/* Line 1426 of yacc.c */ -#line 2683 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2700 "src/parse-gram.c" break; case 94: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 597 "src/parse-gram.y" { grammar_current_rule_merge_set ((yyvsp[0].uniqstr), (yylsp[0])); } -/* Line 1426 of yacc.c */ -#line 2691 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2708 "src/parse-gram.c" break; case 95: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 601 "src/parse-gram.y" { (yyval.named_ref) = 0; } -/* Line 1426 of yacc.c */ -#line 2699 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2716 "src/parse-gram.c" break; case 96: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 603 "src/parse-gram.y" { (yyval.named_ref) = named_ref_new((yyvsp[0].uniqstr), (yylsp[0])); } -/* Line 1426 of yacc.c */ -#line 2707 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2724 "src/parse-gram.c" break; case 98: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 614 "src/parse-gram.y" { (yyval.uniqstr) = uniqstr_new ((yyvsp[0].chars)); } -/* Line 1426 of yacc.c */ -#line 2715 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2732 "src/parse-gram.c" break; case 99: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 619 "src/parse-gram.y" { (yyval.chars) = ""; } -/* Line 1426 of yacc.c */ -#line 2723 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2740 "src/parse-gram.c" break; case 100: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 620 "src/parse-gram.y" { (yyval.chars) = (yyvsp[0].uniqstr); } -/* Line 1426 of yacc.c */ -#line 2731 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2748 "src/parse-gram.c" break; case 102: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 631 "src/parse-gram.y" { code_props plain_code; @@ -2741,51 +2758,51 @@ yyreduce: gram_scanner_last_string_free (); (yyval.chars) = plain_code.code; } -/* Line 1426 of yacc.c */ -#line 2746 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2763 "src/parse-gram.c" break; case 103: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 651 "src/parse-gram.y" { (yyval.symbol) = symbol_from_uniqstr ((yyvsp[0].uniqstr), (yylsp[0])); } -/* Line 1426 of yacc.c */ -#line 2754 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2771 "src/parse-gram.c" break; case 104: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 653 "src/parse-gram.y" { (yyval.symbol) = symbol_get (char_name ((yyvsp[0].character)), (yylsp[0])); symbol_class_set ((yyval.symbol), token_sym, (yylsp[0]), false); symbol_user_token_number_set ((yyval.symbol), (yyvsp[0].character), (yylsp[0])); } -/* Line 1426 of yacc.c */ -#line 2766 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2783 "src/parse-gram.c" break; case 105: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 661 "src/parse-gram.y" { (yyval.symbol) = symbol_from_uniqstr ((yyvsp[0].uniqstr), (yylsp[0])); } -/* Line 1426 of yacc.c */ -#line 2774 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2791 "src/parse-gram.c" break; case 108: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 673 "src/parse-gram.y" { (yyval.symbol) = symbol_get (quotearg_style (c_quoting_style, (yyvsp[0].chars)), (yylsp[0])); symbol_class_set ((yyval.symbol), token_sym, (yylsp[0]), false); } -/* Line 1426 of yacc.c */ -#line 2785 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2802 "src/parse-gram.c" break; case 110: -/* Line 1426 of yacc.c */ +/* Line 1443 of yacc.c */ #line 682 "src/parse-gram.y" { code_props plain_code; @@ -2795,13 +2812,13 @@ yyreduce: muscle_code_grow ("epilogue", plain_code.code, (yylsp[0])); code_scanner_last_string_free (); } -/* Line 1426 of yacc.c */ -#line 2800 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2817 "src/parse-gram.c" break; -/* Line 1426 of yacc.c */ -#line 2805 "src/parse-gram.c" +/* Line 1443 of yacc.c */ +#line 2822 "src/parse-gram.c" default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -2845,7 +2862,7 @@ yyreduce: yyerrlab: /* Make sure we have latest lookahead translation. See comments at user semantic actions for why this is necessary. */ - yytoken = YYTRANSLATE (yychar); + yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar); /* If not already recovering from an error, report this error. */ if (!yyerrstatus) @@ -2861,7 +2878,7 @@ yyerrlab: int yysyntax_error_status = YYSYNTAX_ERROR; if (yysyntax_error_status == 0) yymsgp = yymsg; - else if (yysyntax_error_status == 2 && 0 < yymsg_alloc) + else if (yysyntax_error_status == 1) { if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); @@ -2870,6 +2887,7 @@ yyerrlab: { yymsg = yymsgbuf; yymsg_alloc = sizeof yymsgbuf; + yysyntax_error_status = 2; } else { @@ -3034,7 +3052,7 @@ yyreturn: return YYID (yyresult); } -/* Line 1662 of yacc.c */ +/* Line 1680 of yacc.c */ #line 692 "src/parse-gram.y" diff --git a/src/parse-gram.h b/src/parse-gram.h index 01a3e296..fd1c8571 100644 --- a/src/parse-gram.h +++ b/src/parse-gram.h @@ -31,7 +31,7 @@ This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /* "%code requires" blocks. */ -/* Line 1663 of yacc.c */ +/* Line 1681 of yacc.c */ #line 202 "src/parse-gram.y" # ifndef PARAM_TYPE @@ -46,7 +46,7 @@ # endif -/* Line 1663 of yacc.c */ +/* Line 1681 of yacc.c */ #line 51 "src/parse-gram.h" /* Tokens. */ @@ -175,7 +175,7 @@ #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef union YYSTYPE { -/* Line 1663 of yacc.c */ +/* Line 1681 of yacc.c */ #line 88 "src/parse-gram.y" assoc assoc; @@ -188,13 +188,13 @@ typedef union YYSTYPE uniqstr uniqstr; unsigned char character; -/* Line 1663 of yacc.c */ +/* Line 1681 of yacc.c */ #line 226 "src/parse-gram.y" param_type param; -/* Line 1663 of yacc.c */ +/* Line 1681 of yacc.c */ #line 199 "src/parse-gram.h" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 diff --git a/tests/conflicts.at b/tests/conflicts.at index 72f56963..655a666c 100644 --- a/tests/conflicts.at +++ b/tests/conflicts.at @@ -147,15 +147,30 @@ AT_SETUP([[parse.error=verbose and consistent errors]]) m4_pushdef([AT_CONSISTENT_ERRORS_CHECK], [ -AT_DATA_GRAMMAR([input.y], -[[%code { +AT_BISON_OPTION_PUSHDEFS([$1]) + +m4_pushdef([AT_YYLEX_PROTOTYPE], +[AT_SKEL_CC_IF([[int yylex (yy::parser::semantic_type *lvalp)]], + [[int yylex (YYSTYPE *lvalp)]])]) + +AT_SKEL_JAVA_IF([AT_DATA], [AT_DATA_GRAMMAR])([input.y], +[AT_SKEL_JAVA_IF([[ + +%code imports { + import java.io.IOException; +}]], [[ + +%code {]AT_SKEL_CC_IF([[ + #include ]], [[ #include #include - int yylex (void); - void yyerror (char const *); + void yyerror (char const *msg);]])[ + ]AT_YYLEX_PROTOTYPE[; #define USE(Var) } +]AT_SKEL_CC_IF([[%defines]], [[%define api.pure]])])[ + ]$1[ %define parse.error verbose @@ -164,63 +179,193 @@ AT_DATA_GRAMMAR([input.y], ]$2[ -%% +]AT_SKEL_JAVA_IF([[%code lexer {]], [[%%]])[ -int -yylex (void) +/*--------. +| yylex. | +`--------*/]AT_SKEL_JAVA_IF([[ + +public String input = "]$3["; +public int index = 0; +public int yylex () +{ + if (index < input.length ()) + return input.charAt (index++); + else + return 0; +} +public Object getLVal () +{ + return new Integer(1); +}]], [[ + +]AT_YYLEX_PROTOTYPE[ { static char const *input = "]$3["; - yylval = 1; + *lvalp = 1; return *input++; +}]])[ + +/*----------. +| yyerror. | +`----------*/]AT_SKEL_JAVA_IF([[ + +public void yyerror (String msg) +{ + System.err.println (msg); } +}; + +%%]], [AT_SKEL_CC_IF([[ + +void +yy::parser::error (std::string const &msg) +{ + std::cerr << msg << std::endl; +}]], [[ + void yyerror (char const *msg) { fprintf (stderr, "%s\n", msg); -} +}]])])[ + +/*-------. +| main. | +`-------*/]AT_SKEL_JAVA_IF([[ + +class input +{ + public static void main (String args[]) throws IOException + { + YYParser p = new YYParser (); + p.parse (); + } +}]], [AT_SKEL_CC_IF([[ + +int +main (void) +{ + yy::parser parser; + return parser.parse (); +}]], [[ int main (void) { return yyparse (); -} +}]])])[ ]]) -AT_BISON_CHECK([[-o input.c input.y]]) -AT_COMPILE([[input]]) + +AT_FULL_COMPILE([[input]]) m4_pushdef([AT_EXPECTING], [m4_if($5, [ab], [[, expecting 'a' or 'b']], $5, [a], [[, expecting 'a']], $5, [b], [[, expecting 'b']])]) -AT_PARSER_CHECK([[./input]], [[1]], [[]], +AT_SKEL_JAVA_IF([AT_JAVA_PARSER_CHECK([[input]], [[0]]], + [AT_PARSER_CHECK([[./input]], [[1]]]), +[[]], [[syntax error, unexpected ]$4[]AT_EXPECTING[ ]]) m4_popdef([AT_EXPECTING]) +m4_popdef([AT_YYLEX_PROTOTYPE]) +AT_BISON_OPTION_POPDEFS ]) +m4_pushdef([AT_PREVIOUS_STATE_GRAMMAR], +[[%nonassoc 'a'; + +start: consistent-error-on-a-a 'a' ; + +consistent-error-on-a-a: + 'a' default-reduction + | 'a' default-reduction 'a' + | 'a' shift + ; + +default-reduction: /*empty*/ ; +shift: 'b' ; + +// Provide another context in which all rules are useful so that this +// test case looks a little more realistic. +start: 'b' consistent-error-on-a-a 'c' ; +]]) + +m4_pushdef([AT_PREVIOUS_STATE_INPUT], [[a]]) + +# Unfortunately, no expected tokens are reported even though 'b' can be +# accepted. Nevertheless, the main point of this test is to make sure +# that at least the unexpected token is reported. In a previous version +# of Bison, it wasn't reported because the error is detected in a +# consistent state with an error action, and that case always triggered +# the simple "syntax error" message. +# +# The point isn't to test IELR here, but state merging happens to +# complicate this example. +AT_CONSISTENT_ERRORS_CHECK([[%define lr.type ielr]], + [AT_PREVIOUS_STATE_GRAMMAR], + [AT_PREVIOUS_STATE_INPUT], + [[$end]], [[none]]) +AT_CONSISTENT_ERRORS_CHECK([[%define lr.type ielr + %glr-parser]], + [AT_PREVIOUS_STATE_GRAMMAR], + [AT_PREVIOUS_STATE_INPUT], + [[$end]], [[none]]) +AT_CONSISTENT_ERRORS_CHECK([[%define lr.type ielr + %language "c++"]], + [AT_PREVIOUS_STATE_GRAMMAR], + [AT_PREVIOUS_STATE_INPUT], + [[$end]], [[none]]) +AT_CONSISTENT_ERRORS_CHECK([[%define lr.type ielr + %language "java"]], + [AT_PREVIOUS_STATE_GRAMMAR], + [AT_PREVIOUS_STATE_INPUT], + [[end of input]], [[none]]) + +# Even canonical LR doesn't foresee the error for 'a'! +AT_CONSISTENT_ERRORS_CHECK([[%define lr.type ielr + %define lr.default-reductions consistent]], + [AT_PREVIOUS_STATE_GRAMMAR], + [AT_PREVIOUS_STATE_INPUT], + [[$end]], [[ab]]) +AT_CONSISTENT_ERRORS_CHECK([[%define lr.type ielr + %define lr.default-reductions accepting]], + [AT_PREVIOUS_STATE_GRAMMAR], + [AT_PREVIOUS_STATE_INPUT], + [[$end]], [[ab]]) +AT_CONSISTENT_ERRORS_CHECK([[%define lr.type canonical-lr]], + [AT_PREVIOUS_STATE_GRAMMAR], + [AT_PREVIOUS_STATE_INPUT], + [[$end]], [[ab]]) + +m4_popdef([AT_PREVIOUS_STATE_GRAMMAR]) +m4_popdef([AT_PREVIOUS_STATE_INPUT]) + m4_pushdef([AT_USER_ACTION_GRAMMAR], [[%nonassoc 'a'; -// If yylval=0 here, then we know that the 'a' destructor is being -// invoked incorrectly for the 'b' set in the semantic action below. -// All 'a' tokens are returned by yylex, which sets yylval=1. +// If $$ = 0 here, then we know that the 'a' destructor is being invoked +// incorrectly for the 'b' set in the semantic action below. All 'a' +// tokens are returned by yylex, which sets $$ = 1. %destructor { if (!$$) fprintf (stderr, "Wrong destructor.\n"); } 'a'; -// The lookahead assigned by the semantic action isn't needed before -// either error action is encountered. In a previous version of Bison, -// this was a problem as it meant yychar was not translated into yytoken -// before either error action. The second error action thus invoked a +// Rather than depend on an inconsistent state to induce reading a +// lookahead as in the previous grammar, just assign the lookahead in a +// semantic action. That lookahead isn't needed before either error +// action is encountered. In a previous version of Bison, this was a +// problem as it meant yychar was not translated into yytoken before +// either error action. The second error action thus invoked a // destructor that it selected according to the incorrect yytoken. The // first error action would have reported an incorrect unexpected token -// except that, due to another bug, the unexpected token is not reported -// at all because the error action is the default action in a consistent -// state. That bug still needs to be fixed. +// except that, due to the bug described in the previous grammar, the +// unexpected token was not reported at all. start: error-reduce consistent-error 'a' { USE ($][3); } ; error-reduce: @@ -247,13 +392,16 @@ start: 'b' consistent-error 'b' ; ]]) m4_pushdef([AT_USER_ACTION_INPUT], [[aa]]) -# See comments in grammar for why this test doesn't succeed. -AT_XFAIL_IF([[:]]) - AT_CONSISTENT_ERRORS_CHECK([[]], [AT_USER_ACTION_GRAMMAR], [AT_USER_ACTION_INPUT], [['b']], [[none]]) +AT_CONSISTENT_ERRORS_CHECK([[%glr-parser]], + [AT_USER_ACTION_GRAMMAR], + [AT_USER_ACTION_INPUT], + [['b']], [[none]]) +# No C++ or Java test because yychar cannot be manipulated by users. + AT_CONSISTENT_ERRORS_CHECK([[%define lr.default-reductions consistent]], [AT_USER_ACTION_GRAMMAR], [AT_USER_ACTION_INPUT], diff --git a/tests/java.at b/tests/java.at index 9ea703fe..dfd42523 100644 --- a/tests/java.at +++ b/tests/java.at @@ -219,25 +219,6 @@ m4_define([AT_DATA_JAVA_CALC_Y], ]) - -# AT_JAVA_COMPILE(SOURCE) -# ----------------------- -# Compile SOURCES into Java class files. Skip the test if java or javac is -# not installed. -m4_define([AT_JAVA_COMPILE], -[AT_KEYWORDS(java) -AT_CHECK([test -n "$CONF_JAVA" || exit 77 -test -n "$CONF_JAVAC" || exit 77]) -AT_CHECK([$SHELL ../../../javacomp.sh $1], - 0, [ignore], [ignore])]) - - -# AT_JAVA_PARSER_CHECK(COMMAND, EXIT-STATUS, EXPOUT, EXPERR, [PRE]) -# ----------------------------------------------------------------- -m4_define([AT_JAVA_PARSER_CHECK], -[AT_CHECK([$5 $SHELL ../../../javaexec.sh $1], [$2], [$3], [$4])]) - - # _AT_CHECK_JAVA_CALC_ERROR(BISON-OPTIONS, INPUT, # [VERBOSE-AND-LOCATED-ERROR-MESSAGE]) # --------------------------------------------------------- diff --git a/tests/local.at b/tests/local.at index d3b245c2..bdcbfc49 100644 --- a/tests/local.at +++ b/tests/local.at @@ -80,6 +80,8 @@ m4_pushdef([AT_DEFINES_IF], [m4_bmatch([$3], [%defines], [$1], [$2])]) m4_pushdef([AT_SKEL_CC_IF], [m4_bmatch([$3], [%language "[Cc]\+\+"\|%skeleton "[a-z0-9]+\.cc"], [$1], [$2])]) +m4_pushdef([AT_SKEL_JAVA_IF], +[m4_bmatch([$3], [%language "[Jj][Aa][Vv][Aa]"\|%skeleton "[a-z0-9]+\.java"], [$1], [$2])]) m4_pushdef([AT_GLR_IF], [m4_bmatch([$3], [%glr-parser\|%skeleton "glr\.], [$1], [$2])]) m4_pushdef([AT_LALR1_CC_IF], @@ -189,6 +191,7 @@ m4_popdef([AT_LEXPARAM_IF]) m4_popdef([AT_YACC_IF]) m4_popdef([AT_GLR_IF]) m4_popdef([AT_SKEL_CC_IF]) +m4_popdef([AT_SKEL_JAVA_IF]) m4_popdef([AT_GLR_CC_IF]) m4_popdef([AT_LALR1_CC_IF]) m4_popdef([AT_DEFINES_IF]) @@ -404,19 +407,38 @@ AT_CHECK([$BISON_CXX_WORKS], 0, ignore, ignore) AT_CHECK([$CXX $CXXFLAGS $CPPFLAGS m4_bmatch([$1], [[.]], [], [$LDFLAGS ])-o $1 m4_default([$2], [$1.cc])[]m4_bmatch([$1], [[.]], [], [ $LIBS])], 0, [ignore], [ignore])]) +# AT_JAVA_COMPILE(SOURCES) +# ------------------------ +# Compile SOURCES into Java class files. Skip the test if java or javac +# is not installed. +m4_define([AT_JAVA_COMPILE], +[AT_KEYWORDS(java) +AT_CHECK([[test -n "$CONF_JAVA" || exit 77 + test -n "$CONF_JAVAC" || exit 77]]) +AT_CHECK([[$SHELL ../../../javacomp.sh ]$1], + [[0]], [ignore], [ignore])]) # AT_FULL_COMPILE(OUTPUT, [OTHER]) # -------------------------------- -# Compile OUTPUT.y to OUTPUT.c or OUTPUT.cc, and compile it to OUTPUT. -# If OTHER is specified, compile OUTPUT-OTHER.c or OUTPUT-OTHER.cc to OUTPUT -# along with it. -# Relies on AT_SKEL_CC_IF. -m4_define([AT_FULL_COMPILE], -[AT_SKEL_CC_IF( - [AT_BISON_CHECK([-o $1.cc $1.y]) - AT_COMPILE_CXX([$1]m4_ifval($2, [, [$1.cc $1-$2.cc]]))], - [AT_BISON_CHECK([-o $1.c $1.y]) - AT_COMPILE([$1]m4_ifval($2, [, [$1.c $1-$2.c]]))]) +# Compile OUTPUT.y to OUTPUT.c, OUTPUT.cc, or OUTPUT.java, and then +# compile it to OUTPUT or OUTPUT.class. If OTHER is specified, compile +# OUTPUT-OTHER.c, OUTPUT-OTHER.cc, or OUTPUT-OTHER.java to OUTPUT or +# OUTPUT.java along with it. Relies on AT_SKEL_CC_IF and +# AT_SKEL_JAVA_IF. +m4_define([AT_FULL_COMPILE], [ + AT_SKEL_JAVA_IF([ + AT_BISON_CHECK([[-o ]$1[.java ]$1[.y]]) + AT_JAVA_COMPILE([$1[.java]]m4_ifval($2, + [[$1[.java ]$1[-]$2[.java]]])) + ], [ + AT_SKEL_CC_IF([ + AT_BISON_CHECK([[-o ]$1[.cc ]$1[.y]]) + AT_COMPILE_CXX([$1]m4_ifval($2, [, [$1[.cc ]$1[-]$2[.cc]]])) + ], [ + AT_BISON_CHECK([[-o ]$1[.c ]$1[.y]]) + AT_COMPILE([$1]m4_ifval($2, [, [$1[.c ]$1[-]$2[.c]]])) + ]) + ]) ]) @@ -430,6 +452,11 @@ m4_define([AT_FULL_COMPILE], m4_define([AT_PARSER_CHECK], [AT_CHECK([$5 $PREPARSER $1], [$2], [$3], [$4])]) +# AT_JAVA_PARSER_CHECK(COMMAND, EXIT-STATUS, EXPOUT, EXPERR, [PRE]) +# ----------------------------------------------------------------- +m4_define([AT_JAVA_PARSER_CHECK], +[AT_CHECK([$5[ $SHELL ../../../javaexec.sh ]$1], [$2], [$3], [$4])]) + # AT_TEST_TABLES_AND_PARSE(TITLE, COND-VALUE, TEST-SPEC, # DECLS, GRAMMAR, INPUT, # BISON-STDERR, TABLES-OR-LAST-STATE, -- 2.45.2