From: Paul Eggert Date: Mon, 15 May 2006 06:13:53 +0000 (+0000) Subject: * data/glr.c (yyreportSyntaxError): Fix off-by-one error in X-Git-Tag: v2.3b~400 X-Git-Url: https://git.saurik.com/bison.git/commitdiff_plain/d6645148013be7c2abb641fcebe68d48af1a3739 * 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 . * 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. --- diff --git a/ChangeLog b/ChangeLog index bd61223b..0b94fe9a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,17 @@ 2006-05-14 Paul Eggert + * 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 + . + * 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. + * data/yacc.c (yytnamerr): Fix typo: local var should be of type YYSIZE_T, not size_t. * tests/regression.at (Trivial grammars): New test, to catch diff --git a/data/glr.c b/data/glr.c index a3a3f49d..0a4b8999 100644 --- a/data/glr.c +++ b/data/glr.c @@ -2077,7 +2077,7 @@ yyreportSyntaxError (yyGLRStack* yystackp]b4_user_formals[) #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* yystackp]b4_user_formals[) 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; diff --git a/data/lalr1.cc b/data/lalr1.cc index 527a8de7..abcdcd5d 100644 --- a/data/lalr1.cc +++ b/data/lalr1.cc @@ -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) diff --git a/data/yacc.c b/data/yacc.c index 61e2fddf..289bee8a 100644 --- a/data/yacc.c +++ b/data/yacc.c @@ -847,7 +847,7 @@ yysyntax_error (char *yyresult, int yystate, int yychar) { 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 yystate, int yychar) 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; diff --git a/tests/regression.at b/tests/regression.at index 5e68b95c..c5ceaf14 100644 --- a/tests/regression.at +++ b/tests/regression.at @@ -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 +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"])