bison-patches
[Top][All Lists]
Advanced

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

yacc.c fix for parser loops (glr.c and lalr1.cc are still broken)


From: Paul Eggert
Subject: yacc.c fix for parser loops (glr.c and lalr1.cc are still broken)
Date: Sun, 1 Jun 2003 21:16:19 -0700 (PDT)

I installed the following patch.  If you build CVS Bison, the GLR and
lalr1.cc tests all fail now, since they all test the for the bug in
question, and the GLR and lalr1.cc code still has the bug.

2003-06-01  Paul Eggert  <address@hidden>

        Follow up on a bug I reported in February, where a Bison-generated
        parser can loop.  Provide a test case and a fix for yacc.c.  I
        don't have a fix for lalr1.cc or for glr.c, unfortunately.
        The original bug report is in:
        <http://mail.gnu.org/archive/html/bison-patches/2003-02/msg00044.html>
        
        * data/yacc.c (YYERROR): Now just 'goto yyerrorlab', since the
        macro's size was becoming unwieldy.
        (yyerrlab): Do not discard an empty lookahead symbol, as this
        might destroy garbage.
        (yyerrorlab): New label, with the old contents of YYERROR,
        plus the following change: pop the stack of rhs corresponding
        to the production that invoked YYERROR.  That is how Yacc
        behaves, and POSIX requires this behavior.
        (yyerrlab1): Use YYPOPSTACK instead of its definiens.
        * tests/calc.at (_AT_DATA_CALC_Y): Include unistd.h if available.
        Define 'alarm' to do nothing if unistd.h is not available.
        Add a new rule "exp: '-' error;" to test the above change to
        data/yacc.c.  Use 'alarm' to abort any test taking longer than
        10 seconds, as it's probably looping.
        (AT_CHECK_CALC): Test recovery from error in new grammar rule.
        Also, the new yacc.c generates two fewer diagnostics for an
        existing test.

Index: data/yacc.c
===================================================================
RCS file: /cvsroot/bison/bison/data/yacc.c,v
retrieving revision 1.57
diff -p -u -r1.57 yacc.c
--- data/yacc.c 25 May 2003 06:44:08 -0000      1.57
+++ data/yacc.c 2 Jun 2003 03:44:44 -0000
@@ -466,14 +466,7 @@ static const ]b4_int_type_for([b4_stos])
 
 #define YYACCEPT       goto yyacceptlab
 #define YYABORT                goto yyabortlab
-#define YYERROR                ]b4_location_if([do                             
\
-                         {                             \
-                           yylerrsp = yylsp;           \
-                           *++yylerrsp = yyloc;        \
-                           goto yyerrlab1;             \
-                         }                             \
-                       while (0)],
-                       [goto yyerrlab1])[
+#define YYERROR                goto yyerrorlab
 
 
 /* Like YYERROR except do call yyerror.  This remains here temporarily
@@ -1101,25 +1094,27 @@ yyerrlab:
       /* If just tried and failed to reuse lookahead token after an
         error, discard it.  */
 
-      /* Return failure if at end of input.  */
-      if (yychar == YYEOF)
+      if (yychar <= YYEOF)
         {
-         /* Pop the error token.  */
-          YYPOPSTACK;
-         /* Pop the rest of the stack.  */
-         while (yyss < yyssp)
-           {
-             YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
-             yydestruct (yystos[*yyssp], yyvsp]b4_location_if([, yylsp])[);
-             YYPOPSTACK;
-           }
-         YYABORT;
+          /* If at end of input, pop the error token,
+            then the rest of the stack, then return failure.  */
+         if (yychar == YYEOF)
+            for (;;)
+              {
+                YYPOPSTACK;
+                if (yyssp == yyss)
+                  YYABORT;
+                YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
+                yydestruct (yystos[*yyssp], yyvsp]b4_location_if([, yylsp])[);
+              }
         }
-
-      YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc);
-      yydestruct (yytoken, &yylval]b4_location_if([, &yylloc])[);
-      yychar = YYEMPTY;
-]b4_location_if([      *++yylerrsp = yylloc;])[
+      else
+       {
+         YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc);
+         yydestruct (yytoken, &yylval]b4_location_if([, &yylloc])[);
+         yychar = YYEMPTY;
+]b4_location_if([        *++yylerrsp = yylloc;])[
+       }
     }
 
   /* Else will try to reuse lookahead token after shifting the error
@@ -1127,9 +1122,30 @@ yyerrlab:
   goto yyerrlab1;
 
 
-/*----------------------------------------------------.
-| yyerrlab1 -- error raised explicitly by an action.  |
-`----------------------------------------------------*/
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR.  |
+`---------------------------------------------------*/
+yyerrorlab:
+
+#ifdef __GNUC__
+  /* Pacify GCC when the user code never invokes YYERROR and the label
+     yyerrorlab therefore never appears in user code.  */
+  if (0)
+     goto yyerrorlab;
+#endif
+
+  yyvsp -= yylen;
+  yyssp -= yylen;
+  yystate = *yyssp;
+  ]b4_location_if([yylerrsp = yylsp;
+  *++yylerrsp = yyloc;
+  yylsp -= yylen;
+  ])[goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR.  |
+`-------------------------------------------------------------*/
 yyerrlab1:
   yyerrstatus = 3;     /* Each real token shifted decrements this.  */
 
@@ -1153,9 +1169,8 @@ yyerrlab1:
 
       YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
       yydestruct (yystos[yystate], yyvsp]b4_location_if([, yylsp])[);
-      yyvsp--;
-      yystate = *--yyssp;
-]b4_location_if([      yylsp--;])[
+      YYPOPSTACK;
+      yystate = *yyssp;
       YY_STACK_PRINT (yyss, yyssp);
     }
 
Index: tests/calc.at
===================================================================
RCS file: /cvsroot/bison/bison/tests/calc.at,v
retrieving revision 1.56
diff -p -u -r1.56 calc.at
--- tests/calc.at       14 May 2003 18:41:48 -0000      1.56
+++ tests/calc.at       2 Jun 2003 03:44:45 -0000
@@ -1,4 +1,4 @@
-# Checking the output filenames.                         -*- Autotest -*-
+# Simple calculator.                         -*- Autotest -*-
 # Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
 
 # This program is free software; you can redistribute it and/or modify
@@ -45,6 +45,12 @@ AT_DATA_GRAMMAR([calc.y],
 # include <stdlib.h>
 # include <string.h>
 #endif
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#else
+# undef alarm
+# define alarm(seconds) /* empty */
+#endif
 #include <ctype.h>
 
 extern void perror (const char *s);
@@ -117,6 +123,7 @@ exp:
 | '(' exp ')'        { $$ = $2;             }
 | '(' error ')'      { $$ = 1111;           }
 | '!'                { YYERROR;             }
+| '-' error          { YYERROR;             }
 ;
 %%
 /* The input. */
@@ -303,6 +310,7 @@ main (int argc, const char **argv)
   int count = 0;
   int status;
 
+  alarm (10);
   if (argc == 2)
     yyin = fopen (argv[1], "r");
   else
@@ -503,8 +511,12 @@ calc: error: 4444 != 1])
 
 # The same, but this time exercising explicitly triggered syntax errors.
 # POSIX says the lookahead causing the error should not be discarded.
-_AT_CHECK_CALC_ERROR([$1], [0], [(!) + (0 0) = 1], [64],
+_AT_CHECK_CALC_ERROR([$1], [0], [(!) + (0 0) = 1], [62],
 [1.9: syntax error, unexpected "number"
+calc: error: 2222 != 1])
+_AT_CHECK_CALC_ERROR([$1], [0], [(- *) + (0 0) = 1], [70],
+[1.3: syntax error, unexpected '*', expecting "number" or '-' or '(' or '!'
+1.11: syntax error, unexpected "number"
 calc: error: 2222 != 1])
 AT_BISON_OPTION_POPDEFS
 




reply via email to

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