* data/c.m4 (b4_identification, b4_user_args, b4_parse_param):
authorAkim Demaille <akim@epita.fr>
Sun, 3 Nov 2002 16:41:57 +0000 (16:41 +0000)
committerAkim Demaille <akim@epita.fr>
Sun, 3 Nov 2002 16:41:57 +0000 (16:41 +0000)
New.
* data/yacc.m4 (b4_pure_args, b4_Pure_args): New.
(b4_parse_param): Remove.
Use b4_identification.
Propagate b4_pure_args where needed to pass them to yyerror.
* data/glr.m4 (b4_parse_param): Remove.
(b4_user_formals, b4_pure_args, b4_pure_formals, b4_lpure_args)
(b4_lpure_formals): New.
Use b4_identification.
(YY_USER_FORMALS, YY_USER_ARGS): Remove, replaced by
b4_user_formals and b4_user_args.
(yyexpandGLRStack, yyFail, yyaddDeferredAction, yyglrShiftDefer)
(yyreportAmbiguity): When using a pure parser, also need
the location, and the parse-params.
Adjust callers.
(yyuserAction, yyglrShift, yyreportParseError, yyrecoverParseError):
When using a pure parser, also need the parse-params.
Adjust callers.
* tests/calc.at: Test pure (%pure-parser) and absolutely pure
(%pure-parser + %parse-param) LALR and GLR parsers.
(AT_CHECK_PUSHDEFS, AT_CHECK_POPDEFS): New, define AT_PARAM_IF,
AT_LOCATION_IF, AT_PURE_IF, AT_GLR_IF, AAT_PURE_AND_LOC_IF,
AT_GLR_OR_PARAM_IF, AT_YYERROR_ARG_LOC_IF, AT_YYERROR_SEES_LOC_IF.
(_AT_DATA_CALC_Y): Equip for purity of yyerror.
(_AT_CHECK_CALC_ERROR): Use AT_YYERROR_SEES_LOC_IF.
* tests/cxx-type.at (_AT_TEST_GLR_CALC): Equip for yyerror purity.
* doc/bison.texinfo: Untabify the whole file.
(Parser Function): Document %parse-param, deprecate YYPARSE_PARAM.
(Pure Calling): Document %lex-param, deprecate YYLEX_PARAM.
(Error Reporting): Adjust to these new directives.
Document %error-verbose, deprecate YYERROR_VERBOSE.

ChangeLog
NEWS
data/c.m4
data/glr.c
data/yacc.c
doc/bison.texinfo
tests/calc.at
tests/cxx-type.at

index 7c5dee4..4b0b8b7 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,40 @@
 2002-11-03  Akim Demaille  <akim@epita.fr>
 
+       * data/c.m4 (b4_identification, b4_user_args, b4_parse_param):
+       New.
+       * data/yacc.m4 (b4_pure_args, b4_Pure_args): New.
+       (b4_parse_param): Remove.
+       Use b4_identification.
+       Propagate b4_pure_args where needed to pass them to yyerror.
+       * data/glr.m4 (b4_parse_param): Remove.
+       (b4_user_formals, b4_pure_args, b4_pure_formals, b4_lpure_args)
+       (b4_lpure_formals): New.
+       Use b4_identification.
+       (YY_USER_FORMALS, YY_USER_ARGS): Remove, replaced by
+       b4_user_formals and b4_user_args.
+       (yyexpandGLRStack, yyFail, yyaddDeferredAction, yyglrShiftDefer)
+       (yyreportAmbiguity): When using a pure parser, also need
+       the location, and the parse-params.
+       Adjust callers.
+       (yyuserAction, yyglrShift, yyreportParseError, yyrecoverParseError):
+       When using a pure parser, also need the parse-params.
+       Adjust callers.
+       * tests/calc.at: Test pure (%pure-parser) and absolutely pure
+       (%pure-parser + %parse-param) LALR and GLR parsers.
+       (AT_CHECK_PUSHDEFS, AT_CHECK_POPDEFS): New, define AT_PARAM_IF,
+       AT_LOCATION_IF, AT_PURE_IF, AT_GLR_IF, AAT_PURE_AND_LOC_IF,
+       AT_GLR_OR_PARAM_IF, AT_YYERROR_ARG_LOC_IF, AT_YYERROR_SEES_LOC_IF.
+       (_AT_DATA_CALC_Y): Equip for purity of yyerror.
+       (_AT_CHECK_CALC_ERROR): Use AT_YYERROR_SEES_LOC_IF.
+       * tests/cxx-type.at (_AT_TEST_GLR_CALC): Equip for yyerror purity.
+       * doc/bison.texinfo: Untabify the whole file.
+       (Parser Function): Document %parse-param, deprecate YYPARSE_PARAM.
+       (Pure Calling): Document %lex-param, deprecate YYLEX_PARAM.
+       (Error Reporting): Adjust to these new directives.
+       Document %error-verbose, deprecate YYERROR_VERBOSE.
+
+2002-11-03  Akim Demaille  <akim@epita.fr>
+
        * tests/calc.at: Change all the AT_CHECK_CALC_LALR and
        AT_CHECK_CALC_GLR invocations to use % directives, instead of
        command line options.
diff --git a/NEWS b/NEWS
index 681a2bd..b6ab693 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -8,6 +8,14 @@ Changes in version 1.75a, 2002-10-24:
   ago, but nobody noticed until we recently asked someone to try
   building Bison with a K&R C compiler.
 
+* %error-verbose
+  This new directive is preferred over YYERROR_VERBOSE.
+
+* %lex-param, %parse-param
+  These new directives are preferred over PARSE_PARAM and LEX_PARAM.
+  In addition, they provide a means for yyerror to remain pure, and
+  to access to the current location.
+
 Changes in version 1.75, 2002-10-14:
 
 * Bison should now work on 64-bit hosts.
index 785f9e1..2617162 100644 (file)
--- a/data/c.m4
+++ b/data/c.m4
@@ -19,9 +19,9 @@ m4_divert(-1)                                               -*- Autoconf -*-
 # 02111-1307  USA
 
 
-## ----------- ##
-## Copyright.  ##
-## ----------- ##
+## ---------------- ##
+## Identification.  ##
+## ---------------- ##
 
 # b4_copyright(TITLE, YEARS)
 # --------------------------
@@ -47,6 +47,45 @@ m4_define([b4_copyright],
    Boston, MA 02111-1307, USA.  */])
 
 
+# b4_identification
+# -----------------
+m4_define([b4_identification],
+[/* Identify Bison output.  */
+[#]define YYBISON 1
+
+/* Skeleton name.  */
+[#]define YYSKELETON_NAME "b4_skeleton"
+
+/* Pure parsers.  */
+[#]define YYPURE b4_pure
+
+/* Using locations.  */
+[#]define YYLSP_NEEDED b4_locations_flag
+])
+
+
+
+## ------------------------ ##
+## Pure/impure interfaces.  ##
+## ------------------------ ##
+
+
+# b4_user_args
+# ------------
+m4_define([b4_user_args],
+[m4_ifset([b4_parse_param], [, b4_c_args(b4_parse_param)])])
+
+
+# b4_parse_param
+# --------------
+# If defined, b4_parse_param arrives double quoted, but below we prefer
+# it to be single quoted.
+m4_define_default([b4_parse_param])
+m4_define([b4_parse_param],
+b4_parse_param))
+
+
+
 ## ------------ ##
 ## Data Types.  ##
 ## ------------ ##
index 14185cf..6a18bcb 100644 (file)
@@ -31,6 +31,15 @@ m4_define_default([b4_stack_depth_init],  [200])
 # Location type.
 m4_define_default([b4_location_type], [yyltype])
 
+
+
+## ------------------------ ##
+## Pure/impure interfaces.  ##
+## ------------------------ ##
+
+
+# b4_lex_param
+# ------------
 # Accumule in b4_lex_param all the yylex arguments.
 # Yes, this is quite ugly...
 m4_define([b4_lex_param],
@@ -38,13 +47,40 @@ m4_dquote(b4_pure_if([[[[YYSTYPE *]], [[yylvalp]]][]dnl
 b4_location_if([, [[YYLTYPE *], [yyllocp]]])])dnl
 m4_ifdef([b4_lex_param], [, ]b4_lex_param)))
 
-# Yes, this is quite ugly...
-  m4_define_default([b4_parse_param])
-m4_ifdef([b4_parse_param],
-[m4_define([b4_parse_param],
-          b4_parse_param)])
+
+# b4_user_formals
+# ---------------
+m4_define([b4_user_formals],
+[m4_ifset([b4_parse_param], [, b4_c_ansi_formals(b4_parse_param)])])
+
+
+# b4_pure_args
+# ------------
+# Arguments passed to yyerror: user args plus yylloc.
+m4_define([b4_pure_args],
+[b4_pure_if([b4_location_if([, yylocp])])[]b4_user_args])
+
+
+# b4_pure_formals
+# ---------------
+# Arguments passed to yyerror: user formals plus yyllocp.
+m4_define([b4_pure_formals],
+[b4_pure_if([b4_location_if([, YYLTYPE *yylocp])])[]b4_user_formals])
+
+
+# b4_lpure_args
+# -------------
+# Same as above, but on the lookahead, hence yyllocp instead of yylocp.
+m4_define([b4_lpure_args],
+[b4_pure_if([b4_location_if([, yyllocp])])[]b4_user_args])
 
 
+# b4_lpure_formals
+# ----------------
+# Same as above, but on the lookahead, hence yyllocp instead of yylocp.
+m4_define([b4_lpure_formals],
+[b4_pure_if([b4_location_if([YYLTYPE *yyllocp])])[]b4_user_formals])
+
 
 ## ----------------- ##
 ## Semantic Values.  ##
@@ -119,24 +155,15 @@ b4_copyright([Skeleton parser for GLR parsing with Bison], [2002])
 [
 /* This is the parser code for GLR (Generalized LR) parser. */
 
-/* FIXME: minimize these */
 #include <assert.h>
-#include <setjmp.h>
-#include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <stdarg.h>
+#include <setjmp.h>
 
-/* Identify Bison output.  */
-#define YYBISON        1
-
-/* Pure parsers.  */
-#define YYPURE ]b4_pure[
-
-/* Using locations.  */
-#define YYLSP_NEEDED ]b4_locations_flag[
-
-]m4_if(b4_prefix[], [yy], [],
+]b4_identification
+m4_if(b4_prefix[], [yy], [],
 [/* If NAME_PREFIX is specified substitute the variables and functions
    names.  */
 #define yyparse b4_prefix[]parse
@@ -378,16 +405,9 @@ static const ]b4_int_type_for([b4_check])[ yycheck[] =
 
 \f
 /* Prevent warning if -Wmissing-prototypes.  */
-]b4_c_ansi_function_decl([yyparse], [int], b4_parse_param)
-
-m4_ifset([b4_parse_param],
-[#define YY_USER_FORMALS , b4_c_ansi_formals(b4_parse_param)
-#define YY_USER_ARGS    , b4_c_args(b4_parse_param)],
-[#define YY_USER_FORMALS
-#define YY_USER_ARGS])
+]b4_c_ansi_function_decl([yyparse], [int], b4_parse_param)[
 
-
-[/* Error token number */
+/* Error token number */
 #define YYTERROR 1
 
 /* YYLLOC_DEFAULT -- Compute the default location (before the actions
@@ -548,11 +568,11 @@ struct yyGLRStack {
 };
 
 static void yyinitGLRStack (yyGLRStack* yystack, size_t yysize);
-static void yyexpandGLRStack (yyGLRStack* yystack);
+static void yyexpandGLRStack (yyGLRStack* yystack]b4_pure_formals[);
 static void yyfreeGLRStack (yyGLRStack* yystack);
 
 static void
-yyFail (yyGLRStack* yystack, const char* yyformat, ...)
+yyFail (yyGLRStack* yystack]b4_pure_formals[, const char* yyformat, ...)
 {
   if (yyformat != NULL)
     {
@@ -561,7 +581,7 @@ yyFail (yyGLRStack* yystack, const char* yyformat, ...)
       va_start (yyap, yyformat);
       yystack->yyerrflag = 1;
       vsprintf (yymsg, yyformat, yyap);
-      yyerror (yymsg);
+      yyerror (yymsg]b4_pure_args[);
     }
   longjmp (yystack->yyexception_buffer, 1);
 }
@@ -584,7 +604,7 @@ yytokenName (yySymbol yytoken)
 static YYRESULTTAG
 yyuserAction (yyRuleNum yyn, int yyrhslen, yyGLRStackItem* yyvsp,
              YYSTYPE* yyvalp, YYLTYPE* yylocp, yyGLRStack* yystack
-             YY_USER_FORMALS)
+              ]b4_user_formals[)
 {
   /* Avoid `unused' warnings in there are no $n. */
   (void) yystack;
@@ -616,7 +636,7 @@ yyuserAction (yyRuleNum yyn, int yyrhslen, yyGLRStackItem* yyvsp,
 # undef YYBACKUP
 # define YYBACKUP(Token, Value)                                                     \
   do {                                                                      \
-    yyerror ("syntax error: cannot back up");                               \
+    yyerror ("syntax error: cannot back up"]b4_pure_args[);                 \
     YYERROR;                                                                \
   } while (0)
 
@@ -644,7 +664,7 @@ static YYSTYPE
 yyuserMerge (int yyn, YYSTYPE* yy0, YYSTYPE* yy1)
 {
   YYSTYPE yyval = *yy0;
-  /* `Use' the arguments. */
+  /* `Use' the arguments.  */
   (void) yy0;
   (void) yy1;
 
@@ -655,7 +675,7 @@ yyuserMerge (int yyn, YYSTYPE* yy0, YYSTYPE* yy1)
   return yyval;
 }
 [
-                               /* Bison grammar-table manipulation */
+                             /* Bison grammar-table manipulation.  */
 
 /** Number of symbols composing the right hand side of rule #RULE. */
 static inline int
@@ -751,7 +771,7 @@ yyhasResolvedValue (yyGLRState* yystate)
 
 static void
 yyaddDeferredAction (yyGLRStack* yystack, yyGLRState* yystate,
-                    yyGLRState* rhs, yyRuleNum yyrule)
+                    yyGLRState* rhs, yyRuleNum yyrule]b4_pure_formals[)
 {
   yySemanticOption* yynewItem;
   yynewItem = &yystack->yynextFree->yyoption;
@@ -763,7 +783,7 @@ yyaddDeferredAction (yyGLRStack* yystack, yyGLRState* yystate,
   yynewItem->yynext = yystate->yysemantics.yyfirstVal;
   yystate->yysemantics.yyfirstVal = yynewItem;
   if (yystack->yyspaceLeft < YYHEADROOM)
-    yyexpandGLRStack (yystack);
+    yyexpandGLRStack (yystack]b4_pure_args[);
 }
 
                                /* GLRStacks */
@@ -808,7 +828,7 @@ yyinitGLRStack (yyGLRStack* yystack, size_t yysize)
     allocation, so that we can avoid having external pointers exist
     across an allocation. */
 static void
-yyexpandGLRStack (yyGLRStack* yystack)
+yyexpandGLRStack (yyGLRStack* yystack]b4_pure_formals[)
 {
 #if YYSTACKEXPANDABLE
   yyGLRStack yynewStack;
@@ -817,7 +837,8 @@ yyexpandGLRStack (yyGLRStack* yystack)
   size_t yyn;
   yysize = yystack->yynextFree - yystack->yyitems;
   if (YYMAXDEPTH <= yysize)
-    yyFail (yystack, "parsing stack overflow (%d items)", yysize);
+    yyFail (yystack][]b4_pure_args[,
+           "parsing stack overflow (%d items)", yysize);
   yynewSize = 2*yysize;
   if (YYMAXDEPTH < yynewSize)
     yynewSize = YYMAXDEPTH;
@@ -864,8 +885,8 @@ yyexpandGLRStack (yyGLRStack* yystack)
 
 #else
 
-  yyFail (yystack, "parsing stack overflow (%d items)", yysize);
-
+  yyFail (yystack][]b4_lpure_args[,
+          "parsing stack overflow (%d items)", yysize);
 #endif
 }
 
@@ -937,7 +958,7 @@ yyremoveDeletes (yyGLRStack* yystack)
  * LRSTATE, at input position POSN, with (resolved) semantic value SVAL. */
 static inline void
 yyglrShift (yyGLRStack* yystack, int yyk, yyStateNum yylrState, size_t yyposn,
-           YYSTYPE yysval, YYLTYPE* yylocp)
+           YYSTYPE yysval, YYLTYPE* yylocp]b4_user_formals[)
 {
   yyGLRStackItem* yynewItem;
 
@@ -953,7 +974,7 @@ yyglrShift (yyGLRStack* yystack, int yyk, yyStateNum yylrState, size_t yyposn,
   yynewItem->yystate.yysemantics.yysval = yysval;
   yynewItem->yystate.yyloc = *yylocp;
   if (yystack->yyspaceLeft < YYHEADROOM)
-    yyexpandGLRStack (yystack);
+    yyexpandGLRStack (yystack]b4_pure_args[);
 }
 
 /** Shift to a new state on stack #K of STACK, to a new state
@@ -961,7 +982,7 @@ yyglrShift (yyGLRStack* yystack, int yyk, yyStateNum yylrState, size_t yyposn,
  * the (unresolved) semantic value of RHS under the action for RULE. */
 static inline void
 yyglrShiftDefer (yyGLRStack* yystack, int yyk, yyStateNum yylrState,
-                size_t yyposn, yyGLRState* rhs, yyRuleNum yyrule)
+                size_t yyposn, yyGLRState* rhs, yyRuleNum yyrule]b4_pure_formals[)
 {
   yyGLRStackItem* yynewItem;
 
@@ -975,7 +996,7 @@ yyglrShiftDefer (yyGLRStack* yystack, int yyk, yyStateNum yylrState,
   yystack->yytops.yystates[yyk] = &yynewItem->yystate;
   yystack->yynextFree += 1;
   yystack->yyspaceLeft -= 1;
-  yyaddDeferredAction (yystack, &yynewItem->yystate, rhs, yyrule);
+  yyaddDeferredAction (yystack, &yynewItem->yystate, rhs, yyrule]b4_pure_args[);
 }
 
 /** Pop the symbols consumed by reduction #RULE from the top of stack
@@ -986,7 +1007,7 @@ yyglrShiftDefer (yyGLRStack* yystack, int yyk, yyStateNum yylrState,
  *  for userAction. */
 static inline int
 yydoAction (yyGLRStack* yystack, int yyk, yyRuleNum yyrule,
-           YYSTYPE* yyvalp, YYLTYPE* yylocp YY_USER_FORMALS)
+           YYSTYPE* yyvalp, YYLTYPE* yylocp]b4_user_formals[)
 {
   int yynrhs = yyrhsLength (yyrule);
 
@@ -1009,7 +1030,7 @@ yydoAction (yyGLRStack* yystack, int yyk, yyRuleNum yyrule,
          *yylocp = rhs[1-yynrhs].yystate.yyloc;
        }
       return yyuserAction (yyrule, yynrhs, rhs,
-                          yyvalp, yylocp, yystack YY_USER_ARGS);
+                          yyvalp, yylocp, yystack]b4_user_args[);
     }
   else
     {
@@ -1037,7 +1058,7 @@ yydoAction (yyGLRStack* yystack, int yyk, yyRuleNum yyrule,
          *yylocp = yyrhsVals[0].yystate.yyloc;
        }
       return yyuserAction (yyrule, yynrhs, yyrhsVals + (yynrhs-1),
-                          yyvalp, yylocp, yystack YY_USER_ARGS);
+                          yyvalp, yylocp, yystack]b4_user_args[);
     }
 }
 
@@ -1080,7 +1101,7 @@ yy_reduce_print (size_t yyk, yyRuleNum yyrule)
  */
 static inline YYRESULTTAG
 yyglrReduce (yyGLRStack* yystack, size_t yyk, yyRuleNum yyrule,
-             bool yyforceEval YY_USER_FORMALS)
+             bool yyforceEval]b4_pure_formals[)
 {
   size_t yyposn = yystack->yytops.yystates[yyk]->yyposn;
 
@@ -1090,11 +1111,11 @@ yyglrReduce (yyGLRStack* yystack, size_t yyk, yyRuleNum yyrule,
       YYLTYPE yyloc;
 
       YY_REDUCE_PRINT (yyk, yyrule);
-      YYCHK (yydoAction (yystack, yyk, yyrule, &yysval, &yyloc YY_USER_ARGS));
+      YYCHK (yydoAction (yystack, yyk, yyrule, &yysval, &yyloc]b4_user_args[));
       yyglrShift (yystack, yyk,
                  yyLRgotoState (yystack->yytops.yystates[yyk]->yylrState,
                                 yylhsNonterm (yyrule)),
-               yyposn, yysval, &yyloc);
+                 yyposn, yysval, &yyloc]b4_user_args[);
       YYDPRINTF ((stderr, "Stack %d entering state %d\n",
                  yyk, yystack->yytops.yystates[yyk]->yylrState));
     }
@@ -1126,7 +1147,7 @@ yyglrReduce (yyGLRStack* yystack, size_t yyk, yyRuleNum yyrule,
              {
                if (yyp->yylrState == yynewLRState && yyp->yypred == yys)
                  {
-                   yyaddDeferredAction (yystack, yyp, yys0, yyrule);
+                   yyaddDeferredAction (yystack, yyp, yys0, yyrule]b4_pure_args[);
                    yymarkStackDeleted (yystack, yyk);
                    YYDPRINTF ((stderr, "Merging stack %d into stack %d.\n",
                                yyk, yyi));
@@ -1136,7 +1157,7 @@ yyglrReduce (yyGLRStack* yystack, size_t yyk, yyRuleNum yyrule,
              }
          }
       yystack->yytops.yystates[yyk] = yys;
-      yyglrShiftDefer (yystack, yyk, yynewLRState, yyposn, yys0, yyrule);
+      yyglrShiftDefer (yystack, yyk, yynewLRState, yyposn, yys0, yyrule]b4_pure_args[);
     }
   return 0;
 }
@@ -1236,23 +1257,23 @@ yypreference (yySemanticOption* y0, yySemanticOption* y1)
 
 static YYRESULTTAG yyresolveValue (yySemanticOption* yyoptionList,
                                   yyGLRStack* yystack, YYSTYPE* yyvalp,
-                                  YYLTYPE* yylocp YY_USER_FORMALS);
+                                  YYLTYPE* yylocp]b4_user_formals[);
 
 static YYRESULTTAG
-yyresolveStates (yyGLRState* yys, int yyn, yyGLRStack* yystack YY_USER_FORMALS)
+yyresolveStates (yyGLRState* yys, int yyn, yyGLRStack* yystack]b4_user_formals[)
 {
   YYRESULTTAG yyflag;
   if (0 < yyn)
     {
       assert (yys->yypred != NULL);
-      yyflag = yyresolveStates (yys->yypred, yyn-1, yystack YY_USER_ARGS);
+      yyflag = yyresolveStates (yys->yypred, yyn-1, yystack]b4_user_args[);
       if (yyflag != yyok)
        return yyflag;
       if (! yys->yyresolved)
        {
          yyflag = yyresolveValue (yys->yysemantics.yyfirstVal, yystack,
                                   &yys->yysemantics.yysval, &yys->yyloc
-                                  YY_USER_ARGS);
+                                 ]b4_user_args[);
          if (yyflag != yyok)
            return yyflag;
          yys->yyresolved = yytrue;
@@ -1263,14 +1284,14 @@ yyresolveStates (yyGLRState* yys, int yyn, yyGLRStack* yystack YY_USER_FORMALS)
 
 static YYRESULTTAG
 yyresolveAction (yySemanticOption* yyopt, yyGLRStack* yystack,
-                YYSTYPE* yyvalp, YYLTYPE* yylocp YY_USER_FORMALS)
+                YYSTYPE* yyvalp, YYLTYPE* yylocp]b4_user_formals[)
 {
   yyGLRStackItem yyrhsVals[YYMAXRHS];
   int yynrhs, yyi;
   yyGLRState* yys;
 
   yynrhs = yyrhsLength (yyopt->yyrule);
-  YYCHK (yyresolveStates (yyopt->yystate, yynrhs, yystack YY_USER_ARGS));
+  YYCHK (yyresolveStates (yyopt->yystate, yynrhs, yystack]b4_user_args[));
   for (yyi = yynrhs-1, yys = yyopt->yystate; 0 <= yyi;
        yyi -= 1, yys = yys->yypred)
     {
@@ -1280,7 +1301,7 @@ yyresolveAction (yySemanticOption* yyopt, yyGLRStack* yystack,
       yyrhsVals[yyi].yystate.yyloc = yys->yyloc;
     }
   return yyuserAction (yyopt->yyrule, yynrhs, yyrhsVals + (yynrhs-1),
-                      yyvalp, yylocp, yystack YY_USER_ARGS);
+                      yyvalp, yylocp, yystack]b4_user_args[);
 }
 
 #if YYDEBUG
@@ -1331,7 +1352,7 @@ yyreportTree (yySemanticOption* yyx, int yyindent)
 
 static void
 yyreportAmbiguity (yySemanticOption* yyx0, yySemanticOption* yyx1,
-                  yyGLRStack* yystack)
+                  yyGLRStack* yystack]b4_pure_formals[)
 {
   /* `Unused' warnings.  */
   (void) yyx0;
@@ -1345,7 +1366,7 @@ yyreportAmbiguity (yySemanticOption* yyx0, yySemanticOption* yyx1,
   yyreportTree (yyx1, 2);
   YYFPRINTF (stderr, "\n");
 #endif
-  yyFail (yystack, "ambiguity detected");
+  yyFail (yystack][]b4_pure_args[, "ambiguity detected");
 }
 
 
@@ -1353,7 +1374,7 @@ yyreportAmbiguity (yySemanticOption* yyx0, yySemanticOption* yyx1,
  *  actions, and return the result. */
 static YYRESULTTAG
 yyresolveValue (yySemanticOption* yyoptionList, yyGLRStack* yystack,
-               YYSTYPE* yyvalp, YYLTYPE* yylocp YY_USER_FORMALS)
+               YYSTYPE* yyvalp, YYLTYPE* yylocp]b4_user_formals[)
 {
   yySemanticOption* yybest;
   yySemanticOption* yyp;
@@ -1369,7 +1390,7 @@ yyresolveValue (yySemanticOption* yyoptionList, yyGLRStack* yystack,
        switch (yypreference (yybest, yyp))
          {
          case 0:
-           yyreportAmbiguity (yybest, yyp, yystack);
+           yyreportAmbiguity (yybest, yyp, yystack]b4_pure_args[);
            break;
          case 1:
            yymerge = 1;
@@ -1386,25 +1407,25 @@ yyresolveValue (yySemanticOption* yyoptionList, yyGLRStack* yystack,
   if (yymerge)
     {
       int yyprec = yydprec[yybest->yyrule];
-      YYCHK (yyresolveAction (yybest, yystack, yyvalp, yylocp YY_USER_ARGS));
+      YYCHK (yyresolveAction (yybest, yystack, yyvalp, yylocp]b4_user_args[));
       for (yyp = yybest->yynext; yyp != NULL; yyp = yyp->yynext)
        {
          if (yyprec == yydprec[yyp->yyrule])
            {
              YYSTYPE yyval1;
              YYLTYPE yydummy;
-             YYCHK (yyresolveAction (yyp, yystack, &yyval1, &yydummy YY_USER_ARGS));
+             YYCHK (yyresolveAction (yyp, yystack, &yyval1, &yydummy]b4_user_args[));
              *yyvalp = yyuserMerge (yymerger[yyp->yyrule], yyvalp, &yyval1);
            }
        }
       return yyok;
     }
   else
-    return yyresolveAction (yybest, yystack, yyvalp, yylocp YY_USER_ARGS);
+    return yyresolveAction (yybest, yystack, yyvalp, yylocp]b4_user_args[);
 }
 
 static YYRESULTTAG
-yyresolveStack (yyGLRStack* yystack YY_USER_FORMALS)
+yyresolveStack (yyGLRStack* yystack]b4_user_formals[)
 {
   if (yystack->yysplitPoint != NULL)
     {
@@ -1416,7 +1437,7 @@ yyresolveStack (yyGLRStack* yystack YY_USER_FORMALS)
           yys = yys->yypred, yyn += 1)
        ;
       YYCHK (yyresolveStates (yystack->yytops.yystates[0], yyn, yystack
-                             YY_USER_ARGS));
+                            ]b4_user_args[));
     }
   return yyok;
 }
@@ -1454,7 +1475,7 @@ yycompressStack (yyGLRStack* yystack)
 static YYRESULTTAG
 yyprocessOneStack (yyGLRStack* yystack, int yyk,
                   size_t yyposn, YYSTYPE* yylvalp, YYLTYPE* yyllocp
-                  YY_USER_FORMALS)
+                 ]b4_user_formals[)
 {
   int yyaction;
   const short* yyconflicts;
@@ -1475,7 +1496,7 @@ yyprocessOneStack (yyGLRStack* yystack, int yyk,
              yymarkStackDeleted (yystack, yyk);
              return yyok;
            }
-         YYCHK (yyglrReduce (yystack, yyk, yyrule, yyfalse YY_USER_ARGS));
+         YYCHK (yyglrReduce (yystack, yyk, yyrule, yyfalse]b4_lpure_args[));
        }
       else
        {
@@ -1495,9 +1516,9 @@ yyprocessOneStack (yyGLRStack* yystack, int yyk,
              YYDPRINTF ((stderr, "Splitting off stack %d from %d.\n",
                          yynewStack, yyk));
              YYCHK (yyglrReduce (yystack, yynewStack,
-                                 *yyconflicts, yyfalse YY_USER_ARGS));
+                                 *yyconflicts, yyfalse]b4_lpure_args[));
              YYCHK (yyprocessOneStack (yystack, yynewStack, yyposn,
-                                       yylvalp, yyllocp YY_USER_ARGS));
+                                       yylvalp, yyllocp]b4_user_args[));
              yyconflicts += 1;
            }
 
@@ -1505,7 +1526,8 @@ yyprocessOneStack (yyGLRStack* yystack, int yyk,
            {
              YYDPRINTF ((stderr, "Shifting token %s on stack %d, ",
                          yytokenName (*yytokenp), yyk));
-             yyglrShift (yystack, yyk, yyaction, yyposn+1, *yylvalp, yyllocp);
+             yyglrShift (yystack, yyk, yyaction, yyposn+1,
+                         *yylvalp, yyllocp]b4_user_args[);
              YYDPRINTF ((stderr, "which is now in state #%d\n",
                          yystack->yytops.yystates[yyk]->yylrState));
              break;
@@ -1517,14 +1539,15 @@ yyprocessOneStack (yyGLRStack* yystack, int yyk,
              break;
            }
          else
-           YYCHK (yyglrReduce (yystack, yyk, -yyaction, yyfalse YY_USER_ARGS));
+           YYCHK (yyglrReduce (yystack, yyk, -yyaction, yyfalse]b4_lpure_args[));
        }
     }
   return yyok;
 }
 
 static void
-yyreportParseError (yyGLRStack* yystack, YYSTYPE* yylvalp, YYLTYPE* yyllocp)
+yyreportParseError (yyGLRStack* yystack,
+                   YYSTYPE* yylvalp, YYLTYPE* yyllocp]b4_user_formals[)
 {
   /* `Unused' warnings. */
   (void) yylvalp;
@@ -1568,12 +1591,12 @@ yyreportParseError (yyGLRStack* yystack, YYSTYPE* yylvalp, YYLTYPE* yyllocp)
                    yyprefix = " or ";
                  }
            }
-         yyerror (yymsg);
+         yyerror (yymsg]b4_lpure_args[);
          free (yymsg);
        }
       else
 #endif
-       yyerror ("parse error");
+       yyerror ("parse error"]b4_lpure_args[);
       yynerrs += 1;
     }
 }
@@ -1582,7 +1605,8 @@ yyreportParseError (yyGLRStack* yystack, YYSTYPE* yylvalp, YYLTYPE* yyllocp)
    YYLVALP, and YYLLOCP point to the syntactic category, semantic
    value, and location of the lookahead.  */
 static void
-yyrecoverParseError (yyGLRStack* yystack, YYSTYPE* yylvalp, YYLTYPE* yyllocp)
+yyrecoverParseError (yyGLRStack* yystack,
+                    YYSTYPE* yylvalp, YYLTYPE* yyllocp]b4_user_formals[)
 {
   yySymbol* const yytokenp = yystack->yytokenp;
   size_t yyk;
@@ -1596,7 +1620,7 @@ yyrecoverParseError (yyGLRStack* yystack, YYSTYPE* yylvalp, YYLTYPE* yyllocp)
     while (yytrue)
       {
        if (*yytokenp == YYEOF)
-         yyFail (yystack, NULL);
+         yyFail (yystack][]b4_lpure_args[, NULL);
        if (*yytokenp != YYEMPTY)
          YYDPRINTF ((stderr, "Discarding token %s\n",
                      yytokenName (*yytokenp)));
@@ -1607,7 +1631,7 @@ yyrecoverParseError (yyGLRStack* yystack, YYSTYPE* yylvalp, YYLTYPE* yyllocp)
        yyj = yypact[yystack->yytops.yystates[0]->yylrState];
        if (yyj == YYPACT_NINF)
          /* Something's not right; we shouldn't be here.  */
-         yyFail (yystack, NULL);
+         yyFail (yystack][]b4_lpure_args[, NULL);
        yyj += *yytokenp;
        if (yyj < 0 || YYLAST < yyj || yycheck[yyj] != *yytokenp)
          {
@@ -1623,7 +1647,7 @@ yyrecoverParseError (yyGLRStack* yystack, YYSTYPE* yylvalp, YYLTYPE* yyllocp)
     if (yystack->yytops.yystates[yyk] != NULL)
       break;
   if (yyk >= yystack->yytops.yysize)
-    yyFail (yystack, NULL);
+    yyFail (yystack][]b4_lpure_args[, NULL);
   for (yyk += 1; yyk < yystack->yytops.yysize; yyk += 1)
     yymarkStackDeleted (yystack, yyk);
   yyremoveDeletes (yystack);
@@ -1637,7 +1661,8 @@ yyrecoverParseError (yyGLRStack* yystack, YYSTYPE* yylvalp, YYLTYPE* yyllocp)
          yycheck[yyj] == YYTERROR && yyisShiftAction (yytable[yyj]))
        {
          yyglrShift (yystack, 0, yytable[yyj],
-                     yystack->yytops.yystates[0]->yyposn, *yylvalp, yyllocp);
+                     yystack->yytops.yystates[0]->yyposn,
+                     *yylvalp, yyllocp]b4_user_args[);
          break;
        }
       yystack->yytops.yystates[0] = yystack->yytops.yystates[0]->yypred;
@@ -1645,7 +1670,7 @@ yyrecoverParseError (yyGLRStack* yystack, YYSTYPE* yylvalp, YYLTYPE* yyllocp)
       yystack->yyspaceLeft += 1;
     }
   if (yystack->yytops.yystates[0] == NULL)
-    yyFail (yystack, NULL);
+    yyFail (yystack][]b4_lpure_args[, NULL);
 }
 
 #define YYCHK1(YYE)                                                         \
@@ -1693,7 +1718,7 @@ yyrecoverParseError (yyGLRStack* yystack, YYSTYPE* yylvalp, YYLTYPE* yyllocp)
   if (setjmp (yystack.yyexception_buffer) != 0)
     goto yyDone;
 
-  yyglrShift (&yystack, 0, 0, 0, yyval_default, &yyloc_default);
+  yyglrShift (&yystack, 0, 0, 0, yyval_default, &yyloc_default]b4_user_args[);
   yytoken = YYEMPTY;
   yyposn = 0;
 
@@ -1718,10 +1743,10 @@ yyrecoverParseError (yyGLRStack* yystack, YYSTYPE* yylvalp, YYLTYPE* yyllocp)
              yyrule = yydefaultAction (yystate);
              if (yyrule == 0)
                {
-                 yyreportParseError (&yystack, yylvalp, yyllocp);
+                 yyreportParseError (&yystack, yylvalp, yyllocp]b4_user_args[);
                  goto yyuser_error;
                }
-             YYCHK1 (yyglrReduce (&yystack, 0, yyrule, yytrue YY_USER_ARGS));
+             YYCHK1 (yyglrReduce (&yystack, 0, yyrule, yytrue]b4_lpure_args[));
            }
          else
            {
@@ -1743,7 +1768,8 @@ yyrecoverParseError (yyGLRStack* yystack, YYSTYPE* yylvalp, YYLTYPE* yyllocp)
                  if (yytoken != YYEOF)
                    yytoken = YYEMPTY;
                  yyposn += 1;
-                 yyglrShift (&yystack, 0, yyaction, yyposn, yylval, yyllocp);
+                 yyglrShift (&yystack, 0, yyaction, yyposn,
+                             yylval, yyllocp]b4_user_args[);
                  if (0 < yystack.yyerrState)
                    yystack.yyerrState -= 1;
                  YYDPRINTF ((stderr, "Entering state %d\n",
@@ -1751,11 +1777,11 @@ yyrecoverParseError (yyGLRStack* yystack, YYSTYPE* yylvalp, YYLTYPE* yyllocp)
                }
              else if (yyisErrorAction (yyaction))
                {
-                 yyreportParseError (&yystack, yylvalp, yyllocp);
+                 yyreportParseError (&yystack, yylvalp, yyllocp]b4_user_args[);
                  goto yyuser_error;
                }
              else
-               YYCHK1 (yyglrReduce (&yystack, 0, -yyaction, yytrue YY_USER_ARGS));
+               YYCHK1 (yyglrReduce (&yystack, 0, -yyaction, yytrue]b4_lpure_args[));
            }
        }
 
@@ -1765,7 +1791,7 @@ yyrecoverParseError (yyGLRStack* yystack, YYSTYPE* yylvalp, YYLTYPE* yyllocp)
          int yyn = yystack.yytops.yysize;
          for (yys = 0; yys < yyn; yys += 1)
            YYCHK1 (yyprocessOneStack (&yystack, yys, yyposn,
-                                      yylvalp, yyllocp YY_USER_ARGS));
+                                      yylvalp, yyllocp]b4_user_args[));
          yytoken = YYEMPTY;
          yyposn += 1;
          yyremoveDeletes (&yystack);
@@ -1773,15 +1799,15 @@ yyrecoverParseError (yyGLRStack* yystack, YYSTYPE* yylvalp, YYLTYPE* yyllocp)
            {
              yyundeleteLastStack (&yystack);
              if (yystack.yytops.yysize == 0)
-               yyFail (&yystack, "parse error");
-             YYCHK1 (yyresolveStack (&yystack YY_USER_ARGS));
+               yyFail (&yystack][]b4_lpure_args[, "parse error");
+             YYCHK1 (yyresolveStack (&yystack]b4_user_args[));
              YYDPRINTF ((stderr, "Returning to deterministic operation.\n"));
-             yyreportParseError (&yystack, yylvalp, yyllocp);
+             yyreportParseError (&yystack, yylvalp, yyllocp]b4_user_args[);
              goto yyuser_error;
            }
          else if (yystack.yytops.yysize == 1)
            {
-             YYCHK1 (yyresolveStack (&yystack YY_USER_ARGS));
+             YYCHK1 (yyresolveStack (&yystack]b4_user_args[));
              YYDPRINTF ((stderr, "Returning to deterministic operation.\n"));
              yycompressStack (&yystack);
              break;
@@ -1789,7 +1815,7 @@ yyrecoverParseError (yyGLRStack* yystack, YYSTYPE* yylvalp, YYLTYPE* yyllocp)
        }
       continue;
     yyuser_error:
-      yyrecoverParseError (&yystack, yylvalp, yyllocp);
+      yyrecoverParseError (&yystack, yylvalp, yyllocp]b4_user_args[);
       yyposn = yystack.yytops.yystates[0]->yyposn;
     }
  yyDone:
index 0bbd482..cd93373 100644 (file)
@@ -33,19 +33,37 @@ m4_define_default([b4_stack_depth_init],  [200])
 # Location type.
 m4_define_default([b4_location_type], [yyltype])
 
+
+## ------------------------ ##
+## Pure/impure interfaces.  ##
+## ------------------------ ##
+
+
+# b4_Pure_if(IF-TRUE, IF-FALSE)
+# -----------------------------
+# Expand IF-TRUE, if %pure-parser and %parse-param, IF-FALSE otherwise.
+m4_define([b4_Pure_if],
+[b4_pure_if([m4_ifset([b4_parse_param],
+                      [$1], [$2])],
+            [$2])])
+
+
+# b4_pure_args
+# ------------
+# Arguments passed to yyerror: user args plus yylloc.
+m4_define([b4_pure_args],
+[b4_Pure_if([b4_location_if([, &yylloc])])[]b4_user_args])
+
+
+# b4_lex_param
+# ------------
 # Accumule in b4_lex_param all the yylex arguments.
-# Yes, this is quite ugly...
+# b4_lex_param arrives quoted twice, but we want to keep only one level.
 m4_define([b4_lex_param],
 m4_dquote(b4_pure_if([[[[YYSTYPE *]], [[&yylval]]][]dnl
 b4_location_if([, [[YYLTYPE *], [&yylloc]]])])dnl
 m4_ifdef([b4_lex_param], [, ]b4_lex_param)))
 
-# Yes, this is quite ugly...
-m4_define_default([b4_parse_param])
-m4_ifdef([b4_parse_param],
-[m4_define([b4_parse_param],
-          b4_parse_param)])
-
 
 
 ## ------------ ##
@@ -56,7 +74,7 @@ m4_ifdef([b4_parse_param],
 # ---------------------
 # Return the smallest int type able to handle numbers ranging from
 # MIN to MAX (included).  We overwrite the version from c.m4 which relies
-# on `signed char' which is not portable to old K&R compilers.
+# on "signed char" which is not portable to old K&R compilers.
 m4_define([b4_int_type],
 [m4_if(b4_ints_in($@,      [0],   [255]), [1], [unsigned char],
        b4_ints_in($@,   [-128],   [127]), [1], [yysigned_char],
@@ -178,15 +196,7 @@ b4_copyright([Skeleton parser for Yacc-like parsing with Bison],
    define necessary library symbols; they are noted "INFRINGES ON
    USER NAME SPACE" below.  */
 
-/* Identify Bison output.  */
-#define YYBISON        1
-
-/* Pure parsers.  */
-#define YYPURE b4_pure
-
-/* Using locations.  */
-#define YYLSP_NEEDED b4_locations_flag
-
+b4_identification
 m4_if(b4_prefix[], [yy], [],
 [/* If NAME_PREFIX is specified substitute the variables and functions
    names.  */
@@ -519,7 +529,7 @@ do                                                          \
     }                                                          \
   else                                                         \
     {                                                          \
-      yyerror ("syntax error: cannot back up");                        \
+      yyerror ("syntax error: cannot back up"b4_pure_args);    \
       YYERROR;                                                 \
     }                                                          \
 while (0)
@@ -1125,15 +1135,15 @@ yyerrlab:
                        yycount++;
                      }
                }
-             yyerror (yymsg);
+             yyerror (yymsg]b4_pure_args[);
              YYSTACK_FREE (yymsg);
            }
          else
-           yyerror ("parse error; also virtual memory exhausted");
+           yyerror ("parse error; also virtual memory exhausted"]b4_pure_args[);
        }
       else
 #endif /* YYERROR_VERBOSE */
-       yyerror ("parse error");
+       yyerror ("parse error"]b4_pure_args[);
     }
   goto yyerrlab1;
 
@@ -1248,7 +1258,7 @@ yyabortlab:
 | yyoverflowlab -- parser overflow comes here.  |
 `----------------------------------------------*/
 yyoverflowlab:
-  yyerror ("parser stack overflow");
+  yyerror ("parser stack overflow"]b4_pure_args[);
   yyresult = 2;
   /* Fall through.  */
 #endif
index 225bbaa..290cbab 100644 (file)
@@ -682,7 +682,7 @@ involved, or by performing both actions, and then calling a designated
 user-defined function on the resulting values to produce an arbitrary
 merged result.
 
-Let's consider an example, vastly simplified from C++.
+Let's consider an example, vastly simplified from a C++ grammar.
 
 @example
 %@{
@@ -706,20 +706,20 @@ stmt : expr ';'  %dprec 1
      | decl      %dprec 2
      ;
 
-expr : ID              @{ printf ("%s ", $$); @}
+expr : ID               @{ printf ("%s ", $$); @}
      | TYPENAME '(' expr ')'
-                       @{ printf ("%s <cast> ", $1); @}
-     | expr '+' expr   @{ printf ("+ "); @}
-     | expr '=' expr   @{ printf ("= "); @}
+                        @{ printf ("%s <cast> ", $1); @}
+     | expr '+' expr    @{ printf ("+ "); @}
+     | expr '=' expr    @{ printf ("= "); @}
      ;
 
 decl : TYPENAME declarator ';'
-                       @{ printf ("%s <declare> ", $1); @}
+                        @{ printf ("%s <declare> ", $1); @}
      | TYPENAME declarator '=' expr ';'
-                       @{ printf ("%s <init-declare> ", $1); @}
+                        @{ printf ("%s <init-declare> ", $1); @}
      ;
 
-declarator : ID                @{ printf ("\"%s\" ", $1); @}
+declarator : ID         @{ printf ("\"%s\" ", $1); @}
      | '(' declarator ')'
      ;
 @end example
@@ -3559,10 +3559,11 @@ accurate parse error messages.
 Rename the external symbols used in the parser so that they start with
 @var{prefix} instead of @samp{yy}.  The precise list of symbols renamed
 is @code{yyparse}, @code{yylex}, @code{yyerror}, @code{yynerrs},
-@code{yylval}, @code{yychar}, @code{yydebug}, and possible
-@code{yylloc}.  For example, if you use @samp{%name-prefix="c_"}, the
-names become @code{c_parse}, @code{c_lex}, and so on.  @xref{Multiple
-Parsers, ,Multiple Parsers in the Same Program}.
+@code{yylval}, @code{yylloc}, @code{yychar}, @code{yydebug}, and
+possible @code{yylloc}.  For example, if you use
+@samp{%name-prefix="c_"}, the names become @code{c_parse}, @code{c_lex},
+and so on.  @xref{Multiple Parsers, ,Multiple Parsers in the Same
+Program}.
 
 @item %no-parser
 Do not include any C code in the parser file; generate tables only.  The
@@ -3659,9 +3660,9 @@ instead of @samp{yy}.  You can use this to give each parser distinct
 names that do not conflict.
 
 The precise list of symbols renamed is @code{yyparse}, @code{yylex},
-@code{yyerror}, @code{yynerrs}, @code{yylval}, @code{yychar} and
-@code{yydebug}.  For example, if you use @samp{-p c}, the names become
-@code{cparse}, @code{clex}, and so on.
+@code{yyerror}, @code{yynerrs}, @code{yylval}, @code{yylloc},
+@code{yychar} and @code{yydebug}.  For example, if you use @samp{-p c},
+the names become @code{cparse}, @code{clex}, and so on.
 
 @strong{All the other variables and macros associated with Bison are not
 renamed.} These others are not global; there is no conflict if the same
@@ -3706,23 +3707,65 @@ encounters end-of-input or an unrecoverable syntax error.  You can also
 write an action which directs @code{yyparse} to return immediately
 without reading further.
 
+
+@deftypefun int yyparse (void)
 The value returned by @code{yyparse} is 0 if parsing was successful (return
 is due to end-of-input).
 
 The value is 1 if parsing failed (return is due to a syntax error).
+@end deftypefun
 
 In an action, you can cause immediate return from @code{yyparse} by using
 these macros:
 
-@table @code
-@item YYACCEPT
+@defmac YYACCEPT
 @findex YYACCEPT
 Return immediately with value 0 (to report success).
+@end defmac
 
-@item YYABORT
+@defmac YYABORT
 @findex YYABORT
 Return immediately with value 1 (to report failure).
-@end table
+@end defmac
+
+If you use a reentrant parser, you can optionally pass additional
+parameter information to it in a reentrant way.  To do so, use the
+declaration @code{%parse-param}:
+
+@deffn {Directive} %parse-param @var{argument-declaration} @var{argument-name}
+@findex %parse-param
+Declare that @code{argument-name} is an additional @code{yyparse}
+argument.  This argument is also passed to @code{yyerror}.  The
+@var{argument-declaration} is used when declaring functions or
+prototypes.
+@end deffn
+
+Here's an example.  Write this in the parser:
+
+@example
+%parse-param "int *nastiness"  "nastiness"
+%parse-param "int *randomness" "randomness"
+@end example
+
+@noindent
+Then call the parser like this:
+
+@example
+@{
+  int nastiness, randomness;
+  @dots{}  /* @r{Store proper data in @code{nastiness} and @code{randomness}.}  */
+  value = yyparse (&nastiness, &randomness);
+  @dots{}
+@}
+@end example
+
+@noindent
+In the grammar actions, use expressions like this to refer to the data:
+
+@example
+exp: @dots{}    @{ @dots{}; *randomness += 1; @dots{} @}
+@end example
+
 
 @node Lexical
 @section The Lexical Analyzer Function @code{yylex}
@@ -3927,85 +3970,47 @@ textual positions, then the type @code{YYLTYPE} will not be defined.  In
 this case, omit the second argument; @code{yylex} will be called with
 only one argument.
 
-@vindex YYPARSE_PARAM
-If you use a reentrant parser, you can optionally pass additional
-parameter information to it in a reentrant way.  To do so, define the
-macro @code{YYPARSE_PARAM} as a variable name.  This modifies the
-@code{yyparse} function to accept one argument, of type @code{void *},
-with that name.
-
-When you call @code{yyparse}, pass the address of an object, casting the
-address to @code{void *}.  The grammar actions can refer to the contents
-of the object by casting the pointer value back to its proper type and
-then dereferencing it.  Here's an example.  Write this in the parser:
 
-@example
-%@{
-struct parser_control
-@{
-  int nastiness;
-  int randomness;
-@};
+If you wish to pass the additional parameter data to @code{yylex}, use
+@code{%lex-param} just like @code{%parse-param} (@pxref{Parser
+Function}).
 
-#define YYPARSE_PARAM parm
-%@}
-@end example
+@deffn {Directive} lex-param @var{argument-declaration} @var{argument-name}
+@findex %lex-param
+Declare that @code{argument-name} is an additional @code{yylex}
+argument.
+@end deffn
 
-@noindent
-Then call the parser like this:
+For instance:
 
 @example
-struct parser_control
-@{
-  int nastiness;
-  int randomness;
-@};
-
-@dots{}
-
-@{
-  struct parser_control foo;
-  @dots{}  /* @r{Store proper data in @code{foo}.}  */
-  value = yyparse ((void *) &foo);
-  @dots{}
-@}
+%parse-param "int *nastiness"  "nastiness"
+%lex-param   "int *nastiness"  "nastiness"
+%parse-param "int *randomness" "randomness"
 @end example
 
 @noindent
-In the grammar actions, use expressions like this to refer to the data:
+results in the following signature:
 
 @example
-((struct parser_control *) parm)->randomness
+int yylex   (int *nastiness);
+int yyparse (int *nastiness, int *randomness);
 @end example
 
-@vindex YYLEX_PARAM
-If you wish to pass the additional parameter data to @code{yylex},
-define the macro @code{YYLEX_PARAM} just like @code{YYPARSE_PARAM}, as
-shown here:
+If @code{%pure-parser} is added:
 
 @example
-%@{
-struct parser_control
-@{
-  int nastiness;
-  int randomness;
-@};
-
-#define YYPARSE_PARAM parm
-#define YYLEX_PARAM parm
-%@}
+int yylex   (YYSTYPE *lvalp, int *nastiness);
+int yyparse (int *nastiness, int *randomness);
 @end example
 
-You should then define @code{yylex} to accept one additional
-argument---the value of @code{parm}.  (This makes either two or three
-arguments in total, depending on whether an argument of type
-@code{YYLTYPE} is passed.)  You can declare the argument as a pointer to
-the proper object type, or you can declare it as @code{void *} and
-access the contents as shown above.
+@noindent
+and finally, if both @code{%pure-parser} and @code{%locations} are used:
 
-You can use @samp{%pure-parser} to request a reentrant parser without
-also using @code{YYPARSE_PARAM}.  Then you should call @code{yyparse}
-with no arguments, as usual.
+@example
+int yylex   (YYSTYPE *lvalp, YYLTYPE *llocp, int *nastiness);
+int yyparse (int *nastiness, int *randomness);
+@end example
 
 @node Error Reporting
 @section The Error Reporting Function @code{yyerror}
@@ -4026,13 +4031,11 @@ called by @code{yyparse} whenever a syntax error is found, and it
 receives one argument.  For a parse error, the string is normally
 @w{@code{"parse error"}}.
 
-@findex YYERROR_VERBOSE
-If you define the macro @code{YYERROR_VERBOSE} in the Bison declarations
-section (@pxref{Bison Declarations, ,The Bison Declarations Section}),
-then Bison provides a more verbose and specific error message string
-instead of just plain @w{@code{"parse error"}}.  It doesn't matter what
-definition you use for @code{YYERROR_VERBOSE}, just whether you define
-it.
+@findex %error-verbose
+If you invoke the directive @code{%error-verbose} in the Bison
+declarations section (@pxref{Bison Declarations, ,The Bison Declarations
+Section}), then Bison provides a more verbose and specific error message
+string instead of just plain @w{@code{"parse error"}}.
 
 The parser can detect one other kind of error: stack overflow.  This
 happens when the input contains constructions that are very deeply
@@ -4061,6 +4064,50 @@ error recovery if you have written suitable error recovery grammar rules
 (@pxref{Error Recovery}).  If recovery is impossible, @code{yyparse} will
 immediately return 1.
 
+Oviously, in location tracking pure parsers, @code{yyerror} should have
+an access to the current location.  This is indeed the case for the GLR
+parsers, but not for the Yacc parser, for historical reasons.  I.e., if
+@samp{%locations %pure-parser} is passed then the prototypes for
+@code{yyerror} are:
+
+@example
+void yyerror (const char *msg);                 /* Yacc parsers.  */
+void yyerror (const char *msg, YYLTYPE *locp);  /* GLR parsers.   */
+@end example
+
+If @samp{%parse-param "int *nastiness"  "nastiness"} is used, then:
+
+@example
+void yyerror (int *randomness);  /* Yacc parsers.  */
+void yyerror (int *randomness);  /* GLR parsers.   */
+@end example
+
+Finally, GLR and Yacc parsers share the same @code{yyerror} calling
+convention for absolutely pure parsers, i.e., when the calling
+convention of @code{yylex} @emph{and} the calling convention of
+@code{%pure-parser} are pure.  I.e.:
+
+@example
+/* Location tracking.  */
+%locations
+/* Pure yylex.  */
+%pure-parser
+%lex-param   "int *nastiness"  "nastiness"
+/* Pure yyparse.  */
+%parse-param "int *nastiness"  "nastiness"
+%parse-param "int *randomness" "randomness"
+@end example
+
+@noindent
+results in the following signatures for all the parser kinds:
+
+@example
+int yylex (YYSTYPE *lvalp, YYLTYPE *llocp, int *nastiness);
+int yyparse (int *nastiness, int *randomness);
+void yyerror (const char *msg, YYLTYPE *locp,
+              int *nastiness, int *randomness);
+@end example
+
 @vindex yynerrs
 The variable @code{yynerrs} contains the number of syntax errors
 encountered so far.  Normally this variable is global; but if you
@@ -5450,9 +5497,9 @@ state 0
 
     $accept  ->  . exp $   (rule 0)
 
-    NUM        shift, and go to state 1
+    NUM         shift, and go to state 1
 
-    exp        go to state 2
+    exp         go to state 2
 @end example
 
 This reads as follows: ``state 0 corresponds to being at the very
@@ -5499,7 +5546,7 @@ state 1
 
     exp  ->  NUM .   (rule 5)
 
-    $default   reduce using rule 5 (exp)
+    $default    reduce using rule 5 (exp)
 @end example
 
 @noindent
@@ -5517,11 +5564,11 @@ state 2
     exp  ->  exp . '*' exp   (rule 3)
     exp  ->  exp . '/' exp   (rule 4)
 
-    $          shift, and go to state 3
-    '+'        shift, and go to state 4
-    '-'        shift, and go to state 5
-    '*'        shift, and go to state 6
-    '/'        shift, and go to state 7
+    $           shift, and go to state 3
+    '+'         shift, and go to state 4
+    '-'         shift, and go to state 5
+    '*'         shift, and go to state 6
+    '/'         shift, and go to state 7
 @end example
 
 @noindent
@@ -5540,7 +5587,7 @@ state 3
 
     $accept  ->  exp $ .   (rule 0)
 
-    $default   accept
+    $default    accept
 @end example
 
 @noindent
@@ -5555,33 +5602,33 @@ state 4
 
     exp  ->  exp '+' . exp   (rule 1)
 
-    NUM        shift, and go to state 1
+    NUM         shift, and go to state 1
 
-    exp        go to state 8
+    exp         go to state 8
 
 state 5
 
     exp  ->  exp '-' . exp   (rule 2)
 
-    NUM        shift, and go to state 1
+    NUM         shift, and go to state 1
 
-    exp        go to state 9
+    exp         go to state 9
 
 state 6
 
     exp  ->  exp '*' . exp   (rule 3)
 
-    NUM        shift, and go to state 1
+    NUM         shift, and go to state 1
 
-    exp        go to state 10
+    exp         go to state 10
 
 state 7
 
     exp  ->  exp '/' . exp   (rule 4)
 
-    NUM        shift, and go to state 1
+    NUM         shift, and go to state 1
 
-    exp        go to state 11
+    exp         go to state 11
 @end example
 
 As was announced in beginning of the report, @samp{State 8 contains 1
@@ -5596,11 +5643,11 @@ state 8
     exp  ->  exp . '*' exp   (rule 3)
     exp  ->  exp . '/' exp   (rule 4)
 
-    '*'        shift, and go to state 6
-    '/'        shift, and go to state 7
+    '*'         shift, and go to state 6
+    '/'         shift, and go to state 7
 
-    '/'        [reduce using rule 1 (exp)]
-    $default   reduce using rule 1 (exp)
+    '/'         [reduce using rule 1 (exp)]
+    $default    reduce using rule 1 (exp)
 @end example
 
 Indeed, there are two actions associated to the lookahead @samp{/}:
@@ -5657,11 +5704,11 @@ state 9
     exp  ->  exp . '*' exp   (rule 3)
     exp  ->  exp . '/' exp   (rule 4)
 
-    '*'        shift, and go to state 6
-    '/'        shift, and go to state 7
+    '*'         shift, and go to state 6
+    '/'         shift, and go to state 7
 
-    '/'        [reduce using rule 2 (exp)]
-    $default   reduce using rule 2 (exp)
+    '/'         [reduce using rule 2 (exp)]
+    $default    reduce using rule 2 (exp)
 
 state 10
 
@@ -5671,10 +5718,10 @@ state 10
     exp  ->  exp '*' exp .   (rule 3)
     exp  ->  exp . '/' exp   (rule 4)
 
-    '/'        shift, and go to state 7
+    '/'         shift, and go to state 7
 
-    '/'        [reduce using rule 3 (exp)]
-    $default   reduce using rule 3 (exp)
+    '/'         [reduce using rule 3 (exp)]
+    $default    reduce using rule 3 (exp)
 
 state 11
 
@@ -5684,16 +5731,16 @@ state 11
     exp  ->  exp . '/' exp   (rule 4)
     exp  ->  exp '/' exp .   (rule 4)
 
-    '+'        shift, and go to state 4
-    '-'        shift, and go to state 5
-    '*'        shift, and go to state 6
-    '/'        shift, and go to state 7
+    '+'         shift, and go to state 4
+    '-'         shift, and go to state 5
+    '*'         shift, and go to state 6
+    '/'         shift, and go to state 7
 
-    '+'        [reduce using rule 4 (exp)]
-    '-'        [reduce using rule 4 (exp)]
-    '*'        [reduce using rule 4 (exp)]
-    '/'        [reduce using rule 4 (exp)]
-    $default   reduce using rule 4 (exp)
+    '+'         [reduce using rule 4 (exp)]
+    '-'         [reduce using rule 4 (exp)]
+    '*'         [reduce using rule 4 (exp)]
+    '/'         [reduce using rule 4 (exp)]
+    $default    reduce using rule 4 (exp)
 @end example
 
 @noindent
@@ -6171,18 +6218,21 @@ Macro to pretend that a syntax error has just been detected: call
 @code{yyparse} return 1.  @xref{Error Recovery}.
 
 @item YYERROR_VERBOSE
-Macro that you define with @code{#define} in the Bison declarations
-section to request verbose, specific error message strings when
-@code{yyerror} is called.
+An obsolete macro that you define with @code{#define} in the Bison
+declarations section to request verbose, specific error message strings
+when @code{yyerror} is called.  It doesn't matter what definition you
+use for @code{YYERROR_VERBOSE}, just whether you define it.  Using
+@code{%error-verbose} is preferred.
 
 @item YYINITDEPTH
 Macro for specifying the initial size of the parser stack.
 @xref{Stack Overflow}.
 
 @item YYLEX_PARAM
-Macro for specifying an extra argument (or list of extra arguments) for
-@code{yyparse} to pass to @code{yylex}.  @xref{Pure Calling,, Calling
-Conventions for Pure Parsers}.
+An obsolete macro for specifying an extra argument (or list of extra
+arguments) for @code{yyparse} to pass to @code{yylex}.  he use of this
+macro is deprecated, and is supported only for Yacc like parsers.
+@xref{Pure Calling,, Calling Conventions for Pure Parsers}.
 
 @item YYLTYPE
 Macro for the data type of @code{yylloc}; a structure with four
@@ -6196,8 +6246,10 @@ Macro for specifying the maximum size of the parser stack.
 @xref{Stack Overflow}.
 
 @item YYPARSE_PARAM
-Macro for specifying the name of a parameter that @code{yyparse} should
-accept.  @xref{Pure Calling,, Calling Conventions for Pure Parsers}.
+An obsolete macro for specifying the name of a parameter that
+@code{yyparse} should accept.  The use of this macro is deprecated, and
+is supported only for Yacc like parsers.  @xref{Pure Calling,, Calling
+Conventions for Pure Parsers}.
 
 @item YYRECOVERING
 Macro whose value indicates whether the parser is recovering from a
@@ -6278,6 +6330,10 @@ Bison declaration to assign a precedence to a rule that is used at parse
 time to resolve reduce/reduce conflicts.  @xref{GLR Parsers, ,Writing
 @acronym{GLR} Parsers}.
 
+@item %error-verbose
+Bison declaration to request verbose, specific error message strings
+when @code{yyerror} is called.
+
 @item %file-prefix="@var{prefix}"
 Bison declaration to set the prefix of the output files.  @xref{Decl
 Summary}.
@@ -6298,6 +6354,11 @@ Parsers, ,Writing @acronym{GLR} Parsers}.
 Bison declaration to assign left associativity to token(s).
 @xref{Precedence Decl, ,Operator Precedence}.
 
+@item %lex-param "@var{argument-declaration}" "@var{argument-name}"
+Bison declaration to specifying an additional parameter that
+@code{yylex} should accept.  @xref{Pure Calling,, Calling Conventions
+for Pure Parsers}.
+
 @item %merge
 Bison declaration to assign a merging function to a rule.  If there is a
 reduce/reduce conflict with a rule having the same merging function, the
@@ -6319,6 +6380,11 @@ Bison declaration to assign non-associativity to token(s).
 Bison declaration to set the name of the parser file.  @xref{Decl
 Summary}.
 
+@item %parse-param "@var{argument-declaration}" "@var{argument-name}"
+Bison declaration to specifying an additional parameter that
+@code{yyparse} should accept.  @xref{Parser Function,, The Parser
+Function @code{yyparse}}.
+
 @item %prec
 Bison declaration to assign a precedence to a specific rule.
 @xref{Contextual Precedence, ,Context-Dependent Precedence}.
index d239ddd..82674c1 100644 (file)
@@ -26,8 +26,8 @@
 # ------------------------- #
 
 
-# _AT_DATA_CALC_Y($1, $2, $3, [CPP-DIRECTIVES])
-# ---------------------------------------------
+# _AT_DATA_CALC_Y($1, $2, $3, [BISON-DIRECTIVES])
+# -----------------------------------------------
 # Produce `calc.y'.  Don't call this macro directly, because it contains
 # some occurrences of `$1' etc. which will be interpreted by m4.  So
 # you should call it with $1, $2, and $3 as arguments, which is what
@@ -37,7 +37,7 @@ m4_define([_AT_DATA_CALC_Y],
        [m4_fatal([$0: Invalid arguments: $@])])dnl
 AT_DATA([calc.y],
 [[/* Infix notation calculator--calc */
-
+]$4[
 %{
 #include <config.h>
 /* We don't need perfect functions for these tests. */
@@ -63,9 +63,6 @@ int global_count = 0;
 
 %}
 
-%parse-param "value_t *result", "result"
-%parse-param "int *count",      "count"
-
 /* Exercise %union. */
 %union
 {
@@ -81,16 +78,14 @@ int global_count = 0;
 #  define VAL     (yylval)
 #endif
 
+#define YYLLOC_FORMAL   ]AT_LOCATION_IF([, YYLTYPE *yylloc])[
+#define YYLLOC_ARG      ]AT_LOCATION_IF([, yylloc])[
+#define USE_YYLLOC      ]AT_LOCATION_IF([(void) yylloc;])[
+
 #if YYPURE
-#  if YYLSP_NEEDED
-#    define LEX_FORMALS     YYSTYPE *yylval, YYLTYPE *yylloc
-#    define LEX_ARGS        yylval, yylloc
-#    define USE_LEX_ARGS    (void) yylval; (void) yylloc;
-#  else
-#    define LEX_FORMALS     YYSTYPE *yylval
-#    define LEX_ARGS        yylval
-#    define USE_LEX_ARGS    (void) yylval
-#  endif
+#  define LEX_FORMALS     YYSTYPE *yylval YYLLOC_FORMAL
+#  define LEX_ARGS        yylval          YYLLOC_ARG
+#  define USE_LEX_ARGS    (void) yylval;  USE_YYLLOC
 #  define LEX_PRE_FORMALS   LEX_FORMALS,
 #  define LEX_PRE_ARGS      LEX_ARGS,
 #else
@@ -102,7 +97,13 @@ int global_count = 0;
 #endif
 
 static int power (int base, int exponent);
-static void yyerror (const char *s);
+/* yyerror receives the location if:
+   - %location & %pure & %glr
+   - %location & %pure & %yacc & %parse-param. */
+static void yyerror (const char *s
+                     ]AT_YYERROR_ARG_LOC_IF([, YYLTYPE *yylloc])[
+                     ]AT_PARAM_IF([, value_t *result, int *count])[
+                     );
 static int yylex (LEX_FORMALS);
 static int yygetc (LEX_FORMALS);
 static void yyungetc (LEX_PRE_FORMALS int c);
@@ -119,27 +120,25 @@ static void yyungetc (LEX_PRE_FORMALS int c);
 %left NEG     /* negation--unary minus */
 %right '^'    /* exponentiation        */
 
-]$4[
-
 /* Grammar follows */
 %%
 input:
   line
-| input line         { ++*count; ++global_count; }
+| input line         { ]AT_PARAM_IF([++*count; ++global_count;])[ }
 ;
 
 line:
   '\n'
-| exp '\n'           { *result = global_result = $1; }
+| exp '\n'           { ]AT_PARAM_IF([*result = global_result = $1;])[ }
 ;
 
 exp:
   NUM                { $$ = $1;             }
 | exp '=' exp
   {
-     if ($1 != $3)
-       fprintf (stderr, "calc: error: %d != %d\n", $1, $3);
-     $$ = $1;
+    if ($1 != $3)
+      fprintf (stderr, "calc: error: %d != %d\n", $1, $3);
+    $$ = $1;
   }
 | exp '+' exp        { $$ = $1 + $3;        }
 | exp '-' exp        { $$ = $1 - $3;        }
@@ -155,26 +154,28 @@ exp:
 FILE *yyin;
 
 static void
-yyerror (const char *s)
+yyerror (const char *s
+         ]AT_YYERROR_ARG_LOC_IF([, YYLTYPE *yylloc])[
+         ]AT_PARAM_IF([, value_t *result, int *count])[)
 {
-#if YYLSP_NEEDED
+]AT_YYERROR_SEES_LOC_IF([
   fprintf (stderr, "%d.%d-%d.%d: ",
           LOC.first_line, LOC.first_column,
           LOC.last_line, LOC.last_column);
-#endif
+])[
   fprintf (stderr, "%s\n", s);
 }
 
 
-#if YYLSP_NEEDED
+]AT_LOCATION_IF([
 static YYLTYPE last_yylloc;
-#endif
+])[
 static int
 yygetc (LEX_FORMALS)
 {
   int res = getc (yyin);
   USE_LEX_ARGS;
-#if YYLSP_NEEDED
+]AT_LOCATION_IF([
   last_yylloc = LOC;
   if (res == '\n')
     {
@@ -183,7 +184,7 @@ yygetc (LEX_FORMALS)
     }
   else
     LOC.last_column++;
-#endif
+])[
   return res;
 }
 
@@ -192,10 +193,10 @@ static void
 yyungetc (LEX_PRE_FORMALS int c)
 {
   USE_LEX_ARGS;
-#if YYLSP_NEEDED
+]AT_LOCATION_IF([
   /* Wrong when C == `\n'. */
   LOC = last_yylloc;
-#endif
+])[
   ungetc (c, yyin);
 }
 
@@ -241,24 +242,24 @@ yylex (LEX_FORMALS)
   if (init)
     {
       init = 0;
-#if YYLSP_NEEDED
+]AT_LOCATION_IF([
       LOC.last_column = 1;
       LOC.last_line = 1;
-#endif
+])[
     }
 
-#if YYLSP_NEEDED
+]AT_LOCATION_IF([
   LOC.first_column = LOC.last_column;
   LOC.first_line = LOC.last_line;
-#endif
+])[
 
   /* Skip white space.  */
   while ((c = yygetc (LEX_ARGS)) == ' ' || c == '\t')
     {
-#if YYLSP_NEEDED
+]AT_LOCATION_IF([
       LOC.first_column = LOC.last_column;
       LOC.first_line = LOC.last_line;
-#endif
+])[
     }
 
   /* process numbers   */
@@ -309,7 +310,7 @@ main (int argc, const char **argv)
 #if YYDEBUG
   yydebug = 1;
 #endif
-  yyparse (&result, &count);
+  yyparse (]AT_PARAM_IF([&result, &count])[);
   assert (global_result == result);
   assert (global_count  == count);
 
@@ -352,8 +353,8 @@ m4_bmatch([$1],
 
 
 # _AT_CHECK_CALC_ERROR(BISON-OPTIONS, INPUT, [NUM-DEBUG-LINES],
-#                      [ERROR-LOCATION], [IF-YYERROR-VERBOSE])
-# ------------------------------------------------------------
+#                      [VERBOSE-AND-LOCATED-ERROR-MESSAGE])
+# -------------------------------------------------------------
 # Run `calc' on INPUT, and expect a `parse error' message.
 #
 # If INPUT starts with a slash, it is used as absolute input file name,
@@ -402,7 +403,7 @@ AT_DATA([[expout]],
 [$4
 ])
 # 3. If locations are not used, remove them.
-m4_bmatch([$1], [%locations], [],
+AT_YYERROR_SEES_LOC_IF([],
 [[sed 's/^[-0-9.]*: //' expout >at-expout
 mv at-expout expout]])
 # 4. If error-verbose is not used, strip the`, unexpected....' part.
@@ -414,6 +415,54 @@ AT_CHECK([cat stderr], 0, [expout])
 ])
 
 
+# AT_CALC_PUSHDEFS($1, $2, [BISON-OPTIONS])
+# -----------------------------------------
+# This macro works around the impossibility to define macros
+# inside macros, because issuing `[$1]' is not possible in M4 :(.
+# This sucks hard, GNU M4 should really provide M5 like $$1.
+m4_define([AT_CHECK_PUSHDEFS],
+[m4_if([$1$2], $[1]$[2], [],
+       [m4_fatal([$0: Invalid arguments: $@])])dnl
+m4_pushdef([AT_PARAM_IF],
+[m4_bmatch([$3], [%parse-param], [$1], [$2])])
+m4_pushdef([AT_LOCATION_IF],
+[m4_bmatch([$3], [%locations], [$1], [$2])])
+m4_pushdef([AT_PURE_IF],
+[m4_bmatch([$3], [%pure-parser], [$1], [$2])])
+m4_pushdef([AT_GLR_IF],
+[m4_bmatch([$3], [%glr-parser], [$1], [$2])])
+m4_pushdef([AT_PURE_AND_LOC_IF],
+[m4_bmatch([$3], [%locations.*%pure-parser\|%pure-parser.*%locations],
+           [$1], [$2])])
+m4_pushdef([AT_GLR_OR_PARAM_IF],
+[m4_bmatch([$3], [%glr-parser\|%parse-param], [$1], [$2])])
+
+# yyerror receives the location if %location & %pure & (%glr or %parse-param).
+m4_pushdef([AT_YYERROR_ARG_LOC_IF],
+[AT_GLR_OR_PARAM_IF([AT_PURE_AND_LOC_IF([$1], [$2])],
+                    [$2])])
+# yyerror cannot see the locations if !glr & pure.
+m4_pushdef([AT_YYERROR_SEES_LOC_IF],
+[AT_LOCATION_IF([AT_GLR_IF([$1],
+                           [AT_PURE_IF([$2], [$1])])],
+                [$2])])
+])
+
+
+# AT_CALC_POPDEFS
+# ---------------
+m4_define([AT_CHECK_POPDEFS],
+[m4_popdef([AT_YYERROR_SEES_LOC_IF])
+m4_popdef([AT_YYERROR_ARG_LOC_IF])
+m4_popdef([AT_GLR_OR_PARAM_IF])
+m4_popdef([AT_PURE_AND_LOC_IF])
+m4_popdef([AT_GLR_IF])
+m4_popdef([AT_LOCATION_IF])
+m4_popdef([AT_PARAM_IF])
+])
+
+
+
 # AT_CHECK_CALC([BISON-OPTIONS])
 # ------------------------------
 # Start a testing chunk which compiles `calc' grammar with
@@ -422,6 +471,8 @@ m4_define([AT_CHECK_CALC],
 [# We use integers to avoid dependencies upon the precision of doubles.
 AT_SETUP([Calculator $1])
 
+AT_CHECK_PUSHDEFS($[1], $[2], [$1])
+
 AT_DATA_CALC_Y([$1])
 
 # Specify the output files to avoid problems on different file systems.
@@ -473,6 +524,8 @@ _AT_CHECK_CALC_ERROR([$1], [(1 ++ 2) + (0 0) = 1], [82],
 1.15-1.16: parse error, unexpected "number"
 calc: error: 0 != 1])
 
+AT_CHECK_POPDEFS
+
 AT_CLEANUP
 ])# AT_CHECK_CALC
 
@@ -508,7 +561,9 @@ AT_CHECK_CALC_LALR([%error-verbose %locations %defines %name-prefix="calc" %verb
 AT_CHECK_CALC_LALR([%debug])
 AT_CHECK_CALC_LALR([%error-verbose %debug %locations %defines %name-prefix="calc" %verbose %yacc])
 
-# AT_CHECK_CALC_LALR([%pure-parser %error-verbose %debug %locations %defines %name-prefix="calc" %verbose %yacc])
+AT_CHECK_CALC_LALR([%pure-parser %error-verbose %debug %locations %defines %name-prefix="calc" %verbose %yacc])
+
+AT_CHECK_CALC_LALR([%pure-parser %error-verbose %debug %locations %defines %name-prefix="calc" %verbose %yacc %parse-param "value_t *result", "result" %parse-param "int *count", "count"])
 
 
 # ----------------------- #
@@ -541,4 +596,6 @@ AT_CHECK_CALC_GLR([%error-verbose %locations %defines %name-prefix="calc" %verbo
 AT_CHECK_CALC_GLR([%debug])
 AT_CHECK_CALC_GLR([%error-verbose %debug %locations %defines %name-prefix="calc" %verbose %yacc])
 
-# AT_CHECK_CALC_GLR([%pure-parser %error-verbose %debug %locations %defines %name-prefix="calc" %verbose %yacc])
+AT_CHECK_CALC_GLR([%pure-parser %error-verbose %debug %locations %defines %name-prefix="calc" %verbose %yacc])
+
+AT_CHECK_CALC_GLR([%pure-parser %error-verbose %debug %locations %defines %name-prefix="calc" %verbose %yacc %parse-param "value_t *result", "result" %parse-param "int *count", "count"])
index 9562b13..61c7f50 100644 (file)
@@ -36,7 +36,11 @@ $1
 ]m4_bmatch([$2], [stmtMerge],
 [ static YYSTYPE stmtMerge (YYSTYPE x0, YYSTYPE x1);])[
   #define YYINITDEPTH 10
-  int yyerror (const char *s);
+  int yyerror (const char *s
+#if YYPURE && YYLSP_NEEDED
+               , YYLTYPE *yylocation
+#endif
+              );
 
   #if YYPURE
 ]m4_bmatch([$1], [location],
@@ -130,7 +134,7 @@ yylex ()
          break;
        default:
          if (isalpha (c))
-           { 
+           {
              i = 0;
 
              do
@@ -153,8 +157,15 @@ yylex ()
 }
 
 int
-yyerror (const char *s)
+yyerror (const char *s
+#if YYPURE && YYLSP_NEEDED
+        , YYLTYPE *yylocation
+#endif
+        )
 {
+#if YYPURE && YYLSP_NEEDED
+  (void) *yylocation;
+#endif
   fprintf (stderr, "%s\n", s);
   return 0;
 }