c: add support for YYNOMEM

Suggested by Joe Nelson <joe@begriffs.com>.
https://lists.gnu.org/r/help-bison/2020-12/msg00020.html

* data/skeletons/glr.c, data/skeletons/yacc.c (YYNOMEM): New.
Use it.
(yyexhaustedlab): Rename as...
(yynomemlab): this.
* tests/calc.at: Check it.
* doc/bison.texi: Document it.
Fix incorrect statements about non-existing constants for YYERROR etc.
This commit is contained in:
Akim Demaille
2021-01-16 09:17:07 +01:00
parent a9f9f317b5
commit 17fb1d0377
6 changed files with 67 additions and 35 deletions

5
NEWS
View File

@@ -64,6 +64,11 @@ GNU Bison NEWS
The Java skeleton (lalr1.java) now supports LAC, via the `parse.lac` The Java skeleton (lalr1.java) now supports LAC, via the `parse.lac`
%define variable. %define variable.
*** Abort parsing for memory exhaustion (C)
The user actions may now use YYNOMEM to abort the current parse with
memory exhaustion.
* Noteworthy changes in release 3.7.4 (2020-11-14) [stable] * Noteworthy changes in release 3.7.4 (2020-11-14) [stable]

View File

@@ -442,7 +442,7 @@ int yychar;])[
enum { YYENOMEM = -2 }; enum { YYENOMEM = -2 };
typedef enum { yyok, yyaccept, yyabort, yyerr } YYRESULTTAG; typedef enum { yyok, yyaccept, yyabort, yyerr, yynomem } YYRESULTTAG;
#define YYCHK(YYE) \ #define YYCHK(YYE) \
do { \ do { \
@@ -898,7 +898,7 @@ yyfill (yyGLRStackItem *yyvsp, int *yylow, int yylow1, yybool yynormal)
* and top stack item YYVSP. YYLVALP points to place to put semantic * and top stack item YYVSP. YYLVALP points to place to put semantic
* value ($$), and yylocp points to place for location information * value ($$), and yylocp points to place for location information
* (@@$). Returns yyok for normal return, yyaccept for YYACCEPT, * (@@$). Returns yyok for normal return, yyaccept for YYACCEPT,
* yyerr for YYERROR, yyabort for YYABORT. */ * yyerr for YYERROR, yyabort for YYABORT, yynomem for YYNOMEM. */
static YYRESULTTAG static YYRESULTTAG
yyuserAction (yyRuleNum yyrule, int yyrhslen, yyGLRStackItem* yyvsp, yyuserAction (yyRuleNum yyrule, int yyrhslen, yyGLRStackItem* yyvsp,
yyGLRStack* yystackp, YYPTRDIFF_T yyk, yyGLRStack* yystackp, YYPTRDIFF_T yyk,
@@ -915,6 +915,8 @@ yyuserAction (yyRuleNum yyrule, int yyrhslen, yyGLRStackItem* yyvsp,
# define YYACCEPT return yyaccept # define YYACCEPT return yyaccept
# undef YYABORT # undef YYABORT
# define YYABORT return yyabort # define YYABORT return yyabort
# undef YYNOMEM
# define YYNOMEM return yynomem
# undef YYERROR # undef YYERROR
# define YYERROR return yyerrok, yyerr # define YYERROR return yyerrok, yyerr
# undef YYRECOVERING # undef YYRECOVERING
@@ -965,6 +967,7 @@ yyuserAction (yyRuleNum yyrule, int yyrhslen, yyGLRStackItem* yyvsp,
# undef yyerrok # undef yyerrok
# undef YYABORT # undef YYABORT
# undef YYACCEPT # undef YYACCEPT
# undef YYNOMEM
# undef YYERROR # undef YYERROR
# undef YYBACKUP # undef YYBACKUP
# undef yyclearin # undef yyclearin
@@ -2431,6 +2434,7 @@ yyrecoverSyntaxError (yyGLRStack* yystackp]b4_user_formals[)
case yyabort: goto yyabortlab; \ case yyabort: goto yyabortlab; \
case yyaccept: goto yyacceptlab; \ case yyaccept: goto yyacceptlab; \
case yyerr: goto yyuser_error; \ case yyerr: goto yyuser_error; \
case yynomem: goto yyexhaustedlab; \
default: goto yybuglab; \ default: goto yybuglab; \
} \ } \
} while (0) } while (0)

View File

@@ -732,6 +732,7 @@ enum { YYENOMEM = -2 };
#define YYACCEPT goto yyacceptlab #define YYACCEPT goto yyacceptlab
#define YYABORT goto yyabortlab #define YYABORT goto yyabortlab
#define YYERROR goto yyerrorlab #define YYERROR goto yyerrorlab
#define YYNOMEM goto yyexhaustedlab
#define YYRECOVERING() (!!yyerrstatus) #define YYRECOVERING() (!!yyerrstatus)
@@ -987,7 +988,7 @@ do { \
switch (yy_lac (yyesa, &yyes, &yyes_capacity, yyssp, yytoken)) \ switch (yy_lac (yyesa, &yyes, &yyes_capacity, yyssp, yytoken)) \
{ \ { \
case YYENOMEM: \ case YYENOMEM: \
goto yyexhaustedlab; \ YYNOMEM; \
case 1: \ case 1: \
goto yyerrlab; \ goto yyerrlab; \
} \ } \
@@ -1707,7 +1708,7 @@ yysetstate:
if (yyss + yystacksize - 1 <= yyssp) if (yyss + yystacksize - 1 <= yyssp)
#if !defined yyoverflow && !defined YYSTACK_RELOCATE #if !defined yyoverflow && !defined YYSTACK_RELOCATE
goto yyexhaustedlab; YYNOMEM;
#else #else
{ {
/* Get the current used size of the three stacks, in elements. */ /* Get the current used size of the three stacks, in elements. */
@@ -1738,7 +1739,7 @@ yysetstate:
# else /* defined YYSTACK_RELOCATE */ # else /* defined YYSTACK_RELOCATE */
/* Extend the stack our own way. */ /* Extend the stack our own way. */
if (YYMAXDEPTH <= yystacksize) if (YYMAXDEPTH <= yystacksize)
goto yyexhaustedlab; YYNOMEM;
yystacksize *= 2; yystacksize *= 2;
if (YYMAXDEPTH < yystacksize) if (YYMAXDEPTH < yystacksize)
yystacksize = YYMAXDEPTH; yystacksize = YYMAXDEPTH;
@@ -1749,7 +1750,7 @@ yysetstate:
YY_CAST (union yyalloc *, YY_CAST (union yyalloc *,
YYSTACK_ALLOC (YY_CAST (YYSIZE_T, YYSTACK_BYTES (yystacksize)))); YYSTACK_ALLOC (YY_CAST (YYSIZE_T, YYSTACK_BYTES (yystacksize))));
if (! yyptr) if (! yyptr)
goto yyexhaustedlab; YYNOMEM;
YYSTACK_RELOCATE (yyss_alloc, yyss); YYSTACK_RELOCATE (yyss_alloc, yyss);
YYSTACK_RELOCATE (yyvs_alloc, yyvs);]b4_locations_if([ YYSTACK_RELOCATE (yyvs_alloc, yyvs);]b4_locations_if([
YYSTACK_RELOCATE (yyls_alloc, yyls);])[ YYSTACK_RELOCATE (yyls_alloc, yyls);])[
@@ -1980,8 +1981,8 @@ yyerrlab:
if (yychar != ]b4_symbol(empty, id)[) if (yychar != ]b4_symbol(empty, id)[)
YY_LAC_ESTABLISH;]])[ YY_LAC_ESTABLISH;]])[
if (yyreport_syntax_error (&yyctx]m4_ifset([b4_parse_param], if (yyreport_syntax_error (&yyctx]m4_ifset([b4_parse_param],
[[, ]b4_args(b4_parse_param)])[) == 2) [[, ]b4_args(b4_parse_param)])[) == 2)
goto yyexhaustedlab; YYNOMEM;
}]], }]],
[simple], [simple],
[[ yyerror (]b4_yyerror_args[YY_("syntax error"));]], [[ yyerror (]b4_yyerror_args[YY_("syntax error"));]],
@@ -2016,7 +2017,7 @@ yyerrlab:
} }
yyerror (]b4_yyerror_args[yymsgp); yyerror (]b4_yyerror_args[yymsgp);
if (yysyntax_error_status == YYENOMEM) if (yysyntax_error_status == YYENOMEM)
goto yyexhaustedlab; YYNOMEM;
}]])[ }]])[
} }
]b4_locations_if([[ ]b4_locations_if([[
@@ -2132,15 +2133,13 @@ yyabortlab:
goto yyreturnlab; goto yyreturnlab;
#if ]b4_lac_if([[1]], [b4_parse_error_case([simple], [[!defined yyoverflow]], [[1]])])[ /*-----------------------------------------------------------.
/*-------------------------------------------------. | yyexhaustedlab -- YYNOMEM (memory exhaustion) comes here. |
| yyexhaustedlab -- memory exhaustion comes here. | `-----------------------------------------------------------*/
`-------------------------------------------------*/
yyexhaustedlab: yyexhaustedlab:
yyerror (]b4_yyerror_args[YY_("memory exhausted")); yyerror (]b4_yyerror_args[YY_("memory exhausted"));
yyresult = 2; yyresult = 2;
goto yyreturnlab; goto yyreturnlab;
#endif
/*----------------------------------------------------------. /*----------------------------------------------------------.

View File

@@ -5239,10 +5239,10 @@ For instance, if your locations use a file name, you may use
@findex %destructor @findex %destructor
@findex <*> @findex <*>
@findex <> @findex <>
During error recovery (@pxref{Error Recovery}), symbols already pushed During error recovery (@pxref{Error Recovery}), symbols already pushed on
on the stack and tokens coming from the rest of the file are discarded the stack and tokens coming from the rest of the file are discarded until
until the parser falls on its feet. If the parser runs out of memory, the parser falls on its feet. If the parser runs out of memory, or if it
or if it returns via @code{YYABORT} or @code{YYACCEPT}, all the returns via @code{YYABORT}, @code{YYACCEPT} or @code{YYNOMEM}, all the
symbols on the stack must be discarded. Even if the parser succeeds, it symbols on the stack must be discarded. Even if the parser succeeds, it
must discard the start symbol. must discard the start symbol.
@@ -5368,8 +5368,8 @@ the start symbol, when the parser succeeds.
@end itemize @end itemize
The parser can @dfn{return immediately} because of an explicit call to The parser can @dfn{return immediately} because of an explicit call to
@code{YYABORT} or @code{YYACCEPT}, or failed error recovery, or memory @code{YYABORT}, @code{YYACCEPT} or @code{YYNOMEM}, or failed error recovery,
exhaustion. or memory exhaustion.
Right-hand side symbols of a rule that explicitly triggers a syntax Right-hand side symbols of a rule that explicitly triggers a syntax
error via @code{YYERROR} are not discarded automatically. As a rule error via @code{YYERROR} are not discarded automatically. As a rule
@@ -7215,6 +7215,11 @@ Return immediately with value 0 (to report success).
Return immediately with value 1 (to report failure). Return immediately with value 1 (to report failure).
@end defmac @end defmac
@defmac YYNOMEM
@findex YYNOMEM
Return immediately with value 2 (to report memory exhaustion).
@end defmac
If you use a reentrant parser, you can optionally pass additional If you use a reentrant parser, you can optionally pass additional
parameter information to it in a reentrant way. To do so, use the parameter information to it in a reentrant way. To do so, use the
declaration @code{%parse-param}: declaration @code{%parse-param}:
@@ -7936,6 +7941,11 @@ want to print an error message, call @code{yyerror} explicitly before
the @samp{YYERROR;} statement. @xref{Error Recovery}. the @samp{YYERROR;} statement. @xref{Error Recovery}.
@end deffn @end deffn
@deffn {Macro} YYNOMEM @code{;}
Return immediately from @code{yyparse}, indicating memory exhaustion.
@xref{Parser Function}.
@end deffn
@deffn {Macro} YYRECOVERING @deffn {Macro} YYRECOVERING
@findex YYRECOVERING @findex YYRECOVERING
The expression @code{YYRECOVERING ()} yields 1 when the parser The expression @code{YYRECOVERING ()} yields 1 when the parser
@@ -14676,10 +14686,10 @@ api.push-pull both" declaration is used (@pxref{%define
Summary}). The @code{Location} and @code{Position} Summary}). The @code{Location} and @code{Position}
parameters are available only if location tracking is active. parameters are available only if location tracking is active.
The value returned by the @code{push_parse} method is one of the following The value returned by the @code{push_parse} method is one of the following:
four constants: @code{YYABORT}, @code{YYACCEPT}, @code{YYERROR}, or 0 (success), 1 (abort), 2 (memory exhaustion), or @code{YYPUSH_MORE}. This
@code{YYPUSH_MORE}. This new value, @code{YYPUSH_MORE}, may be returned if new value, @code{YYPUSH_MORE}, may be returned if more input is required to
more input is required to finish parsing the grammar. finish parsing the grammar.
If api.push-pull is declared as @code{both}, then the generated parser class If api.push-pull is declared as @code{both}, then the generated parser class
will also implement the @code{parse} method. This method's body is a loop will also implement the @code{parse} method. This method's body is a loop
@@ -14719,13 +14729,12 @@ section summarizes these differences.
@itemize @itemize
@item @item
Java lacks a preprocessor, so the @code{YYERROR}, @code{YYACCEPT}, Java lacks a preprocessor, so obviously the @code{YYERROR}, @code{YYACCEPT},
@code{YYABORT} symbols (@pxref{Table of Symbols}) cannot obviously be @code{YYABORT} symbols (@pxref{Table of Symbols}) cannot be macros.
macros. Instead, they should be preceded by @code{return} when they Instead, they should be preceded by @code{return} when they appear in an
appear in an action. The actual definition of these symbols is action. The actual definition of these symbols is opaque to the Bison
opaque to the Bison grammar, and it might change in the future. The grammar, and it might change in the future. The only meaningful operation
only meaningful operation that you can do, is to return them. that you can do, is to return them. @xref{Java Action Features}.
@xref{Java Action Features}.
Note that of these three symbols, only @code{YYACCEPT} and Note that of these three symbols, only @code{YYACCEPT} and
@code{YYABORT} will cause a return from the @code{yyparse} @code{YYABORT} will cause a return from the @code{yyparse}
@@ -16006,6 +16015,12 @@ pure push parser, it is a member of @code{yypstate}.)
@xref{Error Reporting Function}. @xref{Error Reporting Function}.
@end deffn @end deffn
@deffn {Macro} YYNOMEM
Macro to pretend that memory is exhausted, by making @code{yyparse} return 2
immediately. The error reporting function @code{yyerror} is called.
@xref{Parser Function}.
@end deffn
@deffn {Function} yyparse @deffn {Function} yyparse
The parser function produced by Bison; call this function to start The parser function produced by Bison; call this function to start
parsing. @xref{Parser Function}. parsing. @xref{Parser Function}.
@@ -16518,12 +16533,13 @@ London, Department of Computer Science, TR-00-12 (December 2000).
@c LocalWords: YYUNDEF SymbolKind yypcontext YYENOMEM TOKENMAX getBundle @c LocalWords: YYUNDEF SymbolKind yypcontext YYENOMEM TOKENMAX getBundle
@c LocalWords: ResourceBundle myResources getString getName getToken ylwrap @c LocalWords: ResourceBundle myResources getString getName getToken ylwrap
@c LocalWords: getLocation getExpectedTokens reportSyntaxError bistromathic @c LocalWords: getLocation getExpectedTokens reportSyntaxError bistromathic
@c LocalWords: TokenKind Automake's rtti Wcounterexamples Chinawat PLDI @c LocalWords: TokenKind Automake's rtti Wcounterexamples Chinawat PLDI buf
@c LocalWords: Isradisaikul tcite pcite rgbGreen colorGreen rgbYellow Wcex @c LocalWords: Isradisaikul tcite pcite rgbGreen colorGreen rgbYellow Wcex
@c LocalWords: colorYellow rgbRed colorRed rgbBlue colorBlue rgbPurple Ddoc @c LocalWords: colorYellow rgbRed colorRed rgbBlue colorBlue rgbPurple Ddoc
@c LocalWords: colorPurple ifhtml ifnothtml situ rcex MERCHANTABILITY Wnone @c LocalWords: colorPurple ifhtml ifnothtml situ rcex MERCHANTABILITY Wnone
@c LocalWords: diagError diagNotice diagWarning diagOff danglingElseCex @c LocalWords: diagError diagNotice diagWarning diagOff danglingElseCex
@c LocalWords: nonunifying @c LocalWords: nonunifying YYNOMEM Wuseless dgettext textdomain domainname
@c LocalWords: dirname typeof writeln YYBISON
@c Local Variables: @c Local Variables:
@c ispell-dictionary: "american" @c ispell-dictionary: "american"

View File

@@ -32,3 +32,4 @@ The grammar features several special directives:
- `!!` YYERROR - `!!` YYERROR
- `!+` YYACCEPT - `!+` YYACCEPT
- `!-` YYABORT - `!-` YYABORT
- `!*` YYNOMEM

View File

@@ -447,7 +447,8 @@ exp:
| '-' error { $$ = 0; YYERROR; } | '-' error { $$ = 0; YYERROR; }
| '!' '!' { $$ = 0; YYERROR; } | '!' '!' { $$ = 0; YYERROR; }
| '!' '+' { $$ = 0; YYACCEPT; } | '!' '+' { $$ = 0; YYACCEPT; }
| '!' '-' { $$ = 0; YYABORT; } | '!' '-' { $$ = 0; YYABORT; }]AT_C_IF([[
| '!' '*' { $$ = 0; YYNOMEM; }]])[
; ;
%% %%
@@ -1224,7 +1225,7 @@ _AT_CHECK_CALC_ERROR([$1], [0], [(* *) + (*) + (*)],
# Special actions. # Special actions.
# ---------------- # ----------------
# !+ => YYACCEPT, !- => YYABORT, !! => YYERROR. # !+ => YYACCEPT, !- => YYABORT, !! => YYERROR, !* => YYNOMEM.
# YYACCEPT. # YYACCEPT.
# Java lacks the traces at the end for cleaning the stack # Java lacks the traces at the end for cleaning the stack
@@ -1238,6 +1239,12 @@ _AT_CHECK_CALC([], [1 + 2 * 3 + !+ ++],
_AT_CHECK_CALC_ERROR([$1], [1], [1 + 2 * 3 + !- ++], _AT_CHECK_CALC_ERROR([$1], [1], [1 + 2 * 3 + !- ++],
[AT_PARAM_IF([final: 0 0 0])], [AT_PARAM_IF([final: 0 0 0])],
[102]) [102])
AT_C_IF(
[# YYNOMEM.
_AT_CHECK_CALC_ERROR([$1], [2], [1 + 2 * 3 + !* ++],
[AT_PARAM_IF([final: 0 0 1])],
[102],
[1.14: memory exhausted])])
# YYerror. # YYerror.