]> git.saurik.com Git - bison.git/commitdiff
Clean up handling of %destructor for the end token (token 0).
authorJoel E. Denny <jdenny@ces.clemson.edu>
Sat, 29 Jul 2006 04:11:33 +0000 (04:11 +0000)
committerJoel E. Denny <jdenny@ces.clemson.edu>
Sat, 29 Jul 2006 04:11:33 +0000 (04:11 +0000)
Discussed starting at
<http://lists.gnu.org/archive/html/bison-patches/2006-07/msg00019.html>
and
<http://lists.gnu.org/archive/html/help-bison/2006-07/msg00013.html>.

Make the skeletons consistent in how they pop the end token and invoke
its %destructor.
* data/glr.c (yyrecoverSyntaxError, yyparse): Don't pop the start
state, which has token number 0, since this would invoke the
%destructor for the end token.
* data/lalr1.cc (yy::parser::parse): Don't check for the final state
until after shifting the end token, or else it won't be popped.
* data/yacc.c (yyparse): Likewise.

* data/glr.c (yyparse): Clear the lookahead after shifting it even when
it's the end token.  Upon termination, destroy an unshifted lookahead
even when it's the end token.
* data/lalr1.cc (yy::parser::parse): Likewise.
* data/yacc.c (yyparse): Likewise.

* src/reader.c (packgram): Don't check rule 0.  This suppresses unused
value warnings for the end token when the user gives the end token a
%destructor.

* tests/actions.at (Printers and Destructors): Test all the above.

ChangeLog
data/glr.c
data/lalr1.cc
data/yacc.c
src/reader.c
tests/actions.at

index 6880017d0cee5f9db050dea1febb19e61683ad5f..d603301c4eafd8e8e06d92615f39a9f86f00619c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,32 @@
+2006-07-29  Joel E. Denny  <jdenny@ces.clemson.edu>
+
+       Clean up handling of %destructor for the end token (token 0).
+       Discussed starting at
+       <http://lists.gnu.org/archive/html/bison-patches/2006-07/msg00019.html>
+       and
+       <http://lists.gnu.org/archive/html/help-bison/2006-07/msg00013.html>.
+
+       Make the skeletons consistent in how they pop the end token and invoke
+       its %destructor.
+       * data/glr.c (yyrecoverSyntaxError, yyparse): Don't pop the start
+       state, which has token number 0, since this would invoke the
+       %destructor for the end token.
+       * data/lalr1.cc (yy::parser::parse): Don't check for the final state
+       until after shifting the end token, or else it won't be popped.
+       * data/yacc.c (yyparse): Likewise.
+
+       * data/glr.c (yyparse): Clear the lookahead after shifting it even when
+       it's the end token.  Upon termination, destroy an unshifted lookahead
+       even when it's the end token.
+       * data/lalr1.cc (yy::parser::parse): Likewise.
+       * data/yacc.c (yyparse): Likewise.
+
+       * src/reader.c (packgram): Don't check rule 0.  This suppresses unused
+       value warnings for the end token when the user gives the end token a
+       %destructor.
+
+       * tests/actions.at (Printers and Destructors): Test all the above.
+
 2006-07-24  Paul Eggert  <eggert@cs.ucla.edu>
 
        Update to latest gnulib and gettext versions.
 2006-07-24  Paul Eggert  <eggert@cs.ucla.edu>
 
        Update to latest gnulib and gettext versions.
index 836df5032c72d646cea95dd866ca80b558d37aa5..7c3d998d29aadbf89b82638d1831a5f01d8d99dc 100644 (file)
@@ -2261,7 +2261,8 @@ yyrecoverSyntaxError (yyGLRStack* yystackp]b4_user_formals[)
            }
        }
 ]b4_locations_if([[      yystackp->yyerror_range[1].yystate.yyloc = yys->yyloc;]])[
            }
        }
 ]b4_locations_if([[      yystackp->yyerror_range[1].yystate.yyloc = yys->yyloc;]])[
-      yydestroyGLRState ("Error: popping", yys]b4_user_args[);
+      if (yys->yypred != NULL)
+       yydestroyGLRState ("Error: popping", yys]b4_user_args[);
       yystackp->yytops.yystates[0] = yys->yypred;
       yystackp->yynextFree -= 1;
       yystackp->yyspaceLeft += 1;
       yystackp->yytops.yystates[0] = yys->yypred;
       yystackp->yynextFree -= 1;
       yystackp->yyspaceLeft += 1;
@@ -2373,8 +2374,7 @@ m4_popdef([b4_at_dollar])])dnl
              if (yyisShiftAction (yyaction))
                {
                  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
              if (yyisShiftAction (yyaction))
                {
                  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
-                 if (yychar != YYEOF)
-                   yychar = YYEMPTY;
+                 yychar = YYEMPTY;
                  yyposn += 1;
                  yyglrShift (&yystack, 0, yyaction, yyposn, &yylval, &yylloc);
                  if (0 < yystack.yyerrState)
                  yyposn += 1;
                  yyglrShift (&yystack, 0, yyaction, yyposn, &yylval, &yylloc);
                  if (0 < yystack.yyerrState)
@@ -2490,7 +2490,7 @@ m4_popdef([b4_at_dollar])])dnl
   goto yyreturn;
 
  yyreturn:
   goto yyreturn;
 
  yyreturn:
-  if (yychar != YYEOF && yychar != YYEMPTY)
+  if (yychar != YYEMPTY)
     yydestruct ("Cleanup: discarding lookahead",
                YYTRANSLATE (yychar),
                &yylval]b4_locations_if([, &yylloc])[]b4_user_args[);
     yydestruct ("Cleanup: discarding lookahead",
                YYTRANSLATE (yychar),
                &yylval]b4_locations_if([, &yylloc])[]b4_user_args[);
@@ -2512,7 +2512,8 @@ m4_popdef([b4_at_dollar])])dnl
                  {
                    yyGLRState *yys = yystates[yyk];
 ]b4_locations_if([[                yystack.yyerror_range[1].yystate.yyloc = yys->yyloc;]]
                  {
                    yyGLRState *yys = yystates[yyk];
 ]b4_locations_if([[                yystack.yyerror_range[1].yystate.yyloc = yys->yyloc;]]
-)[                 yydestroyGLRState ("Cleanup: popping", yys]b4_user_args[);
+)[                 if (yys->yypred != NULL)
+                     yydestroyGLRState ("Cleanup: popping", yys]b4_user_args[);
                    yystates[yyk] = yys->yypred;
                    yystack.yynextFree -= 1;
                    yystack.yyspaceLeft += 1;
                    yystates[yyk] = yys->yypred;
                    yystack.yynextFree -= 1;
                    yystack.yyspaceLeft += 1;
index 25b9160cb87b728ecc2360e17a2721fae6c3a4ea..377659e54100c6e56174310dad31b4742b317933 100644 (file)
@@ -567,6 +567,11 @@ m4_popdef([b4_at_dollar])])dnl
   yynewstate:
     yystate_stack_.push (yystate);
     YYCDEBUG << "Entering state " << yystate << std::endl;
   yynewstate:
     yystate_stack_.push (yystate);
     YYCDEBUG << "Entering state " << yystate << std::endl;
+
+    /* Accept?  */
+    if (yystate == yyfinal_)
+      goto yyacceptlab;
+
     goto yybackup;
 
     /* Backup.  */
     goto yybackup;
 
     /* Backup.  */
@@ -616,16 +621,11 @@ m4_ifdef([b4_lex_param], [, ]b4_lex_param))[;
        goto yyreduce;
       }
 
        goto yyreduce;
       }
 
-    /* Accept?  */
-    if (yyn == yyfinal_)
-      goto yyacceptlab;
-
     /* Shift the lookahead token.  */
     YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
 
     /* Shift the lookahead token.  */
     YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
 
-    /* Discard the token being shifted unless it is eof.  */
-    if (yychar != yyeof_)
-      yychar = yyempty_;
+    /* Discard the token being shifted.  */
+    yychar = yyempty_;
 
     yysemantic_stack_.push (yylval);
     yylocation_stack_.push (yylloc);
 
     yysemantic_stack_.push (yylval);
     yylocation_stack_.push (yylloc);
@@ -780,9 +780,6 @@ b4_error_verbose_if([, yytoken])[));
        YY_STACK_PRINT ();
       }
 
        YY_STACK_PRINT ();
       }
 
-    if (yyn == yyfinal_)
-      goto yyacceptlab;
-
     yyerror_range[1] = yylloc;
     // Using YYLLOC is tempting, but would change the location of
     // the lookahead.  YYLOC is available though.
     yyerror_range[1] = yylloc;
     // Using YYLLOC is tempting, but would change the location of
     // the lookahead.  YYLOC is available though.
@@ -808,7 +805,7 @@ b4_error_verbose_if([, yytoken])[));
     goto yyreturn;
 
   yyreturn:
     goto yyreturn;
 
   yyreturn:
-    if (yychar != yyeof_ && yychar != yyempty_)
+    if (yychar != yyempty_)
       yydestruct_ ("Cleanup: discarding lookahead", yytoken, &yylval, &yylloc);
 
     /* Do not reclaim the symbols of the rule which action triggered
       yydestruct_ ("Cleanup: discarding lookahead", yytoken, &yylval, &yylloc);
 
     /* Do not reclaim the symbols of the rule which action triggered
index cdc6920390f36fb659c4fbbf4f4a2c1f06cc9200..74a014f131a900895fbfd41dc4fc4dcfec9486c3 100644 (file)
@@ -1164,6 +1164,9 @@ m4_ifdef([b4_at_dollar_used], [[  yylsp[0] = yylloc;
 
   YYDPRINTF ((stderr, "Entering state %d\n", yystate));
 
 
   YYDPRINTF ((stderr, "Entering state %d\n", yystate));
 
+  if (yystate == YYFINAL)
+    YYACCEPT;
+
   goto yybackup;
 
 /*-----------.
   goto yybackup;
 
 /*-----------.
@@ -1213,9 +1216,6 @@ yybackup:
       goto yyreduce;
     }
 
       goto yyreduce;
     }
 
-  if (yyn == YYFINAL)
-    YYACCEPT;
-
   /* Count tokens shifted since error; after three, turn off error
      status.  */
   if (yyerrstatus)
   /* Count tokens shifted since error; after three, turn off error
      status.  */
   if (yyerrstatus)
@@ -1224,9 +1224,8 @@ yybackup:
   /* Shift the lookahead token.  */
   YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
 
   /* Shift the lookahead token.  */
   YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
 
-  /* Discard the shifted token unless it is eof.  */
-  if (yychar != YYEOF)
-    yychar = YYEMPTY;
+  /* Discard the shifted token.  */
+  yychar = YYEMPTY;
 
   yystate = yyn;
   *++yyvsp = yylval;
 
   yystate = yyn;
   *++yyvsp = yylval;
@@ -1418,9 +1417,6 @@ yyerrlab1:
       YY_STACK_PRINT (yyss, yyssp);
     }
 
       YY_STACK_PRINT (yyss, yyssp);
     }
 
-  if (yyn == YYFINAL)
-    YYACCEPT;
-
   *++yyvsp = yylval;
 ]b4_locations_if([[
   yyerror_range[1] = yylloc;
   *++yyvsp = yylval;
 ]b4_locations_if([[
   yyerror_range[1] = yylloc;
@@ -1461,7 +1457,7 @@ yyexhaustedlab:
 #endif
 
 yyreturn:
 #endif
 
 yyreturn:
-  if (yychar != YYEOF && yychar != YYEMPTY)
+  if (yychar != YYEMPTY)
      yydestruct ("Cleanup: discarding lookahead",
                 yytoken, &yylval]b4_locations_if([, &yylloc])[]b4_user_args[);
   /* Do not reclaim the symbols of the rule which action triggered
      yydestruct ("Cleanup: discarding lookahead",
                 yytoken, &yylval]b4_locations_if([, &yylloc])[]b4_user_args[);
   /* Do not reclaim the symbols of the rule which action triggered
index 800ecc227876b0b060551ca804c3152a67e13c55..928be1b85e89d1e5f4c6e16c77336a28bcc68293 100644 (file)
@@ -488,7 +488,11 @@ packgram (void)
         rule.  Thus, the midrule actions have already been scanned in order to
         set `used' flags for this rule's rhs, so grammar_rule_check will work
         properly.  */
         rule.  Thus, the midrule actions have already been scanned in order to
         set `used' flags for this rule's rhs, so grammar_rule_check will work
         properly.  */
-      grammar_rule_check (p);
+      /* Don't check the generated rule 0.  It has no action, so some rhs
+        symbols may appear unused, but the parsing algorithm ensures that
+        %destructor's are invoked appropriately.  */
+      if (p != grammar)
+       grammar_rule_check (p);
 
       for (p = p->next; p && p->sym; p = p->next)
        {
 
       for (p = p->next; p && p->sym; p = p->next)
        {
index 6267b74e782d538bf7e0ff33e1d9be0a2f12f50e..2a2bce75a7d44064edb8469b098b334494dc1618 100644 (file)
@@ -197,8 +197,9 @@ AT_LALR1_CC_IF([typedef yy::location YYLTYPE;
 ]AT_LALR1_CC_IF([], [static void yyerror (const char *msg);])
 [}
 
 ]AT_LALR1_CC_IF([], [static void yyerror (const char *msg);])
 [}
 
-]m4_ifval([$6], [%type <ival> '(' 'x' 'y' ')' ';' thing line input])[
+]m4_ifval([$6], [%type <ival> '(' 'x' 'y' ')' ';' thing line input END])[
 
 
+/* FIXME: This %printer isn't actually tested.  */
 %printer
   {
     ]AT_LALR1_CC_IF([debug_stream () << $$;],
 %printer
   {
     ]AT_LALR1_CC_IF([debug_stream () << $$;],
@@ -226,6 +227,11 @@ AT_LALR1_CC_IF([typedef yy::location YYLTYPE;
   { printf ("Freeing token 'y' (%d@%d-%d)\n", $$, RANGE (@$)); }
   'y'
 
   { printf ("Freeing token 'y' (%d@%d-%d)\n", $$, RANGE (@$)); }
   'y'
 
+%token END 0
+%destructor
+  { printf ("Freeing token END (%d@%d-%d)\n", $$, RANGE (@$)); }
+  END
+
 %%
 /*
    This grammar is made to exercise error recovery.
 %%
 /*
    This grammar is made to exercise error recovery.
@@ -241,7 +247,7 @@ input:
       printf ("input (%d@%d-%d): /* Nothing */\n", $$, RANGE (@$));
     }
 | line input /* Right recursive to load the stack so that popping at
       printf ("input (%d@%d-%d): /* Nothing */\n", $$, RANGE (@$));
     }
 | line input /* Right recursive to load the stack so that popping at
-               EOF can be exercised.  */
+               END can be exercised.  */
     {
       $$ = 2;
       printf ("input (%d@%d-%d): line (%d@%d-%d) input (%d@%d-%d)\n",
     {
       $$ = 2;
       printf ("input (%d@%d-%d): line (%d@%d-%d) input (%d@%d-%d)\n",
@@ -308,7 +314,7 @@ yylex (]AT_LEX_FORMALS[)
   if (source[c])
     printf ("sending: '%c'", source[c]);
   else
   if (source[c])
     printf ("sending: '%c'", source[c]);
   else
-    printf ("sending: EOF");
+    printf ("sending: END");
   printf (" (%d@%d-%d)\n", c, RANGE (]AT_LOC[));
   return source[c];
 }
   printf (" (%d@%d-%d)\n", c, RANGE (]AT_LOC[));
   return source[c];
 }
@@ -372,9 +378,10 @@ sending: 'x' (1@10-19)
 thing (1@10-19): 'x' (1@10-19)
 sending: ')' (2@20-29)
 line (0@0-29): '(' (0@0-9) thing (1@10-19) ')' (2@20-29)
 thing (1@10-19): 'x' (1@10-19)
 sending: ')' (2@20-29)
 line (0@0-29): '(' (0@0-9) thing (1@10-19) ')' (2@20-29)
-sending: EOF (3@30-39)
+sending: END (3@30-39)
 input (0@29-29): /* Nothing */
 input (2@0-29): line (0@0-29) input (0@29-29)
 input (0@29-29): /* Nothing */
 input (2@0-29): line (0@0-29) input (0@29-29)
+Freeing token END (3@30-39)
 Freeing nterm input (2@0-29)
 Successful parse.
 ]])
 Freeing nterm input (2@0-29)
 Successful parse.
 ]])
@@ -391,9 +398,10 @@ sending: 'y' (1@10-19)
 Freeing token 'y' (1@10-19)
 sending: ')' (2@20-29)
 line (-1@0-29): '(' (0@0-9) error (@10-19) ')' (2@20-29)
 Freeing token 'y' (1@10-19)
 sending: ')' (2@20-29)
 line (-1@0-29): '(' (0@0-9) error (@10-19) ')' (2@20-29)
-sending: EOF (3@30-39)
+sending: END (3@30-39)
 input (0@29-29): /* Nothing */
 input (2@0-29): line (-1@0-29) input (0@29-29)
 input (0@29-29): /* Nothing */
 input (2@0-29): line (-1@0-29) input (0@29-29)
+Freeing token END (3@30-39)
 Freeing nterm input (2@0-29)
 Successful parse.
 ]])
 Freeing nterm input (2@0-29)
 Successful parse.
 ]])
@@ -445,12 +453,45 @@ input (0@129-129): /* Nothing */
 input (2@100-129): line (10@100-129) input (0@129-129)
 input (2@70-129): line (7@70-99) input (2@100-129)
 input (2@0-129): line (-1@0-69) input (2@70-129)
 input (2@100-129): line (10@100-129) input (0@129-129)
 input (2@70-129): line (7@70-99) input (2@100-129)
 input (2@0-129): line (-1@0-69) input (2@70-129)
-130-139: syntax error, unexpected 'y', expecting $end
+130-139: syntax error, unexpected 'y', expecting END
 Freeing nterm input (2@0-129)
 Freeing token 'y' (13@130-139)
 Parsing FAILED.
 ]])
 
 Freeing nterm input (2@0-129)
 Freeing token 'y' (13@130-139)
 Parsing FAILED.
 ]])
 
+
+# Syntax error caught by the parser where lookahead = END
+# --------------------------------------------------------
+# Load the stack and provoke an error that cannot be caught by the
+# grammar, to check that the stack is cleared.  And make sure the
+# lookahead is freed.
+#
+#     '(', 'x', ')',
+#     '(', 'x', ')',
+#     'x'
+AT_PARSER_CHECK([./input '(x)(x)x'], 1,
+[[sending: '(' (0@0-9)
+sending: 'x' (1@10-19)
+thing (1@10-19): 'x' (1@10-19)
+sending: ')' (2@20-29)
+line (0@0-29): '(' (0@0-9) thing (1@10-19) ')' (2@20-29)
+sending: '(' (3@30-39)
+sending: 'x' (4@40-49)
+thing (4@40-49): 'x' (4@40-49)
+sending: ')' (5@50-59)
+line (3@30-59): '(' (3@30-39) thing (4@40-49) ')' (5@50-59)
+sending: 'x' (6@60-69)
+thing (6@60-69): 'x' (6@60-69)
+sending: END (7@70-79)
+70-79: syntax error, unexpected END, expecting 'x'
+Freeing nterm thing (6@60-69)
+Freeing nterm line (3@30-59)
+Freeing nterm line (0@0-29)
+Freeing token END (7@70-79)
+Parsing FAILED.
+]])
+
+
 # Check destruction upon stack overflow
 # -------------------------------------
 # Upon stack overflow, all symbols on the stack should be destroyed.
 # Check destruction upon stack overflow
 # -------------------------------------
 # Upon stack overflow, all symbols on the stack should be destroyed.