]> git.saurik.com Git - bison.git/commitdiff
GLR parsers sometimes raise parse errors instead of performing the
authorAkim Demaille <akim@epita.fr>
Sun, 13 Oct 2002 14:25:14 +0000 (14:25 +0000)
committerAkim Demaille <akim@epita.fr>
Sun, 13 Oct 2002 14:25:14 +0000 (14:25 +0000)
default reduction.
Reported by Charles-Henry de Boysson.
* tests/calc.at (_AT_CHECK_CALC, _AT_CHECK_CALC_ERROR): Don't
check the length of the traces when %glr.
(_AT_CHECK_CALC_ERROR): Also skip `^Stack' lines, coming from
GLR's traces.
(AT_CHECK_CALC_LALR, AT_CHECK_CALC_GLR): New.
Test GLR parsers.
* data/glr.c (YYLEFTMOST_STATE): Fix its value.
(yyltype): Remove the yy prefix from the member names.
(yytable): Complete its comment.
(yygetLRActions): Map error action number from YYTABLE from
YYTABLE_NINF to 0.
(yyisErrorAction): No longer compare YYACTION to YYPACT_NINF
(which was a bug: it should have been YYTABEL_NINF, and yet it was
not satisfying as we could compare an YYACTION computed from
YYDEFACT to YYTABLE_NINF although they are unrelated): 0 is the
only value for error actions.
(yyreportParseError): In verbose parse error messages, don't issue
`error' in the list of expected tokens.
* data/yacc.c (yyparse) <yybackup>: Rewrite the decoding of the
next action to perform to match glr.c's decoding.
(yytable): Complete its comment.

ChangeLog
NEWS
THANKS
data/glr.c
data/yacc.c
tests/calc.at

index cf9d75a36239cb485461ba40be64f098486eb396..aadd09704d7c78516438c0e9e935bf2e0605bb02 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,31 @@
+2002-10-13  Akim Demaille  <akim@epita.fr>
+
+       GLR parsers sometimes raise parse errors instead of performing the
+       default reduction.
+       Reported by Charles-Henry de Boysson.
+
+       * tests/calc.at (_AT_CHECK_CALC, _AT_CHECK_CALC_ERROR): Don't
+       check the length of the traces when %glr.
+       (_AT_CHECK_CALC_ERROR): Also skip `^Stack' lines, coming from
+       GLR's traces.
+       (AT_CHECK_CALC_LALR, AT_CHECK_CALC_GLR): New.
+       Test GLR parsers.
+       * data/glr.c (YYLEFTMOST_STATE): Fix its value.
+       (yyltype): Remove the yy prefix from the member names.
+       (yytable): Complete its comment.
+       (yygetLRActions): Map error action number from YYTABLE from
+       YYTABLE_NINF to 0.
+       (yyisErrorAction): No longer compare YYACTION to YYPACT_NINF
+       (which was a bug: it should have been YYTABEL_NINF, and yet it was
+       not satisfying as we could compare an YYACTION computed from
+       YYDEFACT to YYTABLE_NINF although they are unrelated): 0 is the
+       only value for error actions.
+       (yyreportParseError): In verbose parse error messages, don't issue
+       `error' in the list of expected tokens.
+       * data/yacc.c (yyparse) <yybackup>: Rewrite the decoding of the
+       next action to perform to match glr.c's decoding.
+       (yytable): Complete its comment.
+
 2002-10-13  Paul Eggert  <eggert@twinsun.com>
 
        Fix problem reported by Henrik Grubbstroem in
 2002-10-13  Paul Eggert  <eggert@twinsun.com>
 
        Fix problem reported by Henrik Grubbstroem in
diff --git a/NEWS b/NEWS
index 699fe44c5b0c84020e253a3d46aa2fdbf3bf5feb..183b129f9840a835f8981a6870270e99d7b9b90d 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,13 @@ Changes in version 1.50a:
 
 * Indonesian translation thanks to Tedi Heriyanto.
 
 
 * Indonesian translation thanks to Tedi Heriyanto.
 
+* GLR parsers
+  Fix spurious parse errors.
+
+* Pure parsers
+  Some people redefine yyerror to steal yyparse' private variables.
+  Reenable this trick until an official feature replaces it.
+
 Changes in version 1.50, 2002-10-04:
 
 * GLR parsing
 Changes in version 1.50, 2002-10-04:
 
 * GLR parsing
diff --git a/THANKS b/THANKS
index 38e7e222e661d0d863f5a97d116090aa60dbde21..85c6a7d85028de9f8406831ae8d840f57b93116e 100644 (file)
--- a/THANKS
+++ b/THANKS
@@ -1,62 +1,63 @@
 Bison was originally written by Robert Corbett.  It would not be what
 it is today without the invaluable help of these people:
 
 Bison was originally written by Robert Corbett.  It would not be what
 it is today without the invaluable help of these people:
 
-Airy Andre             Airy.Andre@edf.fr
-Akim Demaille          akim@freefriends.org
-Albert Chin-A-Young    china@thewrittenword.com
-Alexander Belopolsky   alexb@rentec.com
-Andreas Schwab         schwab@suse.de
-Arnold Robbins         arnold@skeeve.com
-Art Haas                ahaas@neosoft.com
-Benoit Perrot          benoit.perrot@epita.fr
-Bruce Lilly            blilly@erols.com
-Cris Bailiff           c.bailiff+bison@awayweb.com
-Cris van Pelt          cris@amf03054.office.wxs.nl
-Daniel Hagerty         hag@gnu.org
-David J. MacKenzie     djm@gnu.org
-Dick Streefland                dick.streefland@altium.nl
-Enrico Scholz          enrico.scholz@informatik.tu-chemnitz.de
-Evgeny Stambulchik     fnevgeny@plasma-gate.weizmann.ac.il
-Fabrice Bauzac         noon@cote-dazur.com
-Florian Krohm          florian@edamail.fishkill.ibm.com
-H. Merijn Brand                h.m.brand@hccnet.nl
-Hans Aberg             haberg@matematik.su.se
-Jan Nieuwenhuizen       janneke@gnu.org
-Jesse Thilo            jthilo@gnu.org
-Jim Meyering           jim@meyering.net
-Juan Manuel Guerrero   ST001906@HRZ1.HRZ.TU-Darmstadt.De
-Kees Zeelenberg                kzlg@users.sourceforge.net
-Keith Browne           kbrowne@legato.com
-Laurent Mascherpa      laurent.mascherpa@epita.fr
-Magnus Fromreide       magfr@lysator.liu.se
-Marc Autret            autret_m@epita.fr
-Martin Mokrejs          mmokrejs@natur.cuni.cz
-Matt Kraai             kraai@alumni.cmu.edu
-Michael Hayes          m.hayes@elec.canterbury.ac.nz
-Mike Castle            dalgoda@ix.netcom.com
-Neil Booth             NeilB@earthling.net
-Nelson H. F. Beebe     beebe@math.utah.edu
-Nicolas Burrus         nicolas.burrus@epita.fr
-Nicolas Tisserand      nicolas.tisserand@epita.fr
-Noah Friedman          friedman@gnu.org
-Pascal Bart            pascal.bart@epita.fr
-Paul Eggert            eggert@twinsun.com
-Paul Hilfinger         Hilfinger@CS.Berkeley.EDU
-Per Allansson          per@appgate.com
-Peter Hámorský         hamo@upjs.sk
-Piotr Gackiewicz       gacek@intertel.com.pl
-R Blake                        blakers@mac.com
-Raja R Harinath                harinath@cs.umn.edu
-Richard Stallman       rms@gnu.org
-Robert Anisko          anisko_r@epita.fr
-Shura                  debil_urod@ngs.ru
-Tim Josling            tej@melbpc.org.au
-Tom Lane               tgl@sss.pgh.pa.us
-Tom Tromey             tromey@cygnus.com
-Wayne Green            wayne@infosavvy.com
-Wolfram Wagner         ww@mpi-sb.mpg.de
-Wwp                    subscript@free.fr
-Zack Weinberg          zack@codesourcery.com
+Airy Andre                Airy.Andre@edf.fr
+Akim Demaille             akim@freefriends.org
+Albert Chin-A-Young       china@thewrittenword.com
+Alexander Belopolsky      alexb@rentec.com
+Andreas Schwab            schwab@suse.de
+Arnold Robbins            arnold@skeeve.com
+Art Haas                  ahaas@neosoft.com
+Benoit Perrot             benoit.perrot@epita.fr
+Bruce Lilly               blilly@erols.com
+Charles-Henri de Boysson  deboys_c@epita.fr
+Cris Bailiff              c.bailiff+bison@awayweb.com
+Cris van Pelt             cris@amf03054.office.wxs.nl
+Daniel Hagerty            hag@gnu.org
+David J. MacKenzie        djm@gnu.org
+Dick Streefland           dick.streefland@altium.nl
+Enrico Scholz             enrico.scholz@informatik.tu-chemnitz.de
+Evgeny Stambulchik        fnevgeny@plasma-gate.weizmann.ac.il
+Fabrice Bauzac            noon@cote-dazur.com
+Florian Krohm             florian@edamail.fishkill.ibm.com
+H. Merijn Brand           h.m.brand@hccnet.nl
+Hans Aberg                haberg@matematik.su.se
+Jan Nieuwenhuizen         janneke@gnu.org
+Jesse Thilo               jthilo@gnu.org
+Jim Meyering              jim@meyering.net
+Juan Manuel Guerrero      ST001906@HRZ1.HRZ.TU-Darmstadt.De
+Kees Zeelenberg           kzlg@users.sourceforge.net
+Keith Browne              kbrowne@legato.com
+Laurent Mascherpa         laurent.mascherpa@epita.fr
+Magnus Fromreide          magfr@lysator.liu.se
+Marc Autret               autret_m@epita.fr
+Martin Mokrejs            mmokrejs@natur.cuni.cz
+Matt Kraai                kraai@alumni.cmu.edu
+Michael Hayes             m.hayes@elec.canterbury.ac.nz
+Mike Castle               dalgoda@ix.netcom.com
+Neil Booth                NeilB@earthling.net
+Nelson H. F. Beebe        beebe@math.utah.edu
+Nicolas Burrus            nicolas.burrus@epita.fr
+Nicolas Tisserand         nicolas.tisserand@epita.fr
+Noah Friedman             friedman@gnu.org
+Pascal Bart               pascal.bart@epita.fr
+Paul Eggert               eggert@twinsun.com
+Paul Hilfinger            Hilfinger@CS.Berkeley.EDU
+Per Allansson             per@appgate.com
+Peter Hámorský            hamo@upjs.sk
+Piotr Gackiewicz          gacek@intertel.com.pl
+R Blake                   blakers@mac.com
+Raja R Harinath           harinath@cs.umn.edu
+Richard Stallman          rms@gnu.org
+Robert Anisko             anisko_r@epita.fr
+Shura                     debil_urod@ngs.ru
+Tim Josling               tej@melbpc.org.au
+Tom Lane                  tgl@sss.pgh.pa.us
+Tom Tromey                tromey@cygnus.com
+Wayne Green               wayne@infosavvy.com
+Wolfram Wagner            ww@mpi-sb.mpg.de
+Wwp                       subscript@free.fr
+Zack Weinberg             zack@codesourcery.com
 
 Many people are not named here because we lost track of them.  We
 thank them!  Please, help us keeping this list up to date.
 
 Many people are not named here because we lost track of them.  We
 thank them!  Please, help us keeping this list up to date.
index 0868f0256147a9fcf50c848c40232dc72308e948..a9573ed776539755e18ac0ea91d79c5ad937a5b3 100644 (file)
@@ -169,10 +169,10 @@ typedef union b4_stype yystype;
 typedef struct yyltype
 {
 ]b4_location_if([
 typedef struct yyltype
 {
 ]b4_location_if([
-  int yyfirst_line;
-  int yyfirst_column;
-  int yylast_line;
-  int yylast_column;])[
+  int first_line;
+  int first_column;
+  int last_line;
+  int last_column;])[
 } yyltype;
 # define YYLTYPE ]b4_ltype[
 # define YYLTYPE_IS_TRIVIAL 1
 } yyltype;
 # define YYLTYPE ]b4_ltype[
 # define YYLTYPE_IS_TRIVIAL 1
@@ -333,7 +333,8 @@ static const ]b4_int_type_for([b4_pgoto])[ yypgoto[] =
 
 /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
    positive, shift that token.  If negative, reduce the rule which
 
 /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
    positive, shift that token.  If negative, reduce the rule which
-   number is the opposite.  If zero, do what YYDEFACT says.  */
+   number is the opposite.  If zero, do what YYDEFACT says.
+   If YYTABLE_NINF, parse error.  */
 #define YYTABLE_NINF ]b4_table_ninf[
 static const ]b4_int_type_for([b4_table])[ yytable[] =
 {
 #define YYTABLE_NINF ]b4_table_ninf[
 static const ]b4_int_type_for([b4_table])[ yytable[] =
 {
@@ -396,10 +397,10 @@ int yyparse (void);
 
 #ifndef YYLLOC_DEFAULT
 # define YYLLOC_DEFAULT(yyCurrent, yyRhs, YYN)                 \
 
 #ifndef YYLLOC_DEFAULT
 # define YYLLOC_DEFAULT(yyCurrent, yyRhs, YYN)                 \
-  yyCurrent.yyfirst_line   = YYRHSLOC(yyRhs,1).yyfirst_line;   \
-  yyCurrent.yyfirst_column = YYRHSLOC(yyRhs,1).yyfirst_column; \
-  yyCurrent.yylast_line    = YYRHSLOC(yyRhs,YYN).yylast_line;  \
-  yyCurrent.yylast_column  = YYRHSLOC(yyRhs,YYN).yylast_column;
+  yyCurrent.first_line   = YYRHSLOC(yyRhs,1).first_line;       \
+  yyCurrent.first_column = YYRHSLOC(yyRhs,1).first_column;     \
+  yyCurrent.last_line    = YYRHSLOC(yyRhs,YYN).last_line;      \
+  yyCurrent.last_column  = YYRHSLOC(yyRhs,YYN).last_column;
 #endif
 
 /* YYLEX -- calling `yylex' with the right arguments.  */
 #endif
 
 /* YYLEX -- calling `yylex' with the right arguments.  */
@@ -705,16 +706,21 @@ yygetLRActions (yyStateNum yystate, int yytoken,
                int* yyaction, const short** yyconflicts)
 {
   int yyindex = yypact[yystate] + yytoken;
                int* yyaction, const short** yyconflicts)
 {
   int yyindex = yypact[yystate] + yytoken;
-  if (yyindex < 0 || yyindex > YYLAST || yycheck[yyindex] != yytoken)
+  if (yyindex < 0 || YYLAST < yyindex || yycheck[yyindex] != yytoken)
     {
       *yyaction = -yydefact[yystate];
       *yyconflicts = yyconfl;
     }
     {
       *yyaction = -yydefact[yystate];
       *yyconflicts = yyconfl;
     }
-  else
+  else if (yytable[yyindex] != YYTABLE_NINF)
     {
       *yyaction = yytable[yyindex];
       *yyconflicts = yyconfl + yyconflp[yyindex];
     }
     {
       *yyaction = yytable[yyindex];
       *yyconflicts = yyconfl + yyconflp[yyindex];
     }
+  else
+    {
+      *yyaction = 0;
+      *yyconflicts = yyconfl + yyconflp[yyindex];
+    }
 }
 
 static inline yyStateNum
 }
 
 static inline yyStateNum
@@ -722,7 +728,7 @@ yyLRgotoState (yyStateNum yystate, yySymbol yylhs)
 {
   int yyr;
   yyr = yypgoto[yylhs - YYNTOKENS] + yystate;
 {
   int yyr;
   yyr = yypgoto[yylhs - YYNTOKENS] + yystate;
-  if (yyr >= 0 && yyr <= YYLAST && yycheck[yyr] == yystate)
+  if (0 <= yyr && yyr <= YYLAST && yycheck[yyr] == yystate)
     return yytable[yyr];
   else
     return yydefgoto[yylhs - YYNTOKENS];
     return yytable[yyr];
   else
     return yydefgoto[yylhs - YYNTOKENS];
@@ -737,7 +743,7 @@ yyisShiftAction (int yyaction)
 static inline bool
 yyisErrorAction (int yyaction)
 {
 static inline bool
 yyisErrorAction (int yyaction)
 {
-  return yyaction == 0 || yyaction == YYPACT_NINF;
+  return yyaction == 0;
 }
 
                                /* GLRStates */
 }
 
                                /* GLRStates */
@@ -1256,7 +1262,7 @@ yyresolveAction (yySemanticOption* yyopt, yyGLRStack* yystack,
 }
 
 #if YYDEBUG
 }
 
 #if YYDEBUG
-static yyGLRState YYLEFTMOST_STATE = { 0, NULL, -1, 0, { NULL } };
+static yyGLRState YYLEFTMOST_STATE = { 0, 0, -1, NULL, 0, { NULL } };
 
 static void yyreportTree (yySemanticOption* yyx, int yyindent)
 {
 
 static void yyreportTree (yySemanticOption* yyx, int yyindent)
 {
@@ -1524,7 +1530,7 @@ yyreportParseError (yyGLRStack* yystack, YYSTYPE* yylvalp, YYLTYPE* yyllocp)
            {
              yyprefix = ", expecting ";
              for (yyx = yyn < 0 ? -yyn : 0; yyx < yytname_size; yyx += 1)
            {
              yyprefix = ", expecting ";
              for (yyx = yyn < 0 ? -yyn : 0; yyx < yytname_size; yyx += 1)
-               if (yycheck[yyx + yyn] == yyx)
+               if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
                  {
                    yyp += sprintf (yyp, "%s%s", yyprefix, yytokenName (yyx));
                    yyprefix = " or ";
                  {
                    yyp += sprintf (yyp, "%s%s", yyprefix, yytokenName (yyx));
                    yyprefix = " or ";
@@ -1540,13 +1546,9 @@ yyreportParseError (yyGLRStack* yystack, YYSTYPE* yylvalp, YYLTYPE* yyllocp)
     }
 }
 
     }
 }
 
-/* Recover from a syntax error on STACK, assuming that TOKENP,
+/* Recover from a syntax error on YYSTACK, assuming that YYTOKENP,
    YYLVALP, and YYLLOCP point to the syntactic category, semantic
    YYLVALP, and YYLLOCP point to the syntactic category, semantic
-   value, and location of the lookahead.
-   NOTE: This uses the panic-mode recovery algorithm described in the
-   Bison documentation, which differs from what is in bison.simple.
-   Specifically, this routine performs no reductions before shifting
-   the error token. */
+   value, and location of the lookahead.  */
 static void
 yyrecoverParseError (yyGLRStack* yystack, YYSTYPE* yylvalp, YYLTYPE* yyllocp)
 {
 static void
 yyrecoverParseError (yyGLRStack* yystack, YYSTYPE* yylvalp, YYLTYPE* yyllocp)
 {
@@ -1855,10 +1857,10 @@ b4_location_if(
 [#ifndef YYLTYPE
 typedef struct yyltype
 {
 [#ifndef YYLTYPE
 typedef struct yyltype
 {
-  int yyfirst_line;
-  int yyfirst_column;
-  int yylast_line;
-  int yylast_column;
+  int first_line;
+  int first_column;
+  int last_line;
+  int last_column;
 } yyltype;
 # define YYLTYPE yyltype
 #endif
 } yyltype;
 # define YYLTYPE yyltype
 #endif
index 31ee8436c85111bbd88ea622c91ad34208ec8ebf..f3dcfab47d37165adaeb89846fc14ae1752d502a 100644 (file)
@@ -414,7 +414,8 @@ static const b4_int_type_for([b4_pgoto]) yypgoto[[]] =
 
 /* YYTABLE[[YYPACT[STATE-NUM]]].  What to do in state STATE-NUM.  If
    positive, shift that token.  If negative, reduce the rule which
 
 /* YYTABLE[[YYPACT[STATE-NUM]]].  What to do in state STATE-NUM.  If
    positive, shift that token.  If negative, reduce the rule which
-   number is the opposite.  If zero, do what YYDEFACT says.  */
+   number is the opposite.  If zero, do what YYDEFACT says.
+   If YYTABLE_NINF, parse error.  */
 #define YYTABLE_NINF b4_table_ninf
 static const b4_int_type_for([b4_table]) yytable[[]] =
 {
 #define YYTABLE_NINF b4_table_ninf
 static const b4_int_type_for([b4_table]) yytable[[]] =
 {
@@ -917,23 +918,22 @@ yybackup:
       YYDPRINTF ((stderr, "\n"));
     }
 
       YYDPRINTF ((stderr, "\n"));
     }
 
+  /* Set YYN to the action to take in STATE on seeing token YYCHAR1.
+     Result YYN means
+     - YYN < 0:  Reduce on rule -YYN.
+     - YYN = 0:  Error.
+     - YYN > 0:  Shift to state YYN.  */
   yyn += yychar1;
   if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yychar1)
   yyn += yychar1;
   if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yychar1)
-    goto yydefault;
-
-  yyn = yytable[yyn];
-
-  /* yyn is what to do for this token type in this state.
-     Negative => reduce, -yyn is rule number.
-     Positive => shift, yyn is new state.
-       New state is final state => don't bother to shift,
-       just return success.
-     0, or most negative number => error.  */
+    /* Defaulted action (reduction).  */
+    yyn = -yydefact[yystate];
+  else if (yytable[yyn] != YYTABLE_NINF)
+    yyn = yytable[yyn];
+  else
+    yyn = 0;
 
   if (yyn < 0)
     {
 
   if (yyn < 0)
     {
-      if (yyn == YYTABLE_NINF)
-       goto yyerrlab;
       yyn = -yyn;
       goto yyreduce;
     }
       yyn = -yyn;
       goto yyreduce;
     }
index 8875f9cd1ad407071551dd455d19b5353bc50695..63c8604b16ae8e255bc8d1b9fcbe9558e07b53fc 100644 (file)
@@ -16,8 +16,6 @@
 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 # 02111-1307, USA.
 
 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 # 02111-1307, USA.
 
-AT_BANNER([[Simple Calculator.]])
-
 ## ---------------------------------------------------- ##
 ## Compile the grammar described in the documentation.  ##
 ## ---------------------------------------------------- ##
 ## ---------------------------------------------------- ##
 ## Compile the grammar described in the documentation.  ##
 ## ---------------------------------------------------- ##
@@ -275,8 +273,8 @@ main (int argc, const char **argv)
 # Produce `calc.y'.
 m4_define([AT_DATA_CALC_Y],
 [_AT_DATA_CALC_Y($[1], $[2], $[3],
 # Produce `calc.y'.
 m4_define([AT_DATA_CALC_Y],
 [_AT_DATA_CALC_Y($[1], $[2], $[3],
-                 [m4_bmatch([$1], [--yyerror-verbose],
-                            [[%error-verbose]])])])
+                 [m4_bpatsubst([$1], [--[^ ]*])])
+])
 
 
 
 
 
 
@@ -284,17 +282,22 @@ m4_define([AT_DATA_CALC_Y],
 # ------------------------------------------------------------
 # Run `calc' on INPUT and expect no STDOUT nor STDERR.
 #
 # ------------------------------------------------------------
 # Run `calc' on INPUT and expect no STDOUT nor STDERR.
 #
-# If BISON-OPTIONS contains `--debug', then NUM-STDERR-LINES is the number
-# of expected lines on stderr.
+# If BISON-OPTIONS contains `%debug' but not `%glr-parser', then
+# NUM-STDERR-LINES is the number of expected lines on stderr.
+#
+# We don't count GLR's traces yet, since its traces are somewhat
+# different from LALR's.
 m4_define([_AT_CHECK_CALC],
 [AT_DATA([[input]],
 [[$2
 ]])
 m4_define([_AT_CHECK_CALC],
 [AT_DATA([[input]],
 [[$2
 ]])
-AT_PARSER_CHECK([./calc input], 0, [], [stderr])dnl
-AT_CHECK([wc -l <stderr | sed 's/[[^0-9]]//g'], 0,
-         [m4_bmatch([$1], [--debug],
-                    [$3], [0])
-])
+AT_PARSER_CHECK([./calc input], 0, [], [stderr])
+m4_bmatch([$1],
+  [%debug.*%glr\|%glr.*%debug],
+     [],
+  [%debug],
+     [AT_CHECK([wc -l <stderr | sed 's/[[^0-9]]//g'], 0, [$3
+])])
 ])
 
 
 ])
 
 
@@ -309,12 +312,12 @@ AT_CHECK([wc -l <stderr | sed 's/[[^0-9]]//g'], 0,
 # If BISON-OPTIONS contains `--location', then make sure the ERROR-LOCATION
 # is correctly output on stderr.
 #
 # If BISON-OPTIONS contains `--location', then make sure the ERROR-LOCATION
 # is correctly output on stderr.
 #
-# If BISON-OPTIONS contains `--yyerror-verbose', then make sure the
+# If BISON-OPTIONS contains `%error-verbose', then make sure the
 # IF-YYERROR-VERBOSE message is properly output after `parse error, '
 # on STDERR.
 #
 # IF-YYERROR-VERBOSE message is properly output after `parse error, '
 # on STDERR.
 #
-# If BISON-OPTIONS contains `--debug', then NUM-STDERR-LINES is the number
-# of expected lines on stderr.
+# If BISON-OPTIONS contains `%debug' but not `%glr', then NUM-STDERR-LINES
+# is the number of expected lines on stderr.
 m4_define([_AT_CHECK_CALC_ERROR],
 [m4_bmatch([$2], [^/],
            [AT_PARSER_CHECK([./calc $2], 0, [], [stderr])],
 m4_define([_AT_CHECK_CALC_ERROR],
 [m4_bmatch([$2], [^/],
            [AT_PARSER_CHECK([./calc $2], 0, [], [stderr])],
@@ -322,9 +325,11 @@ m4_define([_AT_CHECK_CALC_ERROR],
 [[$2
 ]])
 AT_PARSER_CHECK([./calc input], 0, [], [stderr])])
 [[$2
 ]])
 AT_PARSER_CHECK([./calc input], 0, [], [stderr])])
-
-m4_bmatch([$1], [--debug],
-[AT_CHECK([wc -l <stderr | sed 's/[[^0-9]]//g'], 0, [$3
+m4_bmatch([$1],
+  [%debug.*%glr\|%glr.*%debug],
+     [],
+  [%debug],
+     [AT_CHECK([wc -l <stderr | sed 's/[[^0-9]]//g'], 0, [$3
 ])])
 
 # Normalize the observed and expected error messages, depending upon the
 ])])
 
 # Normalize the observed and expected error messages, depending upon the
@@ -332,6 +337,7 @@ m4_bmatch([$1], [--debug],
 # 1. Remove the traces from observed.
 sed '/^Starting/d
 /^Entering/d
 # 1. Remove the traces from observed.
 sed '/^Starting/d
 /^Entering/d
+/^Stack/d
 /^Reading/d
 /^Reducing/d
 /^Shifting/d
 /^Reading/d
 /^Reducing/d
 /^Shifting/d
@@ -350,7 +356,7 @@ m4_bmatch([$1], [--location], [],
 [[sed 's/^[-0-9.]*: //' expout >at-expout
 mv at-expout expout]])
 # 4. If error-verbose is not used, strip the`, unexpected....' part.
 [[sed 's/^[-0-9.]*: //' expout >at-expout
 mv at-expout expout]])
 # 4. If error-verbose is not used, strip the`, unexpected....' part.
-m4_bmatch([$1], [--yyerror-verbose], [],
+m4_bmatch([$1], [%error-verbose], [],
 [[sed 's/parse error, .*$/parse error/' expout >at-expout
 mv at-expout expout]])
 # 5. Check
 [[sed 's/parse error, .*$/parse error/' expout >at-expout
 mv at-expout expout]])
 # 5. Check
@@ -358,8 +364,8 @@ AT_CHECK([cat stderr], 0, [expout])
 ])
 
 
 ])
 
 
-# AT_CHECK_CALC([BISON-OPTIONS], [PARSER-EXPECTED-STDERR])
-# --------------------------------------------------------
+# AT_CHECK_CALC([BISON-OPTIONS])
+# ------------------------------
 # Start a testing chunk which compiles `calc' grammar with
 # BISON-OPTIONS, and performs several tests over the parser.
 m4_define([AT_CHECK_CALC],
 # Start a testing chunk which compiles `calc' grammar with
 # BISON-OPTIONS, and performs several tests over the parser.
 m4_define([AT_CHECK_CALC],
@@ -369,7 +375,7 @@ AT_SETUP([Calculator $1])
 AT_DATA_CALC_Y([$1])
 
 # Specify the output files to avoid problems on different file systems.
 AT_DATA_CALC_Y([$1])
 
 # Specify the output files to avoid problems on different file systems.
-AT_CHECK([bison calc.y -o calc.c m4_bpatsubst([$1], [--yyerror-verbose])],
+AT_CHECK([bison calc.y -o calc.c m4_bpatsubst([$1], [%[^ ]*])],
          [0], [], [])
 
 AT_COMPILE([calc])
          [0], [], [])
 
 AT_COMPILE([calc])
@@ -427,22 +433,62 @@ AT_CLEANUP
 
 
 
 
 
 
-# ------------------ #
-# Test the parsers.  #
-# ------------------ #
+# ------------------------ #
+# Simple LALR Calculator.  #
+# ------------------------ #
+
+AT_BANNER([[Simple LALR Calculator.]])
+
+# AT_CHECK_CALC_LALR([BISON-OPTIONS])
+# -----------------------------------
+# Start a testing chunk which compiles `calc' grammar with
+# BISON-OPTIONS, and performs several tests over the parser.
+m4_define([AT_CHECK_CALC_LALR],
+[AT_CHECK_CALC($@)])
+
+AT_CHECK_CALC_LALR()
+
+AT_CHECK_CALC_LALR([--defines])
+AT_CHECK_CALC_LALR([--locations])
+AT_CHECK_CALC_LALR([--name-prefix=calc])
+AT_CHECK_CALC_LALR([--verbose])
+AT_CHECK_CALC_LALR([--yacc])
+AT_CHECK_CALC_LALR([%error-verbose])
+
+AT_CHECK_CALC_LALR([%error-verbose --locations])
+
+AT_CHECK_CALC_LALR([%error-verbose --defines --locations --name-prefix=calc --verbose --yacc])
+
+AT_CHECK_CALC_LALR([%debug])
+AT_CHECK_CALC_LALR([%error-verbose %debug --defines --locations --name-prefix=calc --verbose --yacc])
+
+
+# ----------------------- #
+# Simple GLR Calculator.  #
+# ----------------------- #
+
+AT_BANNER([[Simple GLR Calculator.]])
+
+# AT_CHECK_CALC_GLR([BISON-OPTIONS])
+# ----------------------------------
+# Start a testing chunk which compiles `calc' grammar with
+# BISON-OPTIONS and %glr-parser, and performs several tests over the parser.
+m4_define([AT_CHECK_CALC_GLR],
+[AT_CHECK_CALC([%glr_parser] $@)])
+
 
 
-AT_CHECK_CALC()
+AT_CHECK_CALC_GLR()
 
 
-AT_CHECK_CALC([--defines])
-AT_CHECK_CALC([--locations])
-AT_CHECK_CALC([--name-prefix=calc])
-AT_CHECK_CALC([--verbose])
-AT_CHECK_CALC([--yacc])
-AT_CHECK_CALC([--yyerror-verbose])
+AT_CHECK_CALC_GLR([--defines])
+AT_CHECK_CALC_GLR([--locations])
+AT_CHECK_CALC_GLR([--name-prefix=calc])
+AT_CHECK_CALC_GLR([--verbose])
+AT_CHECK_CALC_GLR([--yacc])
+AT_CHECK_CALC_GLR([%error-verbose])
 
 
-AT_CHECK_CALC([--locations --yyerror-verbose])
+AT_CHECK_CALC_GLR([%error-verbose --locations])
 
 
-AT_CHECK_CALC([--defines --locations --name-prefix=calc --verbose --yacc --yyerror-verbose])
+AT_CHECK_CALC_GLR([%error-verbose --defines --locations --name-prefix=calc --verbose --yacc])
 
 
-AT_CHECK_CALC([--debug])
-AT_CHECK_CALC([--debug --defines --locations --name-prefix=calc --verbose --yacc --yyerror-verbose])
+AT_CHECK_CALC_GLR([%debug])
+AT_CHECK_CALC_GLR([%error-verbose %debug --defines --locations --name-prefix=calc --verbose --yacc])