]> git.saurik.com Git - bison.git/commitdiff
* data/glr.c (yyprocessOneStack): Synchronize the shift for all
authorPaul Eggert <eggert@cs.ucla.edu>
Tue, 6 Dec 2005 19:38:25 +0000 (19:38 +0000)
committerPaul Eggert <eggert@cs.ucla.edu>
Tue, 6 Dec 2005 19:38:25 +0000 (19:38 +0000)
stacks, and iterate another stack in order to call user
destructors.
* tests/glr-regression.at (No users destructors if stack 0 deleted):
New test case.
(Duplicated user destructor for lookahead): This test now is expected
to succeed.

ChangeLog
data/glr.c
tests/glr-regression.at

index e523509792fc7b2b18a676c62f4a037a4a19bf73..fe8bf3135f1cbd2a9166260323eb6c91404acf89 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2005-12-06  "Joel E. Denny" <jdenny@ces.clemson.edu>
+
+       * data/glr.c (yyprocessOneStack): Synchronize the shift for all
+       stacks, and iterate another stack in order to call user
+       destructors.
+       * tests/glr-regression.at (No users destructors if stack 0 deleted):
+       New test case.
+       (Duplicated user destructor for lookahead): This test now is expected
+       to succeed.
+
 2005-12-01  Paul Eggert  <eggert@cs.ucla.edu>
 
        * NEWS: Document the following change.
index de3b9bba83ff6a9ff96e17fac6845bbb05ec7dd4..f72e8bbbe4a1c1a3d19e857f223588d4604c2b8e 100644 (file)
@@ -507,8 +507,8 @@ static const ]b4_int_type_for([b4_stos])[ yystos[] =
 
 # define YY_LOCATION_PRINT(File, Loc)                  \
     fprintf (File, "%d.%d-%d.%d",                      \
-             (Loc).first_line, (Loc).first_column,     \
-             (Loc).last_line,  (Loc).last_column)
+            (Loc).first_line, (Loc).first_column,      \
+            (Loc).last_line,  (Loc).last_column)
 #endif
 ]],[
 #ifndef YYLLOC_DEFAULT
@@ -566,7 +566,7 @@ do {                                                                            \
     {                                                                      \
       YYFPRINTF (stderr, "%s ", Title);                                            \
       yysymprint (stderr,                                                  \
-                  Type, Value]b4_location_if([, Location])[]b4_user_args[); \
+                 Type, Value]b4_location_if([, Location])[]b4_user_args[); \
       YYFPRINTF (stderr, "\n");                                                    \
     }                                                                      \
 } while (/*CONSTCOND*/ 0)
@@ -867,7 +867,7 @@ yyuserAction (yyRuleNum yyn, int yyrhslen, yyGLRStackItem* yyvsp,
              YYSTYPE* yyvalp,
              YYLTYPE* YYOPTIONAL_LOC (yylocp),
              yyGLRStack* yystack
-              ]b4_user_formals[)
+             ]b4_user_formals[)
 {
   yybool yynormal __attribute__ ((__unused__)) =
     (yystack->yysplitPoint == NULL);
@@ -962,15 +962,15 @@ yydestroyGLRState (char const *yymsg, yyGLRState *yys]b4_user_formals[)
 #endif
 
       if (yys->yysemantics.yyfirstVal)
-        {
-          yySemanticOption *yyoption = yys->yysemantics.yyfirstVal;
-          yyGLRState *yyrh;
-          int yyn;
-          for (yyrh = yyoption->yystate, yyn = yyrhsLength (yyoption->yyrule);
-               yyn > 0;
-               yyrh = yyrh->yypred, yyn -= 1)
-            yydestroyGLRState (yymsg, yyrh]b4_user_args[);
-        }
+       {
+         yySemanticOption *yyoption = yys->yysemantics.yyfirstVal;
+         yyGLRState *yyrh;
+         int yyn;
+         for (yyrh = yyoption->yystate, yyn = yyrhsLength (yyoption->yyrule);
+              yyn > 0;
+              yyrh = yyrh->yypred, yyn -= 1)
+           yydestroyGLRState (yymsg, yyrh]b4_user_args[);
+       }
     }
 }
 
@@ -1016,7 +1016,7 @@ yydefaultAction (yyStateNum yystate)
  */
 static inline void
 yygetLRActions (yyStateNum yystate, int yytoken,
-               int* yyaction, const short int** yyconflicts)
+               int* yyaction, const short int** yyconflicts)
 {
   int yyindex = yypact[yystate] + yytoken;
   if (yyindex < 0 || YYLAST < yyindex || yycheck[yyindex] != yytoken)
@@ -1340,7 +1340,7 @@ yydoAction (yyGLRStack* yystack, size_t yyk, yyRuleNum yyrule,
        = yystack->yytops.yystates[yyk];]b4_location_if([[
       if (yynrhs == 0)
        /* Set default location. */
-        yyrhsVals[YYMAXRHS + YYMAXLEFT - 1].yystate.yyloc = yys->yyloc;]])[
+       yyrhsVals[YYMAXRHS + YYMAXLEFT - 1].yystate.yyloc = yys->yyloc;]])[
       for (yyi = 0; yyi < yynrhs; yyi += 1)
        {
          yys = yys->yypred;
@@ -1387,9 +1387,9 @@ yy_reduce_print (yyGLRStack* yystack, size_t yyk, yyRuleNum yyrule,
     {
       fprintf (stderr, "   $%d = ", yyi + 1);
       yysymprint (stderr, yyrhs[yyprhs[yyrule] + yyi],
-                  &]b4_rhs_value(yynrhs, yyi + 1)[
-                  ]b4_location_if([, &]b4_rhs_location(yynrhs, yyi + 1))[]dnl
-                 b4_user_args[);
+                 &]b4_rhs_value(yynrhs, yyi + 1)[
+                 ]b4_location_if([, &]b4_rhs_location(yynrhs, yyi + 1))[]dnl
+                 b4_user_args[);
       fprintf (stderr, "\n");
     }
 }
@@ -1408,7 +1408,7 @@ yy_reduce_print (yyGLRStack* yystack, size_t yyk, yyRuleNum yyrule,
  */
 static inline YYRESULTTAG
 yyglrReduce (yyGLRStack* yystack, size_t yyk, yyRuleNum yyrule,
-             yybool yyforceEval]b4_user_formals[)
+            yybool yyforceEval]b4_user_formals[)
 {
   size_t yyposn = yystack->yytops.yystates[yyk]->yyposn;
 
@@ -1623,7 +1623,7 @@ yyresolveStates (yyGLRState* yys, int yyn, yyGLRStack* yystack]b4_user_formals[)
 
 static YYRESULTTAG
 yyresolveAction (yySemanticOption* yyopt, yyGLRStack* yystack,
-                YYSTYPE* yyvalp, YYLTYPE* yylocp]b4_user_formals[)
+                YYSTYPE* yyvalp, YYLTYPE* yylocp]b4_user_formals[)
 {
   yyGLRStackItem yyrhsVals[YYMAXRHS + YYMAXLEFT + 1];
   int yynrhs;
@@ -1748,7 +1748,7 @@ yyresolveValue (yySemanticOption* yyoptionList, yyGLRStack* yystack,
              break;
            default:
              /* This cannot happen so it is not worth a YYASSERT (yyfalse),
-                but some compilers complain if the default case is
+                but some compilers complain if the default case is
                 omitted.  */
              break;
            }
@@ -1827,7 +1827,7 @@ yycompressStack (yyGLRStack* yystack)
 
 static YYRESULTTAG
 yyprocessOneStack (yyGLRStack* yystack, size_t yyk,
-                  size_t yyposn, YYSTYPE* yylvalp, YYLTYPE* yyllocp
+                  size_t yyposn, YYSTYPE* yylvalp, YYLTYPE* yyllocp
                  ]b4_pure_formals[)
 {
   int yyaction;
@@ -1880,16 +1880,7 @@ yyprocessOneStack (yyGLRStack* yystack, size_t yyk,
            }
 
          if (yyisShiftAction (yyaction))
-           {
-             YYDPRINTF ((stderr, "On stack %lu, ", (unsigned long int) yyk));
-             YY_SYMBOL_PRINT ("shifting", *yytokenp, yylvalp, yyllocp);
-             yyglrShift (yystack, yyk, yyaction, yyposn+1,
-                         *yylvalp, yyllocp);
-             YYDPRINTF ((stderr, "Stack %lu now in state #%d\n",
-                         (unsigned long int) yyk,
-                         yystack->yytops.yystates[yyk]->yylrState));
-             break;
-           }
+           break;
          else if (yyisErrorAction (yyaction))
            {
              YYDPRINTF ((stderr, "Stack %lu dies.\n",
@@ -2187,7 +2178,7 @@ b4_syncline([@oline@], [@ofile@])])dnl
          const short int* yyconflicts;
 
          yyStateNum yystate = yystack.yytops.yystates[0]->yylrState;
-          YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+         YYDPRINTF ((stderr, "Entering state %d\n", yystate));
          if (yystate == YYFINAL)
            goto yyacceptlab;
          if (yyisDefaultedState (yystate))
@@ -2208,7 +2199,7 @@ b4_syncline([@oline@], [@ofile@])])dnl
                  YYDPRINTF ((stderr, "Reading a token: "));
                  yychar = YYLEX;
                  yytoken = YYTRANSLATE (yychar);
-                  YY_SYMBOL_PRINT ("Next token is", yytoken, yylvalp, yyllocp);
+                 YY_SYMBOL_PRINT ("Next token is", yytoken, yylvalp, yyllocp);
                }
              yygetLRActions (yystate, yytoken, &yyaction, &yyconflicts);
              if (*yyconflicts != 0)
@@ -2236,14 +2227,59 @@ b4_syncline([@oline@], [@ofile@])])dnl
 
       while (yytrue)
        {
+         yySymbol yytoken_to_shift;
          size_t yys;
          size_t yyn = yystack.yytops.yysize;
+
+         /* yyprocessOneStack returns one of three things:
+
+             - An error flag.  If the caller is yyprocessOneStack, it
+               immediately returns as well.  When the caller is finally
+               yyparse, it jumps to an error label via YYCHK1.
+
+             - yyok, but yyprocessOneStack has invoked yymarkStackDeleted
+               (&yystack, yys), which sets the top state of yys to NULL.  Thus,
+               yyparse's following invocation of yyremoveDeletes will remove
+               the stack.
+
+             - yyok, when ready to shift a token.
+
+            Except in the first case, yyparse will invoke yyremoveDeletes and
+            then shift the next token onto all remaining stacks.  This
+            synchronization of the shift (that is, after all preceding
+            reductions on all stacks) helps prevents double destructor calls
+            on yylval in the event of memory exhaustion.  */
+
          for (yys = 0; yys < yyn; yys += 1)
            YYCHK1 (yyprocessOneStack (&yystack, yys, yyposn,
                                       yylvalp, yyllocp]b4_lpure_args[));
+         yyremoveDeletes (&yystack);
+         yyn = yystack.yytops.yysize;
+
+         /* If any yyglrShift call fails, it will fail after shifting.  Thus,
+            a copy of yylval will already be on stack 0 in the event of a
+            failure in the following loop.  Thus, yytoken is set to YYEMPTY
+            before the loop to make sure the user destructor for yylval isn't
+            called twice.  */
+         yytoken_to_shift = yytoken;
          yytoken = YYEMPTY;
          yyposn += 1;
-         yyremoveDeletes (&yystack);
+         for (yys = 0; yys < yyn; yys += 1)
+           {
+             int yyaction;
+             const short int* yyconflicts;
+             yyStateNum yystate = yystack.yytops.yystates[yys]->yylrState;
+             yygetLRActions (yystate, yytoken_to_shift, &yyaction,
+                             &yyconflicts);
+             /* Note that yyconflicts were handled by yyprocessOneStack.  */
+             YYDPRINTF ((stderr, "On stack %lu, ", (unsigned long int) yys));
+             YY_SYMBOL_PRINT ("shifting", yytoken_to_shift, yylvalp, yyllocp);
+             yyglrShift (&yystack, yys, yyaction, yyposn,
+                         *yylvalp, yyllocp);
+             YYDPRINTF ((stderr, "Stack %lu now in state #%d\n",
+                         (unsigned long int) yys,
+                         yystack.yytops.yystates[yys]->yylrState));
+           }
          if (yystack.yytops.yysize == 0)
            {
              yyundeleteLastStack (&yystack);
@@ -2289,7 +2325,7 @@ b4_syncline([@oline@], [@ofile@])])dnl
  yyreturn:
   if (yytoken != YYEOF && yytoken != YYEMPTY)
     yydestruct ("Cleanup: discarding lookahead",
-                yytoken, yylvalp]b4_location_if([, yyllocp])[]b4_user_args[);
+               yytoken, yylvalp]b4_location_if([, yyllocp])[]b4_user_args[);
 
   /* If the stack is well-formed, pop the stack until it is empty,
      destroying its entries as we go.  But free the stack regardless
@@ -2298,15 +2334,24 @@ b4_syncline([@oline@], [@ofile@])])dnl
     {
       yyGLRState** yystates = yystack.yytops.yystates;
       if (yystates)
-       while (yystates[0])
-         {
-           yyGLRState *yys = yystates[0];
-]b4_location_if([[       yystack.yyerror_range[1].yystate.yyloc = yys->yyloc;]]
-)[         yydestroyGLRState ("Cleanup: popping", yys]b4_user_args[);
-           yystates[0] = yys->yypred;
-           yystack.yynextFree -= 1;
-           yystack.yyspaceLeft += 1;
-         }
+       {
+         size_t yysize = yystack.yytops.yysize;
+         size_t yyk;
+         for (yyk = 0; yyk < yysize; yyk += 1)
+           if (yystates[yyk])
+             {
+               while (yystates[yyk])
+                 {
+                   yyGLRState *yys = yystates[yyk];
+]b4_location_if([[                 yystack.yyerror_range[1].yystate.yyloc = yys->yyloc;]]
+)[                 yydestroyGLRState ("Cleanup: popping", yys]b4_user_args[);
+                   yystates[yyk] = yys->yypred;
+                   yystack.yynextFree -= 1;
+                   yystack.yyspaceLeft += 1;
+                 }
+               break;
+             }
+       }
       yyfreeGLRStack (&yystack);
     }
 
@@ -2390,7 +2435,7 @@ b4_epilogue
 m4_if(b4_defines_flag, 0, [],
 [@output @output_header_name@
 b4_copyright([Skeleton parser for GLR parsing with Bison],
-             [2002, 2003, 2004, 2005])[
+            [2002, 2003, 2004, 2005])[
 
 /* As a special exception, when this parser skeleton is copied by
    Bison into a Bison output file, you may use that output file
index 148931559a41391705e31f6dd6a5179e139c9af3..e3bdd26b57c9f0a4ed985c3953b3c022b12cc83e 100644 (file)
@@ -633,8 +633,6 @@ AT_CHECK([[./glr-regr7]], 2, [],
 [memory exhausted
 ])
 
-AT_XFAIL_IF(:)
-
 AT_CLEANUP
 
 
@@ -667,9 +665,9 @@ AT_DATA_GRAMMAR([glr-regr8.y],
 
 
 PortClause     : T_PORT InterfaceDeclaration T_PORT
-               { printf("%d/%d - %d/%d - %d/%d\n", 
-                        @1.first_column, @1.last_column, 
-                        @2.first_column, @2.last_column, 
+               { printf("%d/%d - %d/%d - %d/%d\n",
+                        @1.first_column, @1.last_column,
+                        @2.first_column, @2.last_column,
                         @3.first_column, @3.last_column); }
        ;
 
@@ -695,7 +693,7 @@ void yyerror(const char *msg)
 
 static int lexIndex;
 
-int yylex() 
+int yylex (void)
 {
   lexIndex += 1;
   switch (lexIndex)
@@ -714,7 +712,7 @@ int yylex()
 }
 
 int
-main (void) 
+main (void)
 {
   yyparse();
   return 0;
@@ -726,10 +724,91 @@ AT_CHECK([[bison -o glr-regr8.c glr-regr8.y]], 0, [],
 ])
 AT_COMPILE([glr-regr8])
 
-AT_CHECK([[./glr-regr8]], 0, 
+AT_CHECK([[./glr-regr8]], 0,
 [empty: 9/9
 1/9 - 9/9 - 13/17
 ],
 [])
 
 AT_CLEANUP
+
+
+## ------------------------------------------------------------------------- ##
+## No users destructors if stack 0 deleted                                   ##
+## Thanks to Joel E. Denny for this test; see                                ##
+## <http://lists.gnu.org/archive/html/bison-patches/2005-09/msg00109.html>.  ##
+## ------------------------------------------------------------------------- ##
+
+AT_SETUP([No users destructors if stack 0 deleted])
+
+AT_DATA_GRAMMAR([glr-regr9.y],
+[[
+%{
+  #include <stdio.h>
+  #include <stdlib.h>
+  static void yyerror (char const *);
+  static int yylex (void);
+  #define YYSTACKEXPANDABLE 0
+  static int tokens = 0;
+  static int destructors = 0;
+%}
+
+%glr-parser
+%union { int dummy; }
+%type <dummy> 'a'
+
+%destructor {
+  destructors += 1;
+} 'a'
+
+%%
+
+start:
+  ambig0 'a' { destructors += 2; }
+  | ambig1 start { destructors += 1; }
+  | ambig2 start { destructors += 1; }
+  ;
+
+ambig0: 'a' ;
+ambig1: 'a' ;
+ambig2: 'a' ;
+
+%%
+
+static int
+yylex (void)
+{
+  tokens += 1;
+  return 'a';
+}
+
+static void
+yyerror (char const *msg)
+{
+  fprintf (stderr, "%s\n", msg);
+}
+
+int
+main (void)
+{
+  int exit_status;
+  exit_status = yyparse ();
+  if (tokens != destructors)
+    {
+      fprintf (stderr, "Tokens = %d, Destructors = %d\n", tokens, destructors);
+      return 1;
+    }
+  return !exit_status;
+}
+]])
+
+AT_CHECK([[bison -o glr-regr9.c glr-regr9.y]], 0, [],
+[glr-regr9.y: conflicts: 1 reduce/reduce
+])
+AT_COMPILE([glr-regr9])
+
+AT_CHECK([[./glr-regr9]], 0, [],
+[memory exhausted
+])
+
+AT_CLEANUP