bison-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 5/5] c: add support for YYNOMEM


From: Akim Demaille
Subject: [PATCH 5/5] c: add support for YYNOMEM
Date: Sat, 16 Jan 2021 12:59:05 +0100

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.
---
 NEWS                  |  5 ++++
 data/skeletons/glr.c  |  8 +++++--
 data/skeletons/yacc.c | 23 +++++++++---------
 doc/bison.texi        | 54 ++++++++++++++++++++++++++++---------------
 tests/README.md       |  1 +
 tests/calc.at         | 11 +++++++--
 6 files changed, 67 insertions(+), 35 deletions(-)

diff --git a/NEWS b/NEWS
index e12ba6fa..f2c235eb 100644
--- a/NEWS
+++ b/NEWS
@@ -64,6 +64,11 @@ GNU Bison NEWS
   The Java skeleton (lalr1.java) now supports LAC, via the `parse.lac`
   %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]
 
diff --git a/data/skeletons/glr.c b/data/skeletons/glr.c
index ab398101..b9334aa2 100644
--- a/data/skeletons/glr.c
+++ b/data/skeletons/glr.c
@@ -442,7 +442,7 @@ int yychar;])[
 
 enum { YYENOMEM = -2 };
 
-typedef enum { yyok, yyaccept, yyabort, yyerr } YYRESULTTAG;
+typedef enum { yyok, yyaccept, yyabort, yyerr, yynomem } YYRESULTTAG;
 
 #define YYCHK(YYE)                              \
   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
  *  value ($$), and yylocp points to place for location information
  *  (@@$).  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
 yyuserAction (yyRuleNum yyrule, int yyrhslen, yyGLRStackItem* yyvsp,
               yyGLRStack* yystackp, YYPTRDIFF_T yyk,
@@ -915,6 +915,8 @@ yyuserAction (yyRuleNum yyrule, int yyrhslen, 
yyGLRStackItem* yyvsp,
 # define YYACCEPT return yyaccept
 # undef YYABORT
 # define YYABORT return yyabort
+# undef YYNOMEM
+# define YYNOMEM return yynomem
 # undef YYERROR
 # define YYERROR return yyerrok, yyerr
 # undef YYRECOVERING
@@ -965,6 +967,7 @@ yyuserAction (yyRuleNum yyrule, int yyrhslen, 
yyGLRStackItem* yyvsp,
 # undef yyerrok
 # undef YYABORT
 # undef YYACCEPT
+# undef YYNOMEM
 # undef YYERROR
 # undef YYBACKUP
 # undef yyclearin
@@ -2431,6 +2434,7 @@ yyrecoverSyntaxError (yyGLRStack* 
yystackp]b4_user_formals[)
     case yyabort:  goto yyabortlab;             \
     case yyaccept: goto yyacceptlab;            \
     case yyerr:    goto yyuser_error;           \
+    case yynomem:  goto yyexhaustedlab;         \
     default:       goto yybuglab;               \
     }                                           \
   } while (0)
diff --git a/data/skeletons/yacc.c b/data/skeletons/yacc.c
index 56a050b3..739382ce 100644
--- a/data/skeletons/yacc.c
+++ b/data/skeletons/yacc.c
@@ -732,6 +732,7 @@ enum { YYENOMEM = -2 };
 #define YYACCEPT        goto yyacceptlab
 #define YYABORT         goto yyabortlab
 #define YYERROR         goto yyerrorlab
+#define YYNOMEM         goto yyexhaustedlab
 
 
 #define YYRECOVERING()  (!!yyerrstatus)
@@ -987,7 +988,7 @@ do {                                                        
            \
       switch (yy_lac (yyesa, &yyes, &yyes_capacity, yyssp, yytoken))    \
         {                                                               \
         case YYENOMEM:                                                  \
-          goto yyexhaustedlab;                                          \
+          YYNOMEM;                                                      \
         case 1:                                                         \
           goto yyerrlab;                                                \
         }                                                               \
@@ -1707,7 +1708,7 @@ yysetstate:
 
   if (yyss + yystacksize - 1 <= yyssp)
 #if !defined yyoverflow && !defined YYSTACK_RELOCATE
-    goto yyexhaustedlab;
+    YYNOMEM;
 #else
     {
       /* Get the current used size of the three stacks, in elements.  */
@@ -1738,7 +1739,7 @@ yysetstate:
 # else /* defined YYSTACK_RELOCATE */
       /* Extend the stack our own way.  */
       if (YYMAXDEPTH <= yystacksize)
-        goto yyexhaustedlab;
+        YYNOMEM;
       yystacksize *= 2;
       if (YYMAXDEPTH < yystacksize)
         yystacksize = YYMAXDEPTH;
@@ -1749,7 +1750,7 @@ yysetstate:
           YY_CAST (union yyalloc *,
                    YYSTACK_ALLOC (YY_CAST (YYSIZE_T, YYSTACK_BYTES 
(yystacksize))));
         if (! yyptr)
-          goto yyexhaustedlab;
+          YYNOMEM;
         YYSTACK_RELOCATE (yyss_alloc, yyss);
         YYSTACK_RELOCATE (yyvs_alloc, yyvs);]b4_locations_if([
         YYSTACK_RELOCATE (yyls_alloc, yyls);])[
@@ -1980,8 +1981,8 @@ yyerrlab:
         if (yychar != ]b4_symbol(empty, id)[)
           YY_LAC_ESTABLISH;]])[
         if (yyreport_syntax_error (&yyctx]m4_ifset([b4_parse_param],
-                                  [[, ]b4_args(b4_parse_param)])[) == 2)
-          goto yyexhaustedlab;
+                                   [[, ]b4_args(b4_parse_param)])[) == 2)
+          YYNOMEM;
       }]],
          [simple],
 [[      yyerror (]b4_yyerror_args[YY_("syntax error"));]],
@@ -2016,7 +2017,7 @@ yyerrlab:
           }
         yyerror (]b4_yyerror_args[yymsgp);
         if (yysyntax_error_status == YYENOMEM)
-          goto yyexhaustedlab;
+          YYNOMEM;
       }]])[
     }
 ]b4_locations_if([[
@@ -2132,15 +2133,13 @@ yyabortlab:
   goto yyreturnlab;
 
 
-#if ]b4_lac_if([[1]], [b4_parse_error_case([simple], [[!defined yyoverflow]], 
[[1]])])[
-/*-------------------------------------------------.
-| yyexhaustedlab -- memory exhaustion comes here.  |
-`-------------------------------------------------*/
+/*-----------------------------------------------------------.
+| yyexhaustedlab -- YYNOMEM (memory exhaustion) comes here.  |
+`-----------------------------------------------------------*/
 yyexhaustedlab:
   yyerror (]b4_yyerror_args[YY_("memory exhausted"));
   yyresult = 2;
   goto yyreturnlab;
-#endif
 
 
 /*----------------------------------------------------------.
diff --git a/doc/bison.texi b/doc/bison.texi
index e5cc7bd7..586dd5ce 100644
--- a/doc/bison.texi
+++ b/doc/bison.texi
@@ -5239,10 +5239,10 @@ For instance, if your locations use a file name, you 
may use
 @findex %destructor
 @findex <*>
 @findex <>
-During error recovery (@pxref{Error Recovery}), symbols already pushed
-on the stack and tokens coming from the rest of the file are discarded
-until the parser falls on its feet.  If the parser runs out of memory,
-or if it returns via @code{YYABORT} or @code{YYACCEPT}, all the
+During error recovery (@pxref{Error Recovery}), symbols already pushed on
+the stack and tokens coming from the rest of the file are discarded until
+the parser falls on its feet.  If the parser runs out of memory, or if it
+returns via @code{YYABORT}, @code{YYACCEPT} or @code{YYNOMEM}, all the
 symbols on the stack must be discarded.  Even if the parser succeeds, it
 must discard the start symbol.
 
@@ -5368,8 +5368,8 @@ the start symbol, when the parser succeeds.
 @end itemize
 
 The parser can @dfn{return immediately} because of an explicit call to
-@code{YYABORT} or @code{YYACCEPT}, or failed error recovery, or memory
-exhaustion.
+@code{YYABORT}, @code{YYACCEPT} or @code{YYNOMEM}, or failed error recovery,
+or memory exhaustion.
 
 Right-hand side symbols of a rule that explicitly triggers a syntax
 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).
 @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
 parameter information to it in a reentrant way.  To do so, use the
 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}.
 @end deffn
 
+@deffn {Macro} YYNOMEM @code{;}
+Return immediately from @code{yyparse}, indicating memory exhaustion.
+@xref{Parser Function}.
+@end deffn
+
 @deffn {Macro} YYRECOVERING
 @findex YYRECOVERING
 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}
 parameters are available only if location tracking is active.
 
-The value returned by the @code{push_parse} method is one of the following
-four constants: @code{YYABORT}, @code{YYACCEPT}, @code{YYERROR}, or
-@code{YYPUSH_MORE}.  This new value, @code{YYPUSH_MORE}, may be returned if
-more input is required to finish parsing the grammar.
+The value returned by the @code{push_parse} method is one of the following:
+0 (success), 1 (abort), 2 (memory exhaustion), or @code{YYPUSH_MORE}.  This
+new value, @code{YYPUSH_MORE}, may be returned if more input is required to
+finish parsing the grammar.
 
 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
@@ -14719,13 +14729,12 @@ section summarizes these differences.
 
 @itemize
 @item
-Java lacks a preprocessor, so the @code{YYERROR}, @code{YYACCEPT},
-@code{YYABORT} symbols (@pxref{Table of Symbols}) cannot obviously be
-macros.  Instead, they should be preceded by @code{return} when they
-appear in an action.  The actual definition of these symbols is
-opaque to the Bison grammar, and it might change in the future.  The
-only meaningful operation that you can do, is to return them.
-@xref{Java Action Features}.
+Java lacks a preprocessor, so obviously the @code{YYERROR}, @code{YYACCEPT},
+@code{YYABORT} symbols (@pxref{Table of Symbols}) cannot be macros.
+Instead, they should be preceded by @code{return} when they appear in an
+action.  The actual definition of these symbols is opaque to the Bison
+grammar, and it might change in the future.  The only meaningful operation
+that you can do, is to return them.  @xref{Java Action Features}.
 
 Note that of these three symbols, only @code{YYACCEPT} and
 @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}.
 @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
 The parser function produced by Bison; call this function to start
 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: ResourceBundle myResources getString getName getToken ylwrap
 @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: colorYellow rgbRed colorRed rgbBlue colorBlue rgbPurple Ddoc
 @c LocalWords: colorPurple ifhtml ifnothtml situ rcex MERCHANTABILITY Wnone
 @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 ispell-dictionary: "american"
diff --git a/tests/README.md b/tests/README.md
index 76990a04..53d1a2bf 100644
--- a/tests/README.md
+++ b/tests/README.md
@@ -32,3 +32,4 @@ The grammar features several special directives:
 - `!!` YYERROR
 - `!+` YYACCEPT
 - `!-` YYABORT
+- `!*` YYNOMEM
diff --git a/tests/calc.at b/tests/calc.at
index 2643d570..e7a5b070 100644
--- a/tests/calc.at
+++ b/tests/calc.at
@@ -447,7 +447,8 @@ exp:
 | '-' error          { $$ = 0; YYERROR; }
 | '!' '!'            { $$ = 0; YYERROR; }
 | '!' '+'            { $$ = 0; YYACCEPT; }
-| '!' '-'            { $$ = 0; YYABORT; }
+| '!' '-'            { $$ = 0; YYABORT; }]AT_C_IF([[
+| '!' '*'            { $$ = 0; YYNOMEM; }]])[
 ;
 %%
 
@@ -1224,7 +1225,7 @@ _AT_CHECK_CALC_ERROR([$1], [0], [(* *) + (*) + (*)],
 
 # Special actions.
 # ----------------
-# !+ => YYACCEPT, !- => YYABORT, !! => YYERROR.
+# !+ => YYACCEPT, !- => YYABORT, !! => YYERROR, !* => YYNOMEM.
 
 # YYACCEPT.
 # 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_PARAM_IF([final: 0 0 0])],
                      [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.
-- 
2.30.0




reply via email to

[Prev in Thread] Current Thread [Next in Thread]