[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Possible bug simple grammar
From: |
Paul Eggert |
Subject: |
Re: Possible bug simple grammar |
Date: |
Sun, 14 May 2006 23:16:35 -0700 |
User-agent: |
Gnus/5.1008 (Gnus v5.10.8) Emacs/21.4 (gnu/linux) |
Thanks for that bug report. I installed the following patch to fix
the bug.
2006-05-14 Paul Eggert <address@hidden>
* data/glr.c (yyreportSyntaxError): Fix off-by-one error in
checking against YYLAST that caused the parser to miss a potential
alternative in its diagnostic.
Problem reported by Maria Jose Moron Fernandez in
<http://lists.gnu.org/archive/html/bug-bison/2006-05/msg00024.html>.
* data/lalr1.cc (yysyntax_error_): Likewise.
* data/yacc.c (yysyntax_error): Likewise.
* tests/regression.at (_AT_DATA_DANCER_Y): Use static array for
tokens, in case we run into an older C compiler.
(_AT_DATA_EXPECT2_Y, AT_CHECK_EXPECT2): New macros.
Use them to check for the off-by-one error fixed above.
Index: data/glr.c
===================================================================
RCS file: /cvsroot/bison/bison/data/glr.c,v
retrieving revision 1.173
diff -p -u -r1.173 glr.c
--- data/glr.c 14 May 2006 20:40:34 -0000 1.173
+++ data/glr.c 15 May 2006 06:03:11 -0000
@@ -2077,7 +2077,7 @@ yyreportSyntaxError (yyGLRStack* yystack
#if YYERROR_VERBOSE
int yyn;
yyn = yypact[yystackp->yytops.yystates[0]->yylrState];
- if (YYPACT_NINF < yyn && yyn < YYLAST)
+ if (YYPACT_NINF < yyn && yyn <= YYLAST)
{
yySymbol yytoken = YYTRANSLATE (yychar);
size_t yysize0 = yytnamerr (NULL, yytokenName (yytoken));
@@ -2104,7 +2104,7 @@ yyreportSyntaxError (yyGLRStack* yystack
int yyxbegin = yyn < 0 ? -yyn : 0;
/* Stay within bounds of both yycheck and yytname. */
- int yychecklim = YYLAST - yyn;
+ int yychecklim = YYLAST - yyn + 1;
int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
int yycount = 1;
Index: data/lalr1.cc
===================================================================
RCS file: /cvsroot/bison/bison/data/lalr1.cc,v
retrieving revision 1.130
diff -p -u -r1.130 lalr1.cc
--- data/lalr1.cc 14 May 2006 20:48:24 -0000 1.130
+++ data/lalr1.cc 15 May 2006 06:03:11 -0000
@@ -838,14 +838,14 @@ b4_error_verbose_if([, int tok])[)
YYUSE (yystate);
#if YYERROR_VERBOSE
int yyn = yypact_[yystate];
- if (yypact_ninf_ < yyn && yyn < yylast_)
+ if (yypact_ninf_ < yyn && yyn <= yylast_)
{
/* Start YYX at -YYN if negative to avoid negative indexes in
YYCHECK. */
int yyxbegin = yyn < 0 ? -yyn : 0;
/* Stay within bounds of both yycheck and yytname. */
- int yychecklim = yylast_ - yyn;
+ int yychecklim = yylast_ - yyn + 1;
int yyxend = yychecklim < yyntokens_ ? yychecklim : yyntokens_;
int count = 0;
for (int x = yyxbegin; x < yyxend; ++x)
Index: data/yacc.c
===================================================================
RCS file: /cvsroot/bison/bison/data/yacc.c,v
retrieving revision 1.139
diff -p -u -r1.139 yacc.c
--- data/yacc.c 15 May 2006 05:10:06 -0000 1.139
+++ data/yacc.c 15 May 2006 06:03:11 -0000
@@ -847,7 +847,7 @@ yysyntax_error (char *yyresult, int yyst
{
int yyn = yypact[yystate];
- if (! (YYPACT_NINF < yyn && yyn < YYLAST))
+ if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
return 0;
else
{
@@ -885,7 +885,7 @@ yysyntax_error (char *yyresult, int yyst
int yyxbegin = yyn < 0 ? -yyn : 0;
/* Stay within bounds of both yycheck and yytname. */
- int yychecklim = YYLAST - yyn;
+ int yychecklim = YYLAST - yyn + 1;
int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
int yycount = 1;
Index: tests/regression.at
===================================================================
RCS file: /cvsroot/bison/bison/tests/regression.at,v
retrieving revision 1.96
diff -p -u -r1.96 regression.at
--- tests/regression.at 15 May 2006 05:10:06 -0000 1.96
+++ tests/regression.at 15 May 2006 06:03:11 -0000
@@ -824,7 +824,7 @@ static int
yylex (AT_LALR1_CC_IF([int *lval], [void]))
[{
static int toknum = 0;
- int tokens[] =
+ static int tokens[] =
{
':', -1
};
@@ -864,3 +864,100 @@ AT_CLEANUP
AT_CHECK_DANCER()
AT_CHECK_DANCER([%glr-parser])
AT_CHECK_DANCER([%skeleton "lalr1.cc"])
+
+
+## ------------------------------------------ ##
+## Diagnostic that expects two alternatives. ##
+## ------------------------------------------ ##
+
+
+# _AT_DATA_EXPECT2_Y(BISON-OPTIONS)
+# --------------------------------
+m4_define([_AT_DATA_EXPECT2_Y],
+[AT_DATA_GRAMMAR([expect2.y],
+[%{
+static int yylex (AT_LALR1_CC_IF([int *], [void]));
+AT_LALR1_CC_IF([],
+[#include <stdio.h>
+static void yyerror (const char *);])
+%}
+$1
+%defines
+%error-verbose
+%token A 1000
+%token B
+
+%%
+program: /* empty */
+ | program e ';'
+ | program error ';';
+
+e: e '+' t | t;
+t: A | B;
+
+%%
+AT_LALR1_CC_IF(
+[/* A C++ error reporting function. */
+void
+yy::parser::error (const location&, const std::string& m)
+{
+ std::cerr << m << std::endl;
+}
+
+int
+yyparse ()
+{
+ yy::parser parser;
+ return parser.parse ();
+}
+],
+[static void
+yyerror (const char *s)
+{
+ fprintf (stderr, "%s\n", s);
+}])
+
+static int
+yylex (AT_LALR1_CC_IF([int *lval], [void]))
+[{
+ static int toknum = 0;
+ static int tokens[] =
+ {
+ 1000, '+', '+', -1
+ };
+ ]AT_LALR1_CC_IF([*lval = 0; /* Pacify GCC. */])[
+ return tokens[toknum++];
+}]
+
+int
+main (void)
+{
+ return yyparse ();
+}
+])
+])# _AT_DATA_EXPECT2_Y
+
+
+# AT_CHECK_EXPECT2(BISON-OPTIONS)
+# ------------------------------
+# Generate the grammar, compile it, run it.
+m4_define([AT_CHECK_EXPECT2],
+[AT_SETUP([Expecting two tokens $1])
+AT_BISON_OPTION_PUSHDEFS([$1])
+_AT_DATA_EXPECT2_Y([$1])
+AT_CHECK([bison -o expect2.c expect2.y])
+AT_LALR1_CC_IF(
+ [AT_CHECK([bison -o expect2.cc expect2.y])
+ AT_COMPILE_CXX([expect2])],
+ [AT_CHECK([bison -o expect2.c expect2.y])
+ AT_COMPILE([expect2])])
+AT_PARSER_CHECK([./expect2], 1, [],
+[syntax error, unexpected '+', expecting A or B
+])
+AT_BISON_OPTION_POPDEFS
+AT_CLEANUP
+])
+
+AT_CHECK_EXPECT2()
+AT_CHECK_EXPECT2([%glr-parser])
+AT_CHECK_EXPECT2([%skeleton "lalr1.cc"])