]> git.saurik.com Git - bison.git/commitdiff
parse.lac: implement as %define variable.
authorJoel E. Denny <joeldenny@joeldenny.org>
Sat, 11 Dec 2010 16:13:33 +0000 (11:13 -0500)
committerJoel E. Denny <joeldenny@joeldenny.org>
Sat, 11 Dec 2010 19:43:43 +0000 (14:43 -0500)
LAC = lookahead correction.  See discussion at
<http://lists.gnu.org/archive/html/bison-patches/2009-09/msg00034.html>.
However, one point there must be corrected: because of %nonassoc,
LAC is *not* always redundant for lr.type=canonical-lr.
* data/yacc.c: Accept values of "none" (default) or "full" for
parse.lac.  Accept %define parse.lac.es-capacity to specify
capacity of LAC's temporary exploratory stack.  It defaults to 20
and, for now, will not grow dynamically.
(b4_lac_flag, b4_lac_if): New m4 macros.  Evaluate as true for
parse.lac!=none.
(YYBACKUP): Invoke YY_LAC_DISCARD.
(YY_LAC_ESTABLISH, YY_LAC_DISCARD): New cpp macros that invoke
yy_lac and track when it needs to be invoked
(yy_lac): New function that, given the current stack, determines
whether a token can eventually be shifted.  Return status mimics
yyparse return status.
(yysyntax_error): Change yystate argument to yyssp so stack top
can be passed to yy_lac.  If LAC is requested, build expected
token list by invoking yy_lac for every token instead of just
checking the current state for lookaheads.  Return 2 if yy_lac
exhausts memory.
(yyparse, yypush_parse): Use local variable yy_lac_established and
cpp macros YY_LAC_ESTABLISH and YY_LAC_DISCARD to implement LAC.
Update yysyntax_error invocation.  Add yyexhaustedlab code if LAC
is requested.
* tests/conflicts.at (%nonassoc and eof): Extend to check the
effect of each of -Dlr.type=canonical-lr and -Dparse.lac=full.
(parse.error=verbose and consistent errors): Likewise.
(LAC: %nonassoc requires splitting canonical LR states): New test
group demonstrating how LAC can fix canonical LR.
* tests/input.at (LAC: Errors for %define): New test group.
* tests/regression.at (LAC: Exploratory stack): New test group.
(LAC: Memory exhaustion): New test group.

ChangeLog
data/yacc.c
src/parse-gram.c
src/parse-gram.h
tests/conflicts.at
tests/input.at
tests/regression.at

index 154fd3507987ffc2742a5a833c28a5017de408f6..63d41ed6375c549295348762f821bbeb2c4c2ad2 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,40 @@
+2010-12-11  Joel E. Denny  <jdenny@clemson.edu>
+
+       parse.lac: implement as %define variable.
+       LAC = lookahead correction.  See discussion at
+       <http://lists.gnu.org/archive/html/bison-patches/2009-09/msg00034.html>.
+       However, one point there must be corrected: because of %nonassoc,
+       LAC is *not* always redundant for lr.type=canonical-lr.
+       * data/yacc.c: Accept values of "none" (default) or "full" for
+       parse.lac.  Accept %define parse.lac.es-capacity to specify
+       capacity of LAC's temporary exploratory stack.  It defaults to 20
+       and, for now, will not grow dynamically.
+       (b4_lac_flag, b4_lac_if): New m4 macros.  Evaluate as true for
+       parse.lac!=none.
+       (YYBACKUP): Invoke YY_LAC_DISCARD.
+       (YY_LAC_ESTABLISH, YY_LAC_DISCARD): New cpp macros that invoke
+       yy_lac and track when it needs to be invoked
+       (yy_lac): New function that, given the current stack, determines
+       whether a token can eventually be shifted.  Return status mimics
+       yyparse return status.
+       (yysyntax_error): Change yystate argument to yyssp so stack top
+       can be passed to yy_lac.  If LAC is requested, build expected
+       token list by invoking yy_lac for every token instead of just
+       checking the current state for lookaheads.  Return 2 if yy_lac
+       exhausts memory.
+       (yyparse, yypush_parse): Use local variable yy_lac_established and
+       cpp macros YY_LAC_ESTABLISH and YY_LAC_DISCARD to implement LAC.
+       Update yysyntax_error invocation.  Add yyexhaustedlab code if LAC
+       is requested.
+       * tests/conflicts.at (%nonassoc and eof): Extend to check the
+       effect of each of -Dlr.type=canonical-lr and -Dparse.lac=full.
+       (parse.error=verbose and consistent errors): Likewise.
+       (LAC: %nonassoc requires splitting canonical LR states): New test
+       group demonstrating how LAC can fix canonical LR.
+       * tests/input.at (LAC: Errors for %define): New test group.
+       * tests/regression.at (LAC: Exploratory stack): New test group.
+       (LAC: Memory exhaustion): New test group.
+
 2010-11-21  Joel E. Denny  <jdenny@clemson.edu>
 
        build: use gnulib's new bootstrap_sync option.
 2010-11-21  Joel E. Denny  <jdenny@clemson.edu>
 
        build: use gnulib's new bootstrap_sync option.
index 5cf15eed5d4ed1e1cfad1f32c617e9edd3bd135f..5ba564e87eb58da3d51592f601c57626bae38fbf 100644 (file)
@@ -38,6 +38,16 @@ b4_use_push_for_pull_if([
   b4_push_if([m4_define([b4_use_push_for_pull_flag], [[0]])],
              [m4_define([b4_push_flag], [[1]])])])
 
   b4_push_if([m4_define([b4_use_push_for_pull_flag], [[0]])],
              [m4_define([b4_push_flag], [[1]])])])
 
+# Check the value of %define parse.lac, where LAC stands for lookahead
+# correction.
+b4_percent_define_default([[parse.lac]], [[none]])
+b4_percent_define_default([[parse.lac.es-capacity]], [[20]])
+b4_percent_define_check_values([[[[parse.lac]], [[full]], [[none]]]])
+b4_define_flag_if([lac])
+m4_define([b4_lac_flag],
+          [m4_if(b4_percent_define_get([[parse.lac]]),
+                 [none], [[0]], [[1]])])
+
 m4_include(b4_pkgdatadir/[c.m4])
 
 ## ---------------- ##
 m4_include(b4_pkgdatadir/[c.m4])
 
 ## ---------------- ##
@@ -629,7 +639,8 @@ do                                                          \
     {                                                          \
       yychar = (Token);                                                \
       yylval = (Value);                                                \
     {                                                          \
       yychar = (Token);                                                \
       yylval = (Value);                                                \
-      YYPOPSTACK (1);                                          \
+      YYPOPSTACK (1);                                          \]b4_lac_if([[
+      YY_LAC_DISCARD ("YYBACKUP");                             \]])[
       goto yybackup;                                           \
     }                                                          \
   else                                                         \
       goto yybackup;                                           \
     }                                                          \
   else                                                         \
@@ -813,9 +824,173 @@ int yydebug;
 
 #ifndef YYMAXDEPTH
 # define YYMAXDEPTH ]b4_stack_depth_max[
 
 #ifndef YYMAXDEPTH
 # define YYMAXDEPTH ]b4_stack_depth_max[
+#endif]b4_lac_if([[
+
+/* Establish the initial context for the current lookahead if no initial
+   context is currently established.
+
+   We define a context as a snapshot of the parser stacks.  We define
+   the initial context for a lookahead as the context in which the
+   parser initially examines that lookahead in order to select a
+   syntactic action.  Thus, if the lookahead eventually proves
+   syntactically unacceptable (possibly in a later context reached via a
+   series of reductions), the initial context can be used to determine
+   the exact set of tokens that would be syntactically acceptable in the
+   lookahead's place.  Moreover, it is the context after which any
+   further semantic actions would be erroneous because they would be
+   determined by a syntactically unacceptable token.
+
+   YY_LAC_ESTABLISH should be invoked when a reduction is about to be
+   performed in an inconsistent state (which, for the purposes of LAC,
+   includes consistent states that don't know they're consistent because
+   their default reductions have been disabled).  Iff there is a
+   lookahead token, it should also be invoked before reporting a syntax
+   error.  This latter case is for the sake of the debugging output.
+
+   For parse.lac=full, the implementation of YY_LAC_ESTABLISH is as
+   follows.  If no initial context is currently established for the
+   current lookahead, then check if that lookahead can eventually be
+   shifted if syntactic actions continue from the current context.
+   Report a syntax error if it cannot.  */
+#define YY_LAC_ESTABLISH                                       \
+do {                                                           \
+  if (!yy_lac_established)                                     \
+    {                                                          \
+      YYDPRINTF ((stderr,                                      \
+                  "LAC: initial context established for %s\n", \
+                  yytname[yytoken]));                          \
+      yy_lac_established = 1;                                  \
+      {                                                        \
+        int yy_lac_status =                                    \
+          yy_lac (yyssp, yytoken);                             \
+        if (yy_lac_status == 2)                                \
+          goto yyexhaustedlab;                                 \
+        if (yy_lac_status == 1)                                \
+          goto yyerrlab;                                       \
+      }                                                        \
+    }                                                          \
+} while (YYID (0))
+
+/* Discard any previous initial lookahead context because of Event,
+   which may be a lookahead change or an invalidation of the currently
+   established initial context for the current lookahead.
+
+   The most common example of a lookahead change is a shift.  An example
+   of both cases is syntax error recovery.  That is, a syntax error
+   occurs when the lookahead is syntactically erroneous for the
+   currently established initial context, so error recovery manipulates
+   the parser stacks to try to find a new initial context in which the
+   current lookahead is syntactically acceptable.  If it fails to find
+   such a context, it discards the lookahead.  */
+#if YYDEBUG
+# define YY_LAC_DISCARD(Event)                                           \
+do {                                                                     \
+  if (yy_lac_established)                                                \
+    {                                                                    \
+      if (yydebug)                                                       \
+        YYFPRINTF (stderr, "LAC: initial context discarded due to "      \
+                   Event "\n");                                          \
+      yy_lac_established = 0;                                            \
+    }                                                                    \
+} while (YYID (0))
+#else
+# define YY_LAC_DISCARD(Event) yy_lac_established = 0
 #endif
 
 #endif
 
-\f
+/* Given the stack whose top is *YYSSP, return 0 iff YYTOKEN can
+   eventually (after perhaps some reductions) be shifted, and return 1
+   if not.  Return 2 if memory is exhausted.  */
+static int
+yy_lac (yytype_int16 *yyssp, int yytoken)
+{
+  yytype_int16 *yyes_prev = yyssp;
+  yytype_int16 yyes@{]b4_percent_define_get([[parse.lac.es-capacity]])[@};
+  yytype_int16 *yyesp = yyes_prev;
+  YYDPRINTF ((stderr, "LAC: checking lookahead %s:", yytname[yytoken]));
+  if (yytoken == YYUNDEFTOK)
+    {
+      YYDPRINTF ((stderr, " Always Err\n"));
+      return 1;
+    }
+  while (1)
+    {
+      int yyrule = yypact[*yyesp];
+      if (yypact_value_is_default (yyrule)
+          || (yyrule += yytoken) < 0 || YYLAST < yyrule
+          || yycheck[yyrule] != yytoken)
+        {
+          yyrule = yydefact[*yyesp];
+          if (yyrule == 0)
+            {
+              YYDPRINTF ((stderr, " Err\n"));
+              return 1;
+            }
+        }
+      else
+        {
+          yyrule = yytable[yyrule];
+          if (yytable_value_is_error (yyrule))
+            {
+              YYDPRINTF ((stderr, " Err\n"));
+              return 1;
+            }
+          if (0 < yyrule)
+            {
+              YYDPRINTF ((stderr, " S%d\n", yyrule));
+              return 0;
+            }
+          yyrule = -yyrule;
+        }
+      {
+        YYSIZE_T yylen = yyr2[yyrule];
+        YYDPRINTF ((stderr, " R%d", yyrule - 1));
+        if (yyesp != yyes_prev)
+          {
+            YYSIZE_T yysize = yyesp - yyes + 1;
+            if (yylen < yysize)
+              {
+                yyesp -= yylen;
+                yylen = 0;
+              }
+            else
+              {
+                yylen -= yysize;
+                yyesp = yyes_prev;
+              }
+          }
+        if (yylen)
+          yyesp = yyes_prev -= yylen;
+      }
+      {
+        int yystate;
+        {
+          int yylhs = yyr1[yyrule] - YYNTOKENS;
+          yystate = yypgoto[yylhs] + *yyesp;
+          if (yystate < 0 || YYLAST < yystate
+              || yycheck[yystate] != *yyesp)
+            yystate = yydefgoto[yylhs];
+          else
+            yystate = yytable[yystate];
+        }
+        if (yyesp == yyes_prev)
+          {
+            yyesp = yyes;
+            *yyesp = yystate;
+          }
+        else
+          {
+            if (yyesp == yyes + (sizeof yyes / sizeof *yyes) - 1)
+              {
+                YYDPRINTF ((stderr, " (max stack size exceeded)\n"));
+                return 2;
+              }
+            *++yyesp = yystate;
+          }
+        YYDPRINTF ((stderr, " G%d", *yyesp));
+      }
+    }
+}]])[
+
 
 #if YYERROR_VERBOSE
 
 
 #if YYERROR_VERBOSE
 
@@ -904,15 +1079,18 @@ yytnamerr (char *yyres, const char *yystr)
 # endif
 
 /* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
 # endif
 
 /* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
-   about the unexpected token YYTOKEN while in state YYSTATE.
+   about the unexpected token YYTOKEN for the state stack whose top is
+   YYSSP.]b4_lac_if([[  In order to see if a particular token T is a
+   valid looakhead, invoke yy_lac (YYSSP, T).]])[
 
    Return 0 if *YYMSG was successfully written.  Return 1 if *YYMSG is
    not large enough to hold the message.  In that case, also set
    *YYMSG_ALLOC to the required number of bytes.  Return 2 if the
 
    Return 0 if *YYMSG was successfully written.  Return 1 if *YYMSG is
    not large enough to hold the message.  In that case, also set
    *YYMSG_ALLOC to the required number of bytes.  Return 2 if the
-   required number of bytes is too large to store.  */
+   required number of bytes is too large to store]b4_lac_if([[ or if
+   yy_lac returned 2]])[.  */
 static int
 yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
 static int
 yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
-                int yystate, int yytoken)
+                yytype_int16 *yyssp, int yytoken)
 {
   YYSIZE_T yysize0 = yytnamerr (0, yytname[yytoken]);
   YYSIZE_T yysize = yysize0;
 {
   YYSIZE_T yysize0 = yytnamerr (0, yytname[yytoken]);
   YYSIZE_T yysize = yysize0;
@@ -943,7 +1121,12 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
      - Don't assume there isn't a lookahead just because this state is a
        consistent state with a default action.  There might have been a
        previous inconsistent state, consistent state with a non-default
      - Don't assume there isn't a lookahead just because this state is a
        consistent state with a default action.  There might have been a
        previous inconsistent state, consistent state with a non-default
-       action, or user semantic action that manipulated yychar.
+       action, or user semantic action that manipulated yychar.]b4_lac_if([[
+       In the first two cases, it might appear that the current syntax
+       error should have been detected in the previous state when yy_lac
+       was invoked.  However, at that time, there might have been a
+       different syntax error that discarded a different initial context
+       during error recovery, leaving behind the current lookahead.]], [[
      - Of course, the expected token list depends on states to have
        correct lookahead information, and it depends on the parser not
        to perform extra reductions after fetching a lookahead from the
      - Of course, the expected token list depends on states to have
        correct lookahead information, and it depends on the parser not
        to perform extra reductions after fetching a lookahead from the
@@ -951,26 +1134,39 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
        (from LALR or IELR) and default reductions corrupt the expected
        token list.  However, the list is correct for canonical LR with
        one exception: it will still contain any token that will not be
        (from LALR or IELR) and default reductions corrupt the expected
        token list.  However, the list is correct for canonical LR with
        one exception: it will still contain any token that will not be
-       accepted due to an error action in a later state.
+       accepted due to an error action in a later state.]])[
   */
   if (yytoken != YYEMPTY)
     {
   */
   if (yytoken != YYEMPTY)
     {
-      int yyn = yypact[yystate];
+      int yyn = yypact[*yyssp];]b4_lac_if([[
+      YYDPRINTF ((stderr, "Constructing syntax error message\n"));]])[
       yyarg[yycount++] = yytname[yytoken];
       if (!yypact_value_is_default (yyn))
       yyarg[yycount++] = yytname[yytoken];
       if (!yypact_value_is_default (yyn))
-        {
+        {]b4_lac_if([], [[
           /* Start YYX at -YYN if negative to avoid negative indexes in
              YYCHECK.  In other words, skip the first -YYN actions for
              this state because they are default actions.  */
           int yyxbegin = yyn < 0 ? -yyn : 0;
           /* Stay within bounds of both yycheck and yytname.  */
           int yychecklim = YYLAST - yyn + 1;
           /* Start YYX at -YYN if negative to avoid negative indexes in
              YYCHECK.  In other words, skip the first -YYN actions for
              this state because they are default actions.  */
           int yyxbegin = yyn < 0 ? -yyn : 0;
           /* Stay within bounds of both yycheck and yytname.  */
           int yychecklim = YYLAST - yyn + 1;
-          int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
-          int yyx;
+          int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;]])[
+          int yyx;]b4_lac_if([[
+
+          for (yyx = 0; yyx < YYNTOKENS; ++yyx)
+            if (yyx != YYTERROR && yyx != YYUNDEFTOK)
+              {
+                {
+                  int yy_lac_status = yy_lac (yyssp, yyx);
+                  if (yy_lac_status == 2)
+                    return 2;
+                  if (yy_lac_status == 1)
+                    continue;
+                }]], [[
+
           for (yyx = yyxbegin; yyx < yyxend; ++yyx)
             if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
                 && !yytable_value_is_error (yytable[yyx + yyn]))
           for (yyx = yyxbegin; yyx < yyxend; ++yyx)
             if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
                 && !yytable_value_is_error (yytable[yyx + yyn]))
-              {
+              {]])[
                 if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
                   {
                     yycount = 1;
                 if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
                   {
                     yycount = 1;
@@ -984,12 +1180,16 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
                   return 2;
                 yysize = yysize1;
               }
                   return 2;
                 yysize = yysize1;
               }
-        }
+        }]b4_lac_if([[
+# if YYDEBUG
+      else if (yydebug)
+        YYFPRINTF (stderr, "No expected tokens.\n");
+# endif]])[
     }
 
   switch (yycount)
     {
     }
 
   switch (yycount)
     {
-#define YYCASE_(N, S)                       \
+# define YYCASE_(N, S)                      \
       case N:                               \
         yyformat = S;                       \
       break
       case N:                               \
         yyformat = S;                       \
       break
@@ -999,7 +1199,7 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
       YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
       YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
       YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
       YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
       YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
       YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
-#undef YYCASE_
+# undef YYCASE_
     }
 
   yysize1 = yysize + yystrlen (yyformat);
     }
 
   yysize1 = yysize + yystrlen (yyformat);
@@ -1037,7 +1237,6 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
   return 0;
 }
 #endif /* YYERROR_VERBOSE */
   return 0;
 }
 #endif /* YYERROR_VERBOSE */
-\f
 
 ]b4_yydestruct_generate([b4_c_function_def])b4_push_if([], [[
 
 
 ]b4_yydestruct_generate([b4_c_function_def])b4_push_if([], [[
 
@@ -1172,7 +1371,8 @@ b4_c_function_def([[yyparse]], [[int]], b4_parse_param)[
   YYLTYPE yypushed_loc = yylloc;]])
 ])],
   [b4_declare_parser_state_variables
   YYLTYPE yypushed_loc = yylloc;]])
 ])],
   [b4_declare_parser_state_variables
-])[
+])b4_lac_if([[
+  int yy_lac_established = 0;]])[
   int yyn;
   int yyresult;
   /* Lookahead token as an internal (translated) token number.  */
   int yyn;
   int yyresult;
   /* Lookahead token as an internal (translated) token number.  */
@@ -1379,13 +1579,18 @@ yyread_pushed_token:]])[
   /* If the proper action on seeing token YYTOKEN is to reduce or to
      detect an error, take that action.  */
   yyn += yytoken;
   /* If the proper action on seeing token YYTOKEN is to reduce or to
      detect an error, take that action.  */
   yyn += yytoken;
-  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
-    goto yydefault;
+  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)]b4_lac_if([[
+    {
+      YY_LAC_ESTABLISH;
+      goto yydefault;
+    }]], [[
+    goto yydefault;]])[
   yyn = yytable[yyn];
   if (yyn <= 0)
     {
       if (yytable_value_is_error (yyn))
   yyn = yytable[yyn];
   if (yyn <= 0)
     {
       if (yytable_value_is_error (yyn))
-       goto yyerrlab;
+        goto yyerrlab;]b4_lac_if([[
+      YY_LAC_ESTABLISH;]])[
       yyn = -yyn;
       goto yyreduce;
     }
       yyn = -yyn;
       goto yyreduce;
     }
@@ -1399,7 +1604,8 @@ yyread_pushed_token:]])[
   YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
 
   /* Discard the shifted token.  */
   YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
 
   /* Discard the shifted token.  */
-  yychar = YYEMPTY;
+  yychar = YYEMPTY;]b4_lac_if([[
+  YY_LAC_DISCARD ("shift");]])[
 
   yystate = yyn;
   *++yyvsp = yylval;
 
   yystate = yyn;
   *++yyvsp = yylval;
@@ -1437,12 +1643,22 @@ yyreduce:
 ]b4_locations_if(
 [[  /* Default location.  */
   YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen);]])[
 ]b4_locations_if(
 [[  /* Default location.  */
   YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen);]])[
-  YY_REDUCE_PRINT (yyn);
+  YY_REDUCE_PRINT (yyn);]b4_lac_if([[
+  {
+    int yychar_backup = yychar;
+    switch (yyn)
+      {
+        ]b4_user_actions[
+        default: break;
+      }
+    if (yychar_backup != yychar)
+      YY_LAC_DISCARD ("yychar change");
+  }]], [[
   switch (yyn)
     {
       ]b4_user_actions[
       default: break;
   switch (yyn)
     {
       ]b4_user_actions[
       default: break;
-    }
+    }]])[
   /* User semantic actions sometimes alter yychar, and that requires
      that yytoken be updated with the new translation.  We take the
      approach of translating immediately before every use of yytoken.
   /* User semantic actions sometimes alter yychar, and that requires
      that yytoken be updated with the new translation.  We take the
      approach of translating immediately before every use of yytoken.
@@ -1493,11 +1709,14 @@ yyerrlab:
 #if ! YYERROR_VERBOSE
       yyerror (]b4_yyerror_args[YY_("syntax error"));
 #else
 #if ! YYERROR_VERBOSE
       yyerror (]b4_yyerror_args[YY_("syntax error"));
 #else
-# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, yystate, \
+# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, yyssp, \
                                         yytoken)
       {
         char const *yymsgp = YY_("syntax error");
                                         yytoken)
       {
         char const *yymsgp = YY_("syntax error");
-        int yysyntax_error_status = YYSYNTAX_ERROR;
+        int yysyntax_error_status;]b4_lac_if([[
+        if (yychar != YYEMPTY)
+          YY_LAC_ESTABLISH;]])[
+        yysyntax_error_status = YYSYNTAX_ERROR;
         if (yysyntax_error_status == 0)
           yymsgp = yymsg;
         else if (yysyntax_error_status == 1)
         if (yysyntax_error_status == 0)
           yymsgp = yymsg;
         else if (yysyntax_error_status == 1)
@@ -1602,7 +1821,11 @@ yyerrlab1:
       YYPOPSTACK (1);
       yystate = *yyssp;
       YY_STACK_PRINT (yyss, yyssp);
       YYPOPSTACK (1);
       yystate = *yyssp;
       YY_STACK_PRINT (yyss, yyssp);
-    }
+    }]b4_lac_if([[
+
+  /* If the stack popping above didn't lose the initial context for the
+     current lookahead token, the shift below will for sure.  */
+  YY_LAC_DISCARD ("error recovery");]])[
 
   *++yyvsp = yylval;
 ]b4_locations_if([[
 
   *++yyvsp = yylval;
 ]b4_locations_if([[
@@ -1633,7 +1856,7 @@ yyabortlab:
   yyresult = 1;
   goto yyreturn;
 
   yyresult = 1;
   goto yyreturn;
 
-#if !defined(yyoverflow) || YYERROR_VERBOSE
+#if ]b4_lac_if([[1]], [[!defined(yyoverflow) || YYERROR_VERBOSE]])[
 /*-------------------------------------------------.
 | yyexhaustedlab -- memory exhaustion comes here.  |
 `-------------------------------------------------*/
 /*-------------------------------------------------.
 | yyexhaustedlab -- memory exhaustion comes here.  |
 `-------------------------------------------------*/
index f55a15b67802f149f87922e5b2c5f8f8f665ec4d..9cf16f9ba26370756b22e3749d03a0e9c8172131 100644 (file)
@@ -1,4 +1,4 @@
-/* A Bison parser, made by GNU Bison 2.4.537-34db.  */
+/* A Bison parser, made by GNU Bison 2.4.542-10bae.  */
 
 /* Implementation for Bison's Yacc-like parsers in C
 
 
 /* Implementation for Bison's Yacc-like parsers in C
 
@@ -45,7 +45,7 @@
 #define YYBISON 1
 
 /* Bison version.  */
 #define YYBISON 1
 
 /* Bison version.  */
-#define YYBISON_VERSION "2.4.537-34db"
+#define YYBISON_VERSION "2.4.542-10bae"
 
 /* Skeleton name.  */
 #define YYSKELETON_NAME "yacc.c"
 
 /* Skeleton name.  */
 #define YYSKELETON_NAME "yacc.c"
@@ -73,7 +73,7 @@
 #define yylloc          gram_lloc
 
 /* Copy the first part of user declarations.  */
 #define yylloc          gram_lloc
 
 /* Copy the first part of user declarations.  */
-/* Line 252 of yacc.c  */
+/* Line 262 of yacc.c  */
 #line 1 "src/parse-gram.y"
 /* Bison Grammar Parser                             -*- C -*-
 
 #line 1 "src/parse-gram.y"
 /* Bison Grammar Parser                             -*- C -*-
 
@@ -128,7 +128,7 @@ static void gram_error (location const *, char const *);
 
 static char const *char_name (char);
 
 
 static char const *char_name (char);
 
-/* Line 252 of yacc.c  */
+/* Line 262 of yacc.c  */
 #line 133 "src/parse-gram.c"
 
 /* Enabling traces.  */
 #line 133 "src/parse-gram.c"
 
 /* Enabling traces.  */
@@ -150,7 +150,7 @@ static char const *char_name (char);
 #endif
 
 /* "%code requires" blocks.  */
 #endif
 
 /* "%code requires" blocks.  */
-/* Line 272 of yacc.c  */
+/* Line 282 of yacc.c  */
 #line 202 "src/parse-gram.y"
 
 # ifndef PARAM_TYPE
 #line 202 "src/parse-gram.y"
 
 # ifndef PARAM_TYPE
@@ -165,7 +165,7 @@ static char const *char_name (char);
 # endif
 
 
 # endif
 
 
-/* Line 272 of yacc.c  */
+/* Line 282 of yacc.c  */
 #line 170 "src/parse-gram.c"
 
 /* Tokens.  */
 #line 170 "src/parse-gram.c"
 
 /* Tokens.  */
@@ -294,7 +294,7 @@ static char const *char_name (char);
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 typedef union YYSTYPE
 {
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 typedef union YYSTYPE
 {
-/* Line 277 of yacc.c  */
+/* Line 287 of yacc.c  */
 #line 88 "src/parse-gram.y"
 
   assoc assoc;
 #line 88 "src/parse-gram.y"
 
   assoc assoc;
@@ -307,13 +307,13 @@ typedef union YYSTYPE
   uniqstr uniqstr;
   unsigned char character;
 
   uniqstr uniqstr;
   unsigned char character;
 
-/* Line 277 of yacc.c  */
+/* Line 287 of yacc.c  */
 #line 226 "src/parse-gram.y"
 
   param_type param;
 
 
 #line 226 "src/parse-gram.y"
 
   param_type param;
 
 
-/* Line 277 of yacc.c  */
+/* Line 287 of yacc.c  */
 #line 318 "src/parse-gram.c"
 } YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
 #line 318 "src/parse-gram.c"
 } YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
@@ -337,10 +337,10 @@ typedef struct YYLTYPE
 
 /* Copy the second part of user declarations.  */
 
 
 /* Copy the second part of user declarations.  */
 
-/* Line 327 of yacc.c  */
+/* Line 337 of yacc.c  */
 #line 342 "src/parse-gram.c"
 /* Unqualified %code blocks.  */
 #line 342 "src/parse-gram.c"
 /* Unqualified %code blocks.  */
-/* Line 328 of yacc.c  */
+/* Line 338 of yacc.c  */
 #line 56 "src/parse-gram.y"
 
   static int current_prec = 0;
 #line 56 "src/parse-gram.y"
 
   static int current_prec = 0;
@@ -355,7 +355,7 @@ typedef struct YYLTYPE
   #define YYTYPE_UINT16 uint_fast16_t
   #define YYTYPE_UINT8 uint_fast8_t
 
   #define YYTYPE_UINT16 uint_fast16_t
   #define YYTYPE_UINT8 uint_fast8_t
 
-/* Line 328 of yacc.c  */
+/* Line 338 of yacc.c  */
 #line 215 "src/parse-gram.y"
 
   /** Add a lex-param and/or a parse-param.
 #line 215 "src/parse-gram.y"
 
   /** Add a lex-param and/or a parse-param.
@@ -368,7 +368,7 @@ typedef struct YYLTYPE
   static param_type current_param = param_none;
 
 
   static param_type current_param = param_none;
 
 
-/* Line 328 of yacc.c  */
+/* Line 338 of yacc.c  */
 #line 373 "src/parse-gram.c"
 
 #ifdef short
 #line 373 "src/parse-gram.c"
 
 #ifdef short
@@ -1033,106 +1033,106 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp)
     {
             case 3: // "string"
 
     {
             case 3: // "string"
 
-/* Line 729 of yacc.c  */
+/* Line 740 of yacc.c  */
 #line 175 "src/parse-gram.y"
         { fputs (quotearg_style (c_quoting_style, ((*yyvaluep).chars)), stderr); }
 #line 175 "src/parse-gram.y"
         { fputs (quotearg_style (c_quoting_style, ((*yyvaluep).chars)), stderr); }
-/* Line 729 of yacc.c  */
+/* Line 740 of yacc.c  */
 #line 1041 "src/parse-gram.c"
         break;
 
             case 4: // "integer"
 
 #line 1041 "src/parse-gram.c"
         break;
 
             case 4: // "integer"
 
-/* Line 729 of yacc.c  */
+/* Line 740 of yacc.c  */
 #line 188 "src/parse-gram.y"
         { fprintf (stderr, "%d", ((*yyvaluep).integer)); }
 #line 188 "src/parse-gram.y"
         { fprintf (stderr, "%d", ((*yyvaluep).integer)); }
-/* Line 729 of yacc.c  */
+/* Line 740 of yacc.c  */
 #line 1050 "src/parse-gram.c"
         break;
 
             case 24: // "%<flag>"
 
 #line 1050 "src/parse-gram.c"
         break;
 
             case 24: // "%<flag>"
 
-/* Line 729 of yacc.c  */
+/* Line 740 of yacc.c  */
 #line 184 "src/parse-gram.y"
         { fprintf (stderr, "%%%s", ((*yyvaluep).uniqstr)); }
 #line 184 "src/parse-gram.y"
         { fprintf (stderr, "%%%s", ((*yyvaluep).uniqstr)); }
-/* Line 729 of yacc.c  */
+/* Line 740 of yacc.c  */
 #line 1059 "src/parse-gram.c"
         break;
 
             case 40: // "{...}"
 
 #line 1059 "src/parse-gram.c"
         break;
 
             case 40: // "{...}"
 
-/* Line 729 of yacc.c  */
+/* Line 740 of yacc.c  */
 #line 177 "src/parse-gram.y"
         { fprintf (stderr, "{\n%s\n}", ((*yyvaluep).code)); }
 #line 177 "src/parse-gram.y"
         { fprintf (stderr, "{\n%s\n}", ((*yyvaluep).code)); }
-/* Line 729 of yacc.c  */
+/* Line 740 of yacc.c  */
 #line 1068 "src/parse-gram.c"
         break;
 
             case 42: // "[identifier]"
 
 #line 1068 "src/parse-gram.c"
         break;
 
             case 42: // "[identifier]"
 
-/* Line 729 of yacc.c  */
+/* Line 740 of yacc.c  */
 #line 182 "src/parse-gram.y"
         { fprintf (stderr, "[%s]", ((*yyvaluep).uniqstr)); }
 #line 182 "src/parse-gram.y"
         { fprintf (stderr, "[%s]", ((*yyvaluep).uniqstr)); }
-/* Line 729 of yacc.c  */
+/* Line 740 of yacc.c  */
 #line 1077 "src/parse-gram.c"
         break;
 
             case 43: // "char"
 
 #line 1077 "src/parse-gram.c"
         break;
 
             case 43: // "char"
 
-/* Line 729 of yacc.c  */
+/* Line 740 of yacc.c  */
 #line 169 "src/parse-gram.y"
         { fputs (char_name (((*yyvaluep).character)), stderr); }
 #line 169 "src/parse-gram.y"
         { fputs (char_name (((*yyvaluep).character)), stderr); }
-/* Line 729 of yacc.c  */
+/* Line 740 of yacc.c  */
 #line 1086 "src/parse-gram.c"
         break;
 
             case 44: // "epilogue"
 
 #line 1086 "src/parse-gram.c"
         break;
 
             case 44: // "epilogue"
 
-/* Line 729 of yacc.c  */
+/* Line 740 of yacc.c  */
 #line 177 "src/parse-gram.y"
         { fprintf (stderr, "{\n%s\n}", ((*yyvaluep).chars)); }
 #line 177 "src/parse-gram.y"
         { fprintf (stderr, "{\n%s\n}", ((*yyvaluep).chars)); }
-/* Line 729 of yacc.c  */
+/* Line 740 of yacc.c  */
 #line 1095 "src/parse-gram.c"
         break;
 
             case 46: // "identifier"
 
 #line 1095 "src/parse-gram.c"
         break;
 
             case 46: // "identifier"
 
-/* Line 729 of yacc.c  */
+/* Line 740 of yacc.c  */
 #line 181 "src/parse-gram.y"
         { fputs (((*yyvaluep).uniqstr), stderr); }
 #line 181 "src/parse-gram.y"
         { fputs (((*yyvaluep).uniqstr), stderr); }
-/* Line 729 of yacc.c  */
+/* Line 740 of yacc.c  */
 #line 1104 "src/parse-gram.c"
         break;
 
             case 47: // "identifier:"
 
 #line 1104 "src/parse-gram.c"
         break;
 
             case 47: // "identifier:"
 
-/* Line 729 of yacc.c  */
+/* Line 740 of yacc.c  */
 #line 183 "src/parse-gram.y"
         { fprintf (stderr, "%s:", ((*yyvaluep).uniqstr)); }
 #line 183 "src/parse-gram.y"
         { fprintf (stderr, "%s:", ((*yyvaluep).uniqstr)); }
-/* Line 729 of yacc.c  */
+/* Line 740 of yacc.c  */
 #line 1113 "src/parse-gram.c"
         break;
 
             case 50: // "%{...%}"
 
 #line 1113 "src/parse-gram.c"
         break;
 
             case 50: // "%{...%}"
 
-/* Line 729 of yacc.c  */
+/* Line 740 of yacc.c  */
 #line 177 "src/parse-gram.y"
         { fprintf (stderr, "{\n%s\n}", ((*yyvaluep).chars)); }
 #line 177 "src/parse-gram.y"
         { fprintf (stderr, "{\n%s\n}", ((*yyvaluep).chars)); }
-/* Line 729 of yacc.c  */
+/* Line 740 of yacc.c  */
 #line 1122 "src/parse-gram.c"
         break;
 
             case 52: // "<tag>"
 
 #line 1122 "src/parse-gram.c"
         break;
 
             case 52: // "<tag>"
 
-/* Line 729 of yacc.c  */
+/* Line 740 of yacc.c  */
 #line 185 "src/parse-gram.y"
         { fprintf (stderr, "<%s>", ((*yyvaluep).uniqstr)); }
 #line 185 "src/parse-gram.y"
         { fprintf (stderr, "<%s>", ((*yyvaluep).uniqstr)); }
-/* Line 729 of yacc.c  */
+/* Line 740 of yacc.c  */
 #line 1131 "src/parse-gram.c"
         break;
 
             case 55: // "%param"
 
 #line 1131 "src/parse-gram.c"
         break;
 
             case 55: // "%param"
 
-/* Line 729 of yacc.c  */
+/* Line 740 of yacc.c  */
 #line 231 "src/parse-gram.y"
         {
   switch (((*yyvaluep).param))
 #line 231 "src/parse-gram.y"
         {
   switch (((*yyvaluep).param))
@@ -1146,79 +1146,79 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp)
       case param_none: aver (false); break;
     }
 }
       case param_none: aver (false); break;
     }
 }
-/* Line 729 of yacc.c  */
+/* Line 740 of yacc.c  */
 #line 1151 "src/parse-gram.c"
         break;
 
             case 72: // symbol.prec
 
 #line 1151 "src/parse-gram.c"
         break;
 
             case 72: // symbol.prec
 
-/* Line 729 of yacc.c  */
+/* Line 740 of yacc.c  */
 #line 191 "src/parse-gram.y"
         { fprintf (stderr, "%s", ((*yyvaluep).symbol)->tag); }
 #line 191 "src/parse-gram.y"
         { fprintf (stderr, "%s", ((*yyvaluep).symbol)->tag); }
-/* Line 729 of yacc.c  */
+/* Line 740 of yacc.c  */
 #line 1160 "src/parse-gram.c"
         break;
 
             case 85: // variable
 
 #line 1160 "src/parse-gram.c"
         break;
 
             case 85: // variable
 
-/* Line 729 of yacc.c  */
+/* Line 740 of yacc.c  */
 #line 181 "src/parse-gram.y"
         { fputs (((*yyvaluep).uniqstr), stderr); }
 #line 181 "src/parse-gram.y"
         { fputs (((*yyvaluep).uniqstr), stderr); }
-/* Line 729 of yacc.c  */
+/* Line 740 of yacc.c  */
 #line 1169 "src/parse-gram.c"
         break;
 
             case 86: // content.opt
 
 #line 1169 "src/parse-gram.c"
         break;
 
             case 86: // content.opt
 
-/* Line 729 of yacc.c  */
+/* Line 740 of yacc.c  */
 #line 177 "src/parse-gram.y"
         { fprintf (stderr, "{\n%s\n}", ((*yyvaluep).chars)); }
 #line 177 "src/parse-gram.y"
         { fprintf (stderr, "{\n%s\n}", ((*yyvaluep).chars)); }
-/* Line 729 of yacc.c  */
+/* Line 740 of yacc.c  */
 #line 1178 "src/parse-gram.c"
         break;
 
             case 87: // braceless
 
 #line 1178 "src/parse-gram.c"
         break;
 
             case 87: // braceless
 
-/* Line 729 of yacc.c  */
+/* Line 740 of yacc.c  */
 #line 177 "src/parse-gram.y"
         { fprintf (stderr, "{\n%s\n}", ((*yyvaluep).chars)); }
 #line 177 "src/parse-gram.y"
         { fprintf (stderr, "{\n%s\n}", ((*yyvaluep).chars)); }
-/* Line 729 of yacc.c  */
+/* Line 740 of yacc.c  */
 #line 1187 "src/parse-gram.c"
         break;
 
             case 88: // id
 
 #line 1187 "src/parse-gram.c"
         break;
 
             case 88: // id
 
-/* Line 729 of yacc.c  */
+/* Line 740 of yacc.c  */
 #line 191 "src/parse-gram.y"
         { fprintf (stderr, "%s", ((*yyvaluep).symbol)->tag); }
 #line 191 "src/parse-gram.y"
         { fprintf (stderr, "%s", ((*yyvaluep).symbol)->tag); }
-/* Line 729 of yacc.c  */
+/* Line 740 of yacc.c  */
 #line 1196 "src/parse-gram.c"
         break;
 
             case 89: // id_colon
 
 #line 1196 "src/parse-gram.c"
         break;
 
             case 89: // id_colon
 
-/* Line 729 of yacc.c  */
+/* Line 740 of yacc.c  */
 #line 192 "src/parse-gram.y"
         { fprintf (stderr, "%s:", ((*yyvaluep).symbol)->tag); }
 #line 192 "src/parse-gram.y"
         { fprintf (stderr, "%s:", ((*yyvaluep).symbol)->tag); }
-/* Line 729 of yacc.c  */
+/* Line 740 of yacc.c  */
 #line 1205 "src/parse-gram.c"
         break;
 
             case 90: // symbol
 
 #line 1205 "src/parse-gram.c"
         break;
 
             case 90: // symbol
 
-/* Line 729 of yacc.c  */
+/* Line 740 of yacc.c  */
 #line 191 "src/parse-gram.y"
         { fprintf (stderr, "%s", ((*yyvaluep).symbol)->tag); }
 #line 191 "src/parse-gram.y"
         { fprintf (stderr, "%s", ((*yyvaluep).symbol)->tag); }
-/* Line 729 of yacc.c  */
+/* Line 740 of yacc.c  */
 #line 1214 "src/parse-gram.c"
         break;
 
             case 91: // string_as_id
 
 #line 1214 "src/parse-gram.c"
         break;
 
             case 91: // string_as_id
 
-/* Line 729 of yacc.c  */
+/* Line 740 of yacc.c  */
 #line 191 "src/parse-gram.y"
         { fprintf (stderr, "%s", ((*yyvaluep).symbol)->tag); }
 #line 191 "src/parse-gram.y"
         { fprintf (stderr, "%s", ((*yyvaluep).symbol)->tag); }
-/* Line 729 of yacc.c  */
+/* Line 740 of yacc.c  */
 #line 1223 "src/parse-gram.c"
         break;
 
 #line 1223 "src/parse-gram.c"
         break;
 
@@ -1355,7 +1355,6 @@ int yydebug;
 # define YYMAXDEPTH 10000
 #endif
 
 # define YYMAXDEPTH 10000
 #endif
 
-\f
 
 #if YYERROR_VERBOSE
 
 
 #if YYERROR_VERBOSE
 
@@ -1459,7 +1458,8 @@ yytnamerr (char *yyres, const char *yystr)
 # endif
 
 /* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
 # endif
 
 /* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
-   about the unexpected token YYTOKEN while in state YYSTATE.
+   about the unexpected token YYTOKEN for the state stack whose top is
+   YYSSP.
 
    Return 0 if *YYMSG was successfully written.  Return 1 if *YYMSG is
    not large enough to hold the message.  In that case, also set
 
    Return 0 if *YYMSG was successfully written.  Return 1 if *YYMSG is
    not large enough to hold the message.  In that case, also set
@@ -1467,7 +1467,7 @@ yytnamerr (char *yyres, const char *yystr)
    required number of bytes is too large to store.  */
 static int
 yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
    required number of bytes is too large to store.  */
 static int
 yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
-                int yystate, int yytoken)
+                yytype_int16 *yyssp, int yytoken)
 {
   YYSIZE_T yysize0 = yytnamerr (0, yytname[yytoken]);
   YYSIZE_T yysize = yysize0;
 {
   YYSIZE_T yysize0 = yytnamerr (0, yytname[yytoken]);
   YYSIZE_T yysize = yysize0;
@@ -1510,7 +1510,7 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
   */
   if (yytoken != YYEMPTY)
     {
   */
   if (yytoken != YYEMPTY)
     {
-      int yyn = yypact[yystate];
+      int yyn = yypact[*yyssp];
       yyarg[yycount++] = yytname[yytoken];
       if (!yypact_value_is_default (yyn))
         {
       yyarg[yycount++] = yytname[yytoken];
       if (!yypact_value_is_default (yyn))
         {
@@ -1522,6 +1522,7 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
           int yychecklim = YYLAST - yyn + 1;
           int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
           int yyx;
           int yychecklim = YYLAST - yyn + 1;
           int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
           int yyx;
+
           for (yyx = yyxbegin; yyx < yyxend; ++yyx)
             if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
                 && !yytable_value_is_error (yytable[yyx + yyn]))
           for (yyx = yyxbegin; yyx < yyxend; ++yyx)
             if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
                 && !yytable_value_is_error (yytable[yyx + yyn]))
@@ -1544,7 +1545,7 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
 
   switch (yycount)
     {
 
   switch (yycount)
     {
-#define YYCASE_(N, S)                       \
+# define YYCASE_(N, S)                      \
       case N:                               \
         yyformat = S;                       \
       break
       case N:                               \
         yyformat = S;                       \
       break
@@ -1554,7 +1555,7 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
       YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
       YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
       YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
       YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
       YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
       YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
-#undef YYCASE_
+# undef YYCASE_
     }
 
   yysize1 = yysize + yystrlen (yyformat);
     }
 
   yysize1 = yysize + yystrlen (yyformat);
@@ -1592,7 +1593,6 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
   return 0;
 }
 #endif /* YYERROR_VERBOSE */
   return 0;
 }
 #endif /* YYERROR_VERBOSE */
-\f
 
 /*-----------------------------------------------.
 | Release the memory associated to this symbol.  |
 
 /*-----------------------------------------------.
 | Release the memory associated to this symbol.  |
@@ -1765,7 +1765,7 @@ YYLTYPE yylloc;
 #endif
 
 /* User initialization code.  */
 #endif
 
 /* User initialization code.  */
-/* Line 1230 of yacc.c  */
+/* Line 1430 of yacc.c  */
 #line 80 "src/parse-gram.y"
 {
   /* Bison's grammar can initial empty locations, hence a default
 #line 80 "src/parse-gram.y"
 {
   /* Bison's grammar can initial empty locations, hence a default
@@ -1773,7 +1773,7 @@ YYLTYPE yylloc;
   boundary_set (&yylloc.start, current_file, 1, 1);
   boundary_set (&yylloc.end, current_file, 1, 1);
 }
   boundary_set (&yylloc.start, current_file, 1, 1);
   boundary_set (&yylloc.end, current_file, 1, 1);
 }
-/* Line 1230 of yacc.c  */
+/* Line 1430 of yacc.c  */
 #line 1778 "src/parse-gram.c"
   yylsp[0] = yylloc;
 
 #line 1778 "src/parse-gram.c"
   yylsp[0] = yylloc;
 
@@ -1905,7 +1905,7 @@ yybackup:
   if (yyn <= 0)
     {
       if (yytable_value_is_error (yyn))
   if (yyn <= 0)
     {
       if (yytable_value_is_error (yyn))
-       goto yyerrlab;
+        goto yyerrlab;
       yyn = -yyn;
       goto yyreduce;
     }
       yyn = -yyn;
       goto yyreduce;
     }
@@ -1960,7 +1960,7 @@ yyreduce:
   switch (yyn)
     {
         case 6:
   switch (yyn)
     {
         case 6:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 267 "src/parse-gram.y"
     {
       code_props plain_code;
 #line 267 "src/parse-gram.y"
     {
       code_props plain_code;
@@ -1971,106 +1971,106 @@ yyreduce:
                         plain_code.code, (yylsp[0]));
       code_scanner_last_string_free ();
     }
                         plain_code.code, (yylsp[0]));
       code_scanner_last_string_free ();
     }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 1976 "src/parse-gram.c"
     break;
 
   case 7:
 #line 1976 "src/parse-gram.c"
     break;
 
   case 7:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 277 "src/parse-gram.y"
     {
       muscle_percent_define_ensure ((yyvsp[0].uniqstr), (yylsp[0]), true);
     }
 #line 277 "src/parse-gram.y"
     {
       muscle_percent_define_ensure ((yyvsp[0].uniqstr), (yylsp[0]), true);
     }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 1986 "src/parse-gram.c"
     break;
 
   case 8:
 #line 1986 "src/parse-gram.c"
     break;
 
   case 8:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 281 "src/parse-gram.y"
     {
       muscle_percent_define_insert ((yyvsp[-1].uniqstr), (yylsp[-1]), (yyvsp[0].chars),
                                     MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE);
     }
 #line 281 "src/parse-gram.y"
     {
       muscle_percent_define_insert ((yyvsp[-1].uniqstr), (yylsp[-1]), (yyvsp[0].chars),
                                     MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE);
     }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 1997 "src/parse-gram.c"
     break;
 
   case 9:
 #line 1997 "src/parse-gram.c"
     break;
 
   case 9:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 285 "src/parse-gram.y"
     { defines_flag = true; }
 #line 285 "src/parse-gram.y"
     { defines_flag = true; }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2005 "src/parse-gram.c"
     break;
 
   case 10:
 #line 2005 "src/parse-gram.c"
     break;
 
   case 10:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 287 "src/parse-gram.y"
     {
       defines_flag = true;
       spec_defines_file = xstrdup ((yyvsp[0].chars));
     }
 #line 287 "src/parse-gram.y"
     {
       defines_flag = true;
       spec_defines_file = xstrdup ((yyvsp[0].chars));
     }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2016 "src/parse-gram.c"
     break;
 
   case 11:
 #line 2016 "src/parse-gram.c"
     break;
 
   case 11:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 292 "src/parse-gram.y"
     {
       muscle_percent_define_insert ("parse.error", (yylsp[0]), "verbose",
                                     MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE);
     }
 #line 292 "src/parse-gram.y"
     {
       muscle_percent_define_insert ("parse.error", (yylsp[0]), "verbose",
                                     MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE);
     }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2027 "src/parse-gram.c"
     break;
 
   case 12:
 #line 2027 "src/parse-gram.c"
     break;
 
   case 12:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 296 "src/parse-gram.y"
     { expected_sr_conflicts = (yyvsp[0].integer); }
 #line 296 "src/parse-gram.y"
     { expected_sr_conflicts = (yyvsp[0].integer); }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2035 "src/parse-gram.c"
     break;
 
   case 13:
 #line 2035 "src/parse-gram.c"
     break;
 
   case 13:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 297 "src/parse-gram.y"
     { expected_rr_conflicts = (yyvsp[0].integer); }
 #line 297 "src/parse-gram.y"
     { expected_rr_conflicts = (yyvsp[0].integer); }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2043 "src/parse-gram.c"
     break;
 
   case 14:
 #line 2043 "src/parse-gram.c"
     break;
 
   case 14:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 298 "src/parse-gram.y"
     { spec_file_prefix = (yyvsp[0].chars); }
 #line 298 "src/parse-gram.y"
     { spec_file_prefix = (yyvsp[0].chars); }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2051 "src/parse-gram.c"
     break;
 
   case 15:
 #line 2051 "src/parse-gram.c"
     break;
 
   case 15:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 299 "src/parse-gram.y"
     { spec_file_prefix = (yyvsp[0].chars); }
 #line 299 "src/parse-gram.y"
     { spec_file_prefix = (yyvsp[0].chars); }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2059 "src/parse-gram.c"
     break;
 
   case 16:
 #line 2059 "src/parse-gram.c"
     break;
 
   case 16:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 301 "src/parse-gram.y"
     {
       nondeterministic_parser = true;
       glr_parser = true;
     }
 #line 301 "src/parse-gram.y"
     {
       nondeterministic_parser = true;
       glr_parser = true;
     }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2070 "src/parse-gram.c"
     break;
 
   case 17:
 #line 2070 "src/parse-gram.c"
     break;
 
   case 17:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 306 "src/parse-gram.y"
     {
       code_props action;
 #line 306 "src/parse-gram.y"
     {
       code_props action;
@@ -2080,92 +2080,92 @@ yyreduce:
       muscle_code_grow ("initial_action", action.code, (yylsp[0]));
       code_scanner_last_string_free ();
     }
       muscle_code_grow ("initial_action", action.code, (yylsp[0]));
       code_scanner_last_string_free ();
     }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2085 "src/parse-gram.c"
     break;
 
   case 18:
 #line 2085 "src/parse-gram.c"
     break;
 
   case 18:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 314 "src/parse-gram.y"
     { language_argmatch ((yyvsp[0].chars), grammar_prio, (yylsp[-1])); }
 #line 314 "src/parse-gram.y"
     { language_argmatch ((yyvsp[0].chars), grammar_prio, (yylsp[-1])); }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2093 "src/parse-gram.c"
     break;
 
   case 19:
 #line 2093 "src/parse-gram.c"
     break;
 
   case 19:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 315 "src/parse-gram.y"
     { spec_name_prefix = (yyvsp[0].chars); }
 #line 315 "src/parse-gram.y"
     { spec_name_prefix = (yyvsp[0].chars); }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2101 "src/parse-gram.c"
     break;
 
   case 20:
 #line 2101 "src/parse-gram.c"
     break;
 
   case 20:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 316 "src/parse-gram.y"
     { spec_name_prefix = (yyvsp[0].chars); }
 #line 316 "src/parse-gram.y"
     { spec_name_prefix = (yyvsp[0].chars); }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2109 "src/parse-gram.c"
     break;
 
   case 21:
 #line 2109 "src/parse-gram.c"
     break;
 
   case 21:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 317 "src/parse-gram.y"
     { no_lines_flag = true; }
 #line 317 "src/parse-gram.y"
     { no_lines_flag = true; }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2117 "src/parse-gram.c"
     break;
 
   case 22:
 #line 2117 "src/parse-gram.c"
     break;
 
   case 22:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 318 "src/parse-gram.y"
     { nondeterministic_parser = true; }
 #line 318 "src/parse-gram.y"
     { nondeterministic_parser = true; }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2125 "src/parse-gram.c"
     break;
 
   case 23:
 #line 2125 "src/parse-gram.c"
     break;
 
   case 23:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 319 "src/parse-gram.y"
     { spec_outfile = (yyvsp[0].chars); }
 #line 319 "src/parse-gram.y"
     { spec_outfile = (yyvsp[0].chars); }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2133 "src/parse-gram.c"
     break;
 
   case 24:
 #line 2133 "src/parse-gram.c"
     break;
 
   case 24:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 320 "src/parse-gram.y"
     { spec_outfile = (yyvsp[0].chars); }
 #line 320 "src/parse-gram.y"
     { spec_outfile = (yyvsp[0].chars); }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2141 "src/parse-gram.c"
     break;
 
   case 25:
 #line 2141 "src/parse-gram.c"
     break;
 
   case 25:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 321 "src/parse-gram.y"
     { current_param = (yyvsp[0].param); }
 #line 321 "src/parse-gram.y"
     { current_param = (yyvsp[0].param); }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2149 "src/parse-gram.c"
     break;
 
   case 26:
 #line 2149 "src/parse-gram.c"
     break;
 
   case 26:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 321 "src/parse-gram.y"
     { current_param = param_none; }
 #line 321 "src/parse-gram.y"
     { current_param = param_none; }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2157 "src/parse-gram.c"
     break;
 
   case 27:
 #line 2157 "src/parse-gram.c"
     break;
 
   case 27:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 322 "src/parse-gram.y"
     { version_check (&(yylsp[0]), (yyvsp[0].chars)); }
 #line 322 "src/parse-gram.y"
     { version_check (&(yylsp[0]), (yyvsp[0].chars)); }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2165 "src/parse-gram.c"
     break;
 
   case 28:
 #line 2165 "src/parse-gram.c"
     break;
 
   case 28:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 324 "src/parse-gram.y"
     {
       char const *skeleton_user = (yyvsp[0].chars);
 #line 324 "src/parse-gram.y"
     {
       char const *skeleton_user = (yyvsp[0].chars);
@@ -2190,62 +2190,62 @@ yyreduce:
         }
       skeleton_arg (skeleton_user, grammar_prio, (yylsp[-1]));
     }
         }
       skeleton_arg (skeleton_user, grammar_prio, (yylsp[-1]));
     }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2195 "src/parse-gram.c"
     break;
 
   case 29:
 #line 2195 "src/parse-gram.c"
     break;
 
   case 29:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 347 "src/parse-gram.y"
     { token_table_flag = true; }
 #line 347 "src/parse-gram.y"
     { token_table_flag = true; }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2203 "src/parse-gram.c"
     break;
 
   case 30:
 #line 2203 "src/parse-gram.c"
     break;
 
   case 30:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 348 "src/parse-gram.y"
     { report_flag |= report_states; }
 #line 348 "src/parse-gram.y"
     { report_flag |= report_states; }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2211 "src/parse-gram.c"
     break;
 
   case 31:
 #line 2211 "src/parse-gram.c"
     break;
 
   case 31:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 349 "src/parse-gram.y"
     { yacc_flag = true; }
 #line 349 "src/parse-gram.y"
     { yacc_flag = true; }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2219 "src/parse-gram.c"
     break;
 
   case 33:
 #line 2219 "src/parse-gram.c"
     break;
 
   case 33:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 354 "src/parse-gram.y"
     { add_param (current_param, (yyvsp[0].code), (yylsp[0])); }
 #line 354 "src/parse-gram.y"
     { add_param (current_param, (yyvsp[0].code), (yylsp[0])); }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2227 "src/parse-gram.c"
     break;
 
   case 34:
 #line 2227 "src/parse-gram.c"
     break;
 
   case 34:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 355 "src/parse-gram.y"
     { add_param (current_param, (yyvsp[0].code), (yylsp[0])); }
 #line 355 "src/parse-gram.y"
     { add_param (current_param, (yyvsp[0].code), (yylsp[0])); }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2235 "src/parse-gram.c"
     break;
 
   case 37:
 #line 2235 "src/parse-gram.c"
     break;
 
   case 37:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 367 "src/parse-gram.y"
     {
       grammar_start_symbol_set ((yyvsp[0].symbol), (yylsp[0]));
     }
 #line 367 "src/parse-gram.y"
     {
       grammar_start_symbol_set ((yyvsp[0].symbol), (yylsp[0]));
     }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2245 "src/parse-gram.c"
     break;
 
   case 38:
 #line 2245 "src/parse-gram.c"
     break;
 
   case 38:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 371 "src/parse-gram.y"
     {
       symbol_list *list;
 #line 371 "src/parse-gram.y"
     {
       symbol_list *list;
@@ -2253,12 +2253,12 @@ yyreduce:
        symbol_list_destructor_set (list, (yyvsp[-1].code), (yylsp[-1]));
       symbol_list_free ((yyvsp[0].list));
     }
        symbol_list_destructor_set (list, (yyvsp[-1].code), (yylsp[-1]));
       symbol_list_free ((yyvsp[0].list));
     }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2258 "src/parse-gram.c"
     break;
 
   case 39:
 #line 2258 "src/parse-gram.c"
     break;
 
   case 39:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 378 "src/parse-gram.y"
     {
       symbol_list *list;
 #line 378 "src/parse-gram.y"
     {
       symbol_list *list;
@@ -2266,32 +2266,32 @@ yyreduce:
        symbol_list_printer_set (list, (yyvsp[-1].code), (yylsp[-1]));
       symbol_list_free ((yyvsp[0].list));
     }
        symbol_list_printer_set (list, (yyvsp[-1].code), (yylsp[-1]));
       symbol_list_free ((yyvsp[0].list));
     }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2271 "src/parse-gram.c"
     break;
 
   case 40:
 #line 2271 "src/parse-gram.c"
     break;
 
   case 40:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 385 "src/parse-gram.y"
     {
       default_prec = true;
     }
 #line 385 "src/parse-gram.y"
     {
       default_prec = true;
     }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2281 "src/parse-gram.c"
     break;
 
   case 41:
 #line 2281 "src/parse-gram.c"
     break;
 
   case 41:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 389 "src/parse-gram.y"
     {
       default_prec = false;
     }
 #line 389 "src/parse-gram.y"
     {
       default_prec = false;
     }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2291 "src/parse-gram.c"
     break;
 
   case 42:
 #line 2291 "src/parse-gram.c"
     break;
 
   case 42:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 393 "src/parse-gram.y"
     {
       /* Do not invoke muscle_percent_code_grow here since it invokes
 #line 393 "src/parse-gram.y"
     {
       /* Do not invoke muscle_percent_code_grow here since it invokes
@@ -2299,89 +2299,89 @@ yyreduce:
       muscle_code_grow ("percent_code()", (yyvsp[0].chars), (yylsp[0]));
       code_scanner_last_string_free ();
     }
       muscle_code_grow ("percent_code()", (yyvsp[0].chars), (yylsp[0]));
       code_scanner_last_string_free ();
     }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2304 "src/parse-gram.c"
     break;
 
   case 43:
 #line 2304 "src/parse-gram.c"
     break;
 
   case 43:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 400 "src/parse-gram.y"
     {
       muscle_percent_code_grow ((yyvsp[-1].uniqstr), (yylsp[-1]), (yyvsp[0].chars), (yylsp[0]));
       code_scanner_last_string_free ();
     }
 #line 400 "src/parse-gram.y"
     {
       muscle_percent_code_grow ((yyvsp[-1].uniqstr), (yylsp[-1]), (yyvsp[0].chars), (yylsp[0]));
       code_scanner_last_string_free ();
     }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2315 "src/parse-gram.c"
     break;
 
   case 44:
 #line 2315 "src/parse-gram.c"
     break;
 
   case 44:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 414 "src/parse-gram.y"
     {}
 #line 414 "src/parse-gram.y"
     {}
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2323 "src/parse-gram.c"
     break;
 
   case 45:
 #line 2323 "src/parse-gram.c"
     break;
 
   case 45:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 415 "src/parse-gram.y"
     { muscle_code_grow ("union_name", (yyvsp[0].uniqstr), (yylsp[0])); }
 #line 415 "src/parse-gram.y"
     { muscle_code_grow ("union_name", (yyvsp[0].uniqstr), (yylsp[0])); }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2331 "src/parse-gram.c"
     break;
 
   case 46:
 #line 2331 "src/parse-gram.c"
     break;
 
   case 46:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 420 "src/parse-gram.y"
     {
       union_seen = true;
       muscle_code_grow ("stype", (yyvsp[0].chars), (yylsp[0]));
       code_scanner_last_string_free ();
     }
 #line 420 "src/parse-gram.y"
     {
       union_seen = true;
       muscle_code_grow ("stype", (yyvsp[0].chars), (yylsp[0]));
       code_scanner_last_string_free ();
     }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2343 "src/parse-gram.c"
     break;
 
   case 47:
 #line 2343 "src/parse-gram.c"
     break;
 
   case 47:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 431 "src/parse-gram.y"
     { current_class = nterm_sym; }
 #line 431 "src/parse-gram.y"
     { current_class = nterm_sym; }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2351 "src/parse-gram.c"
     break;
 
   case 48:
 #line 2351 "src/parse-gram.c"
     break;
 
   case 48:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 432 "src/parse-gram.y"
     {
       current_class = unknown_sym;
       current_type = NULL;
     }
 #line 432 "src/parse-gram.y"
     {
       current_class = unknown_sym;
       current_type = NULL;
     }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2362 "src/parse-gram.c"
     break;
 
   case 49:
 #line 2362 "src/parse-gram.c"
     break;
 
   case 49:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 436 "src/parse-gram.y"
     { current_class = token_sym; }
 #line 436 "src/parse-gram.y"
     { current_class = token_sym; }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2370 "src/parse-gram.c"
     break;
 
   case 50:
 #line 2370 "src/parse-gram.c"
     break;
 
   case 50:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 437 "src/parse-gram.y"
     {
       current_class = unknown_sym;
       current_type = NULL;
     }
 #line 437 "src/parse-gram.y"
     {
       current_class = unknown_sym;
       current_type = NULL;
     }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2381 "src/parse-gram.c"
     break;
 
   case 51:
 #line 2381 "src/parse-gram.c"
     break;
 
   case 51:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 442 "src/parse-gram.y"
     {
       symbol_list *list;
 #line 442 "src/parse-gram.y"
     {
       symbol_list *list;
@@ -2390,12 +2390,12 @@ yyreduce:
        symbol_type_set (list->content.sym, (yyvsp[-1].uniqstr), (yylsp[-1]));
       symbol_list_free ((yyvsp[0].list));
     }
        symbol_type_set (list->content.sym, (yyvsp[-1].uniqstr), (yylsp[-1]));
       symbol_list_free ((yyvsp[0].list));
     }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2395 "src/parse-gram.c"
     break;
 
   case 52:
 #line 2395 "src/parse-gram.c"
     break;
 
   case 52:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 453 "src/parse-gram.y"
     {
       symbol_list *list;
 #line 453 "src/parse-gram.y"
     {
       symbol_list *list;
@@ -2408,202 +2408,202 @@ yyreduce:
       symbol_list_free ((yyvsp[0].list));
       current_type = NULL;
     }
       symbol_list_free ((yyvsp[0].list));
       current_type = NULL;
     }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2413 "src/parse-gram.c"
     break;
 
   case 53:
 #line 2413 "src/parse-gram.c"
     break;
 
   case 53:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 467 "src/parse-gram.y"
     { (yyval.assoc) = left_assoc; }
 #line 467 "src/parse-gram.y"
     { (yyval.assoc) = left_assoc; }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2421 "src/parse-gram.c"
     break;
 
   case 54:
 #line 2421 "src/parse-gram.c"
     break;
 
   case 54:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 468 "src/parse-gram.y"
     { (yyval.assoc) = right_assoc; }
 #line 468 "src/parse-gram.y"
     { (yyval.assoc) = right_assoc; }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2429 "src/parse-gram.c"
     break;
 
   case 55:
 #line 2429 "src/parse-gram.c"
     break;
 
   case 55:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 469 "src/parse-gram.y"
     { (yyval.assoc) = non_assoc; }
 #line 469 "src/parse-gram.y"
     { (yyval.assoc) = non_assoc; }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2437 "src/parse-gram.c"
     break;
 
   case 56:
 #line 2437 "src/parse-gram.c"
     break;
 
   case 56:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 470 "src/parse-gram.y"
     { (yyval.assoc) = precedence_assoc; }
 #line 470 "src/parse-gram.y"
     { (yyval.assoc) = precedence_assoc; }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2445 "src/parse-gram.c"
     break;
 
   case 57:
 #line 2445 "src/parse-gram.c"
     break;
 
   case 57:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 474 "src/parse-gram.y"
     { current_type = NULL; }
 #line 474 "src/parse-gram.y"
     { current_type = NULL; }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2453 "src/parse-gram.c"
     break;
 
   case 58:
 #line 2453 "src/parse-gram.c"
     break;
 
   case 58:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 475 "src/parse-gram.y"
     { current_type = (yyvsp[0].uniqstr); tag_seen = true; }
 #line 475 "src/parse-gram.y"
     { current_type = (yyvsp[0].uniqstr); tag_seen = true; }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2461 "src/parse-gram.c"
     break;
 
   case 59:
 #line 2461 "src/parse-gram.c"
     break;
 
   case 59:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 481 "src/parse-gram.y"
     { (yyval.list) = symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0])); }
 #line 481 "src/parse-gram.y"
     { (yyval.list) = symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0])); }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2469 "src/parse-gram.c"
     break;
 
   case 60:
 #line 2469 "src/parse-gram.c"
     break;
 
   case 60:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 483 "src/parse-gram.y"
     { (yyval.list) = symbol_list_prepend ((yyvsp[-1].list), symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0]))); }
 #line 483 "src/parse-gram.y"
     { (yyval.list) = symbol_list_prepend ((yyvsp[-1].list), symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0]))); }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2477 "src/parse-gram.c"
     break;
 
   case 61:
 #line 2477 "src/parse-gram.c"
     break;
 
   case 61:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 487 "src/parse-gram.y"
     { (yyval.symbol) = (yyvsp[0].symbol); }
 #line 487 "src/parse-gram.y"
     { (yyval.symbol) = (yyvsp[0].symbol); }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2485 "src/parse-gram.c"
     break;
 
   case 62:
 #line 2485 "src/parse-gram.c"
     break;
 
   case 62:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 488 "src/parse-gram.y"
     { (yyval.symbol) = (yyvsp[-1].symbol); symbol_user_token_number_set ((yyvsp[-1].symbol), (yyvsp[0].integer), (yylsp[0])); }
 #line 488 "src/parse-gram.y"
     { (yyval.symbol) = (yyvsp[-1].symbol); symbol_user_token_number_set ((yyvsp[-1].symbol), (yyvsp[0].integer), (yylsp[0])); }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2493 "src/parse-gram.c"
     break;
 
   case 63:
 #line 2493 "src/parse-gram.c"
     break;
 
   case 63:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 494 "src/parse-gram.y"
     { (yyval.list) = symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0])); }
 #line 494 "src/parse-gram.y"
     { (yyval.list) = symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0])); }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2501 "src/parse-gram.c"
     break;
 
   case 64:
 #line 2501 "src/parse-gram.c"
     break;
 
   case 64:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 496 "src/parse-gram.y"
     { (yyval.list) = symbol_list_prepend ((yyvsp[-1].list), symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0]))); }
 #line 496 "src/parse-gram.y"
     { (yyval.list) = symbol_list_prepend ((yyvsp[-1].list), symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0]))); }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2509 "src/parse-gram.c"
     break;
 
   case 65:
 #line 2509 "src/parse-gram.c"
     break;
 
   case 65:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 500 "src/parse-gram.y"
     { (yyval.list) = (yyvsp[0].list); }
 #line 500 "src/parse-gram.y"
     { (yyval.list) = (yyvsp[0].list); }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2517 "src/parse-gram.c"
     break;
 
   case 66:
 #line 2517 "src/parse-gram.c"
     break;
 
   case 66:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 501 "src/parse-gram.y"
     { (yyval.list) = symbol_list_prepend ((yyvsp[-1].list), (yyvsp[0].list)); }
 #line 501 "src/parse-gram.y"
     { (yyval.list) = symbol_list_prepend ((yyvsp[-1].list), (yyvsp[0].list)); }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2525 "src/parse-gram.c"
     break;
 
   case 67:
 #line 2525 "src/parse-gram.c"
     break;
 
   case 67:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 505 "src/parse-gram.y"
     { (yyval.list) = symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0])); }
 #line 505 "src/parse-gram.y"
     { (yyval.list) = symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0])); }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2533 "src/parse-gram.c"
     break;
 
   case 68:
 #line 2533 "src/parse-gram.c"
     break;
 
   case 68:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 506 "src/parse-gram.y"
     { (yyval.list) = symbol_list_type_new ((yyvsp[0].uniqstr), (yylsp[0])); }
 #line 506 "src/parse-gram.y"
     { (yyval.list) = symbol_list_type_new ((yyvsp[0].uniqstr), (yylsp[0])); }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2541 "src/parse-gram.c"
     break;
 
   case 69:
 #line 2541 "src/parse-gram.c"
     break;
 
   case 69:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 507 "src/parse-gram.y"
     { (yyval.list) = symbol_list_default_tagged_new ((yylsp[0])); }
 #line 507 "src/parse-gram.y"
     { (yyval.list) = symbol_list_default_tagged_new ((yylsp[0])); }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2549 "src/parse-gram.c"
     break;
 
   case 70:
 #line 2549 "src/parse-gram.c"
     break;
 
   case 70:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 508 "src/parse-gram.y"
     { (yyval.list) = symbol_list_default_tagless_new ((yylsp[0])); }
 #line 508 "src/parse-gram.y"
     { (yyval.list) = symbol_list_default_tagless_new ((yylsp[0])); }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2557 "src/parse-gram.c"
     break;
 
   case 71:
 #line 2557 "src/parse-gram.c"
     break;
 
   case 71:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 514 "src/parse-gram.y"
     {
        current_type = (yyvsp[0].uniqstr);
        tag_seen = true;
      }
 #line 514 "src/parse-gram.y"
     {
        current_type = (yyvsp[0].uniqstr);
        tag_seen = true;
      }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2568 "src/parse-gram.c"
     break;
 
   case 72:
 #line 2568 "src/parse-gram.c"
     break;
 
   case 72:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 519 "src/parse-gram.y"
     {
        symbol_class_set ((yyvsp[0].symbol), current_class, (yylsp[0]), true);
        symbol_type_set ((yyvsp[0].symbol), current_type, (yylsp[0]));
      }
 #line 519 "src/parse-gram.y"
     {
        symbol_class_set ((yyvsp[0].symbol), current_class, (yylsp[0]), true);
        symbol_type_set ((yyvsp[0].symbol), current_type, (yylsp[0]));
      }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2579 "src/parse-gram.c"
     break;
 
   case 73:
 #line 2579 "src/parse-gram.c"
     break;
 
   case 73:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 524 "src/parse-gram.y"
     {
       symbol_class_set ((yyvsp[-1].symbol), current_class, (yylsp[-1]), true);
       symbol_type_set ((yyvsp[-1].symbol), current_type, (yylsp[-1]));
       symbol_user_token_number_set ((yyvsp[-1].symbol), (yyvsp[0].integer), (yylsp[0]));
     }
 #line 524 "src/parse-gram.y"
     {
       symbol_class_set ((yyvsp[-1].symbol), current_class, (yylsp[-1]), true);
       symbol_type_set ((yyvsp[-1].symbol), current_type, (yylsp[-1]));
       symbol_user_token_number_set ((yyvsp[-1].symbol), (yyvsp[0].integer), (yylsp[0]));
     }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2591 "src/parse-gram.c"
     break;
 
   case 74:
 #line 2591 "src/parse-gram.c"
     break;
 
   case 74:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 530 "src/parse-gram.y"
     {
       symbol_class_set ((yyvsp[-1].symbol), current_class, (yylsp[-1]), true);
       symbol_type_set ((yyvsp[-1].symbol), current_type, (yylsp[-1]));
       symbol_make_alias ((yyvsp[-1].symbol), (yyvsp[0].symbol), (yyloc));
     }
 #line 530 "src/parse-gram.y"
     {
       symbol_class_set ((yyvsp[-1].symbol), current_class, (yylsp[-1]), true);
       symbol_type_set ((yyvsp[-1].symbol), current_type, (yylsp[-1]));
       symbol_make_alias ((yyvsp[-1].symbol), (yyvsp[0].symbol), (yyloc));
     }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2603 "src/parse-gram.c"
     break;
 
   case 75:
 #line 2603 "src/parse-gram.c"
     break;
 
   case 75:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 536 "src/parse-gram.y"
     {
       symbol_class_set ((yyvsp[-2].symbol), current_class, (yylsp[-2]), true);
 #line 536 "src/parse-gram.y"
     {
       symbol_class_set ((yyvsp[-2].symbol), current_class, (yylsp[-2]), true);
@@ -2611,144 +2611,144 @@ yyreduce:
       symbol_user_token_number_set ((yyvsp[-2].symbol), (yyvsp[-1].integer), (yylsp[-1]));
       symbol_make_alias ((yyvsp[-2].symbol), (yyvsp[0].symbol), (yyloc));
     }
       symbol_user_token_number_set ((yyvsp[-2].symbol), (yyvsp[-1].integer), (yylsp[-1]));
       symbol_make_alias ((yyvsp[-2].symbol), (yyvsp[0].symbol), (yyloc));
     }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2616 "src/parse-gram.c"
     break;
 
   case 82:
 #line 2616 "src/parse-gram.c"
     break;
 
   case 82:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 566 "src/parse-gram.y"
     {
       yyerrok;
     }
 #line 566 "src/parse-gram.y"
     {
       yyerrok;
     }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2626 "src/parse-gram.c"
     break;
 
   case 83:
 #line 2626 "src/parse-gram.c"
     break;
 
   case 83:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 572 "src/parse-gram.y"
     { current_lhs = (yyvsp[-1].symbol); current_lhs_location = (yylsp[-1]);
     current_lhs_named_ref = (yyvsp[0].named_ref); }
 #line 572 "src/parse-gram.y"
     { current_lhs = (yyvsp[-1].symbol); current_lhs_location = (yylsp[-1]);
     current_lhs_named_ref = (yyvsp[0].named_ref); }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2635 "src/parse-gram.c"
     break;
 
   case 85:
 #line 2635 "src/parse-gram.c"
     break;
 
   case 85:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 577 "src/parse-gram.y"
     { grammar_current_rule_end ((yylsp[0])); }
 #line 577 "src/parse-gram.y"
     { grammar_current_rule_end ((yylsp[0])); }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2643 "src/parse-gram.c"
     break;
 
   case 86:
 #line 2643 "src/parse-gram.c"
     break;
 
   case 86:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 578 "src/parse-gram.y"
     { grammar_current_rule_end ((yylsp[0])); }
 #line 578 "src/parse-gram.y"
     { grammar_current_rule_end ((yylsp[0])); }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2651 "src/parse-gram.c"
     break;
 
   case 88:
 #line 2651 "src/parse-gram.c"
     break;
 
   case 88:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 584 "src/parse-gram.y"
     { grammar_current_rule_begin (current_lhs, current_lhs_location,
                                  current_lhs_named_ref); }
 #line 584 "src/parse-gram.y"
     { grammar_current_rule_begin (current_lhs, current_lhs_location,
                                  current_lhs_named_ref); }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2660 "src/parse-gram.c"
     break;
 
   case 89:
 #line 2660 "src/parse-gram.c"
     break;
 
   case 89:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 587 "src/parse-gram.y"
     { grammar_current_rule_symbol_append ((yyvsp[-1].symbol), (yylsp[-1]), (yyvsp[0].named_ref)); }
 #line 587 "src/parse-gram.y"
     { grammar_current_rule_symbol_append ((yyvsp[-1].symbol), (yylsp[-1]), (yyvsp[0].named_ref)); }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2668 "src/parse-gram.c"
     break;
 
   case 90:
 #line 2668 "src/parse-gram.c"
     break;
 
   case 90:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 589 "src/parse-gram.y"
     { grammar_current_rule_action_append ((yyvsp[-1].code), (yylsp[-1]), (yyvsp[0].named_ref), false); }
 #line 589 "src/parse-gram.y"
     { grammar_current_rule_action_append ((yyvsp[-1].code), (yylsp[-1]), (yyvsp[0].named_ref), false); }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2676 "src/parse-gram.c"
     break;
 
   case 91:
 #line 2676 "src/parse-gram.c"
     break;
 
   case 91:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 591 "src/parse-gram.y"
     { grammar_current_rule_action_append ((yyvsp[0].code), (yylsp[0]), NULL, true); }
 #line 591 "src/parse-gram.y"
     { grammar_current_rule_action_append ((yyvsp[0].code), (yylsp[0]), NULL, true); }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2684 "src/parse-gram.c"
     break;
 
   case 92:
 #line 2684 "src/parse-gram.c"
     break;
 
   case 92:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 593 "src/parse-gram.y"
     { grammar_current_rule_prec_set ((yyvsp[0].symbol), (yylsp[0])); }
 #line 593 "src/parse-gram.y"
     { grammar_current_rule_prec_set ((yyvsp[0].symbol), (yylsp[0])); }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2692 "src/parse-gram.c"
     break;
 
   case 93:
 #line 2692 "src/parse-gram.c"
     break;
 
   case 93:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 595 "src/parse-gram.y"
     { grammar_current_rule_dprec_set ((yyvsp[0].integer), (yylsp[0])); }
 #line 595 "src/parse-gram.y"
     { grammar_current_rule_dprec_set ((yyvsp[0].integer), (yylsp[0])); }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2700 "src/parse-gram.c"
     break;
 
   case 94:
 #line 2700 "src/parse-gram.c"
     break;
 
   case 94:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 597 "src/parse-gram.y"
     { grammar_current_rule_merge_set ((yyvsp[0].uniqstr), (yylsp[0])); }
 #line 597 "src/parse-gram.y"
     { grammar_current_rule_merge_set ((yyvsp[0].uniqstr), (yylsp[0])); }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2708 "src/parse-gram.c"
     break;
 
   case 95:
 #line 2708 "src/parse-gram.c"
     break;
 
   case 95:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 601 "src/parse-gram.y"
     { (yyval.named_ref) = 0; }
 #line 601 "src/parse-gram.y"
     { (yyval.named_ref) = 0; }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2716 "src/parse-gram.c"
     break;
 
   case 96:
 #line 2716 "src/parse-gram.c"
     break;
 
   case 96:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 603 "src/parse-gram.y"
     { (yyval.named_ref) = named_ref_new((yyvsp[0].uniqstr), (yylsp[0])); }
 #line 603 "src/parse-gram.y"
     { (yyval.named_ref) = named_ref_new((yyvsp[0].uniqstr), (yylsp[0])); }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2724 "src/parse-gram.c"
     break;
 
   case 98:
 #line 2724 "src/parse-gram.c"
     break;
 
   case 98:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 614 "src/parse-gram.y"
     { (yyval.uniqstr) = uniqstr_new ((yyvsp[0].chars)); }
 #line 614 "src/parse-gram.y"
     { (yyval.uniqstr) = uniqstr_new ((yyvsp[0].chars)); }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2732 "src/parse-gram.c"
     break;
 
   case 99:
 #line 2732 "src/parse-gram.c"
     break;
 
   case 99:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 619 "src/parse-gram.y"
     { (yyval.chars) = ""; }
 #line 619 "src/parse-gram.y"
     { (yyval.chars) = ""; }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2740 "src/parse-gram.c"
     break;
 
   case 100:
 #line 2740 "src/parse-gram.c"
     break;
 
   case 100:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 620 "src/parse-gram.y"
     { (yyval.chars) = (yyvsp[0].uniqstr); }
 #line 620 "src/parse-gram.y"
     { (yyval.chars) = (yyvsp[0].uniqstr); }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2748 "src/parse-gram.c"
     break;
 
   case 102:
 #line 2748 "src/parse-gram.c"
     break;
 
   case 102:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 631 "src/parse-gram.y"
     {
       code_props plain_code;
 #line 631 "src/parse-gram.y"
     {
       code_props plain_code;
@@ -2758,51 +2758,51 @@ yyreduce:
       gram_scanner_last_string_free ();
       (yyval.chars) = plain_code.code;
     }
       gram_scanner_last_string_free ();
       (yyval.chars) = plain_code.code;
     }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2763 "src/parse-gram.c"
     break;
 
   case 103:
 #line 2763 "src/parse-gram.c"
     break;
 
   case 103:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 651 "src/parse-gram.y"
     { (yyval.symbol) = symbol_from_uniqstr ((yyvsp[0].uniqstr), (yylsp[0])); }
 #line 651 "src/parse-gram.y"
     { (yyval.symbol) = symbol_from_uniqstr ((yyvsp[0].uniqstr), (yylsp[0])); }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2771 "src/parse-gram.c"
     break;
 
   case 104:
 #line 2771 "src/parse-gram.c"
     break;
 
   case 104:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 653 "src/parse-gram.y"
     {
       (yyval.symbol) = symbol_get (char_name ((yyvsp[0].character)), (yylsp[0]));
       symbol_class_set ((yyval.symbol), token_sym, (yylsp[0]), false);
       symbol_user_token_number_set ((yyval.symbol), (yyvsp[0].character), (yylsp[0]));
     }
 #line 653 "src/parse-gram.y"
     {
       (yyval.symbol) = symbol_get (char_name ((yyvsp[0].character)), (yylsp[0]));
       symbol_class_set ((yyval.symbol), token_sym, (yylsp[0]), false);
       symbol_user_token_number_set ((yyval.symbol), (yyvsp[0].character), (yylsp[0]));
     }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2783 "src/parse-gram.c"
     break;
 
   case 105:
 #line 2783 "src/parse-gram.c"
     break;
 
   case 105:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 661 "src/parse-gram.y"
     { (yyval.symbol) = symbol_from_uniqstr ((yyvsp[0].uniqstr), (yylsp[0])); }
 #line 661 "src/parse-gram.y"
     { (yyval.symbol) = symbol_from_uniqstr ((yyvsp[0].uniqstr), (yylsp[0])); }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2791 "src/parse-gram.c"
     break;
 
   case 108:
 #line 2791 "src/parse-gram.c"
     break;
 
   case 108:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 673 "src/parse-gram.y"
     {
       (yyval.symbol) = symbol_get (quotearg_style (c_quoting_style, (yyvsp[0].chars)), (yylsp[0]));
       symbol_class_set ((yyval.symbol), token_sym, (yylsp[0]), false);
     }
 #line 673 "src/parse-gram.y"
     {
       (yyval.symbol) = symbol_get (quotearg_style (c_quoting_style, (yyvsp[0].chars)), (yylsp[0]));
       symbol_class_set ((yyval.symbol), token_sym, (yylsp[0]), false);
     }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2802 "src/parse-gram.c"
     break;
 
   case 110:
 #line 2802 "src/parse-gram.c"
     break;
 
   case 110:
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 682 "src/parse-gram.y"
     {
       code_props plain_code;
 #line 682 "src/parse-gram.y"
     {
       code_props plain_code;
@@ -2812,12 +2812,12 @@ yyreduce:
       muscle_code_grow ("epilogue", plain_code.code, (yylsp[0]));
       code_scanner_last_string_free ();
     }
       muscle_code_grow ("epilogue", plain_code.code, (yylsp[0]));
       code_scanner_last_string_free ();
     }
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2817 "src/parse-gram.c"
     break;
 
 
 #line 2817 "src/parse-gram.c"
     break;
 
 
-/* Line 1443 of yacc.c  */
+/* Line 1646 of yacc.c  */
 #line 2822 "src/parse-gram.c"
       default: break;
     }
 #line 2822 "src/parse-gram.c"
       default: break;
     }
@@ -2871,11 +2871,12 @@ yyerrlab:
 #if ! YYERROR_VERBOSE
       yyerror (YY_("syntax error"));
 #else
 #if ! YYERROR_VERBOSE
       yyerror (YY_("syntax error"));
 #else
-# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, yystate, \
+# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, yyssp, \
                                         yytoken)
       {
         char const *yymsgp = YY_("syntax error");
                                         yytoken)
       {
         char const *yymsgp = YY_("syntax error");
-        int yysyntax_error_status = YYSYNTAX_ERROR;
+        int yysyntax_error_status;
+        yysyntax_error_status = YYSYNTAX_ERROR;
         if (yysyntax_error_status == 0)
           yymsgp = yymsg;
         else if (yysyntax_error_status == 1)
         if (yysyntax_error_status == 0)
           yymsgp = yymsg;
         else if (yysyntax_error_status == 1)
@@ -3052,7 +3053,7 @@ yyreturn:
   return YYID (yyresult);
 }
 
   return YYID (yyresult);
 }
 
-/* Line 1680 of yacc.c  */
+/* Line 1903 of yacc.c  */
 #line 692 "src/parse-gram.y"
 
 
 #line 692 "src/parse-gram.y"
 
 
index fd1c8571a9cf095ab20086f4b1e19434c9c1f9e1..e391f1342fcd0d10c3ba461025550f21a3e35262 100644 (file)
@@ -1,4 +1,4 @@
-/* A Bison parser, made by GNU Bison 2.4.537-34db.  */
+/* A Bison parser, made by GNU Bison 2.4.542-10bae.  */
 
 /* Interface for Bison's Yacc-like parsers in C
 
 
 /* Interface for Bison's Yacc-like parsers in C
 
@@ -31,7 +31,7 @@
    This special exception was added by the Free Software Foundation in
    version 2.2 of Bison.  */
 /* "%code requires" blocks.  */
    This special exception was added by the Free Software Foundation in
    version 2.2 of Bison.  */
 /* "%code requires" blocks.  */
-/* Line 1681 of yacc.c  */
+/* Line 1904 of yacc.c  */
 #line 202 "src/parse-gram.y"
 
 # ifndef PARAM_TYPE
 #line 202 "src/parse-gram.y"
 
 # ifndef PARAM_TYPE
@@ -46,7 +46,7 @@
 # endif
 
 
 # endif
 
 
-/* Line 1681 of yacc.c  */
+/* Line 1904 of yacc.c  */
 #line 51 "src/parse-gram.h"
 
 /* Tokens.  */
 #line 51 "src/parse-gram.h"
 
 /* Tokens.  */
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 typedef union YYSTYPE
 {
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 typedef union YYSTYPE
 {
-/* Line 1681 of yacc.c  */
+/* Line 1904 of yacc.c  */
 #line 88 "src/parse-gram.y"
 
   assoc assoc;
 #line 88 "src/parse-gram.y"
 
   assoc assoc;
@@ -188,13 +188,13 @@ typedef union YYSTYPE
   uniqstr uniqstr;
   unsigned char character;
 
   uniqstr uniqstr;
   unsigned char character;
 
-/* Line 1681 of yacc.c  */
+/* Line 1904 of yacc.c  */
 #line 226 "src/parse-gram.y"
 
   param_type param;
 
 
 #line 226 "src/parse-gram.y"
 
   param_type param;
 
 
-/* Line 1681 of yacc.c  */
+/* Line 1904 of yacc.c  */
 #line 199 "src/parse-gram.h"
 } YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
 #line 199 "src/parse-gram.h"
 } YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
index 655a666c0c0a5e0d0383417f62d2699b911d441b..16e1956f4973448cc5e0c8ccf025e8b42386564f 100644 (file)
@@ -94,46 +94,52 @@ main (int argc, const char *argv[])
 }
 ]])
 
 }
 ]])
 
-# Specify the output files to avoid problems on different file systems.
-AT_BISON_CHECK([-o input.c input.y])
+m4_pushdef([AT_NONASSOC_AND_EOF_CHECK],
+[AT_BISON_CHECK([$1[ -o input.c input.y]])
 AT_COMPILE([input])
 
 AT_COMPILE([input])
 
+m4_pushdef([AT_EXPECTING], [m4_if($2, [correct], [[, expecting $end]])])
+
 AT_PARSER_CHECK([./input '0<0'])
 AT_PARSER_CHECK([./input '0<0<0'], [1], [],
 AT_PARSER_CHECK([./input '0<0'])
 AT_PARSER_CHECK([./input '0<0<0'], [1], [],
-         [syntax error, unexpected '<'
+         [syntax error, unexpected '<'AT_EXPECTING
 ])
 
 AT_PARSER_CHECK([./input '0>0'])
 AT_PARSER_CHECK([./input '0>0>0'], [1], [],
 ])
 
 AT_PARSER_CHECK([./input '0>0'])
 AT_PARSER_CHECK([./input '0>0>0'], [1], [],
-         [syntax error, unexpected '>'
+         [syntax error, unexpected '>'AT_EXPECTING
 ])
 
 AT_PARSER_CHECK([./input '0<0>0'], [1], [],
 ])
 
 AT_PARSER_CHECK([./input '0<0>0'], [1], [],
-         [syntax error, unexpected '>'
+         [syntax error, unexpected '>'AT_EXPECTING
 ])
 
 ])
 
-# We must disable default reductions in inconsistent states in order to
-# have an explicit list of all expected tokens.  (However, unless we use
-# canonical LR, lookahead sets are merged for different left contexts,
-# so it is still possible to have extra incorrect tokens in the expected
-# list.  That just doesn't happen to be a problem for this test case.)
-
-AT_BISON_CHECK([-Dlr.default-reductions=consistent -o input.c input.y])
-AT_COMPILE([input])
-
-AT_PARSER_CHECK([./input '0<0'])
-AT_PARSER_CHECK([./input '0<0<0'], [1], [],
-         [syntax error, unexpected '<', expecting $end
-])
+m4_popdef([AT_EXPECTING])])
 
 
-AT_PARSER_CHECK([./input '0>0'])
-AT_PARSER_CHECK([./input '0>0>0'], [1], [],
-         [syntax error, unexpected '>', expecting $end
-])
+# Expected token list is missing.
+AT_NONASSOC_AND_EOF_CHECK([], [[incorrect]])
 
 
-AT_PARSER_CHECK([./input '0<0>0'], [1], [],
-         [syntax error, unexpected '>', expecting $end
-])
+# We must disable default reductions in inconsistent states in order to
+# have an explicit list of all expected tokens.
+AT_NONASSOC_AND_EOF_CHECK([[-Dlr.default-reductions=consistent]],
+                          [[correct]])
+
+# lr.default-reductions=consistent happens to work for this test case.
+# However, for other grammars, lookahead sets can be merged for
+# different left contexts, so it is still possible to have an incorrect
+# expected list.  Canonical LR is almost a general solution (that is, it
+# can fail only when %nonassoc is used), so make sure it gives the same
+# result as above.
+AT_NONASSOC_AND_EOF_CHECK([[-Dlr.type=canonical-lr]], [[correct]])
+
+# parse.lac=full is a completely general solution that does not require
+# any of the above sacrifices.  Of course, it does not extend the
+# language-recognition power of LALR to (IE)LR, but it does ensure that
+# the reported list of expected tokens matches what the given parser
+# would have accepted in place of the unexpected token.
+AT_NONASSOC_AND_EOF_CHECK([[-Dparse.lac=full]], [[correct]])
+
+m4_popdef([AT_NONASSOC_AND_EOF_CHECK])
 
 AT_CLEANUP
 
 
 AT_CLEANUP
 
@@ -342,6 +348,18 @@ AT_CONSISTENT_ERRORS_CHECK([[%define lr.type canonical-lr]],
                            [AT_PREVIOUS_STATE_INPUT],
                            [[$end]], [[ab]])
 
                            [AT_PREVIOUS_STATE_INPUT],
                            [[$end]], [[ab]])
 
+# Only LAC gets it right.
+AT_CONSISTENT_ERRORS_CHECK([[%define lr.type canonical-lr
+                             %define parse.lac full]],
+                           [AT_PREVIOUS_STATE_GRAMMAR],
+                           [AT_PREVIOUS_STATE_INPUT],
+                           [[$end]], [[b]])
+AT_CONSISTENT_ERRORS_CHECK([[%define lr.type ielr
+                             %define parse.lac full]],
+                           [AT_PREVIOUS_STATE_GRAMMAR],
+                           [AT_PREVIOUS_STATE_INPUT],
+                           [[$end]], [[b]])
+
 m4_popdef([AT_PREVIOUS_STATE_GRAMMAR])
 m4_popdef([AT_PREVIOUS_STATE_INPUT])
 
 m4_popdef([AT_PREVIOUS_STATE_GRAMMAR])
 m4_popdef([AT_PREVIOUS_STATE_INPUT])
 
@@ -417,6 +435,16 @@ AT_CONSISTENT_ERRORS_CHECK([[%define lr.type canonical-lr]],
                            [AT_USER_ACTION_INPUT],
                            [[$end]], [[a]])
 
                            [AT_USER_ACTION_INPUT],
                            [[$end]], [[a]])
 
+AT_CONSISTENT_ERRORS_CHECK([[%define parse.lac full]],
+                           [AT_USER_ACTION_GRAMMAR],
+                           [AT_USER_ACTION_INPUT],
+                           [['b']], [[none]])
+AT_CONSISTENT_ERRORS_CHECK([[%define parse.lac full
+                             %define lr.default-reductions accepting]],
+                           [AT_USER_ACTION_GRAMMAR],
+                           [AT_USER_ACTION_INPUT],
+                           [[$end]], [[none]])
+
 m4_popdef([AT_USER_ACTION_GRAMMAR])
 m4_popdef([AT_USER_ACTION_INPUT])
 
 m4_popdef([AT_USER_ACTION_GRAMMAR])
 m4_popdef([AT_USER_ACTION_INPUT])
 
@@ -426,6 +454,113 @@ AT_CLEANUP
 
 
 
 
 
 
+## ------------------------------------------------------- ##
+## LAC: %nonassoc requires splitting canonical LR states.  ##
+## ------------------------------------------------------- ##
+
+# This test case demonstrates that, when %nonassoc is used, canonical
+# LR(1) parser table construction followed by conflict resolution
+# without further state splitting is not always sufficient to produce a
+# parser that can detect all syntax errors as soon as possible on one
+# token of lookahead.  However, LAC solves the problem completely even
+# with minimal LR parser tables.
+
+AT_SETUP([[LAC: %nonassoc requires splitting canonical LR states]])
+
+AT_DATA_GRAMMAR([[input.y]],
+[[%code {
+  #include <stdio.h>
+  void yyerror (char const *);
+  int yylex (void);
+}
+
+%error-verbose
+%nonassoc 'a'
+
+%%
+
+start:
+  'a' problem 'a' // First context.
+| 'b' problem 'b' // Second context.
+| 'c' reduce-nonassoc // Just makes reduce-nonassoc useful.
+;
+
+problem:
+  look reduce-nonassoc
+| look 'a'
+| look 'b'
+;
+
+// For the state reached after shifting the 'a' in these productions,
+// lookahead sets are the same in both the first and second contexts.
+// Thus, canonical LR reuses the same state for both contexts.  However,
+// the lookahead 'a' for the reduction "look: 'a'" later becomes an
+// error action only in the first context.  In order to immediately
+// detect the syntax error on 'a' here for only the first context, this
+// canonical LR state would have to be split into two states, and the
+// 'a' lookahead would have to be removed from only one of the states.
+look:
+  'a' // Reduction lookahead set is always ['a', 'b'].
+| 'a' 'b'
+| 'a' 'c' // 'c' is forgotten as an expected token.
+;
+
+reduce-nonassoc: %prec 'a';
+
+%%
+
+void
+yyerror (char const *msg)
+{
+  fprintf (stderr, "%s\n", msg);
+}
+
+int
+yylex (void)
+{
+  char const *input = "aaa";
+  return *input++;
+}
+
+int
+main (void)
+{
+  return yyparse ();
+}
+]])
+
+# Show canonical LR's failure.
+AT_BISON_CHECK([[-Dlr.type=canonical-lr -o input.c input.y]],
+               [[0]], [[]],
+[[input.y: conflicts: 2 shift/reduce
+]])
+AT_COMPILE([[input]])
+AT_PARSER_CHECK([[./input]], [[1]], [[]],
+[[syntax error, unexpected 'a', expecting 'b'
+]])
+
+# It's corrected by LAC.
+AT_BISON_CHECK([[-Dlr.type=canonical-lr -Dparse.lac=full \
+                 -o input.c input.y]], [[0]], [[]],
+[[input.y: conflicts: 2 shift/reduce
+]])
+AT_COMPILE([[input]])
+AT_PARSER_CHECK([[./input]], [[1]], [[]],
+[[syntax error, unexpected 'a', expecting 'b' or 'c'
+]])
+
+# IELR is sufficient when LAC is used.
+AT_BISON_CHECK([[-Dlr.type=ielr -Dparse.lac=full -o input.c input.y]],
+               [[0]], [[]],
+[[input.y: conflicts: 2 shift/reduce
+]])
+AT_COMPILE([[input]])
+AT_PARSER_CHECK([[./input]], [[1]], [[]],
+[[syntax error, unexpected 'a', expecting 'b' or 'c'
+]])
+
+AT_CLEANUP
+
 ## ------------------------- ##
 ## Unresolved SR Conflicts.  ##
 ## ------------------------- ##
 ## ------------------------- ##
 ## Unresolved SR Conflicts.  ##
 ## ------------------------- ##
index 241c4d06e526b2980df6b65723d96fbe8ef3eba2..254668545b11d5dbe862012c848b14f11adb890e 100644 (file)
@@ -1289,3 +1289,22 @@ input.y:5.19: invalid character after \-escape: \001
 ]])
 
 AT_CLEANUP
 ]])
 
 AT_CLEANUP
+
+## ------------------------- ##
+## LAC: Errors for %define.  ##
+## ------------------------- ##
+
+AT_SETUP([[LAC: Errors for %define]])
+
+AT_DATA([[input.y]],
+[[%%
+start: ;
+]])
+
+# parse.lac.* options are useless if LAC isn't actually activated.
+AT_BISON_CHECK([[-Dparse.lac.es-capacity-initial=1 input.y]],
+               [[1]], [],
+[[<command line>:2: %define variable `parse.lac.es-capacity-initial' is not used
+]])
+
+AT_CLEANUP
index b3fdc29f10867d14d857b6a1ef83993af2204e7c..65d4ac236be73e7619e82328d4ba693563c1222f 100644 (file)
@@ -1469,3 +1469,186 @@ memory exhausted
 ]])
 
 AT_CLEANUP
 ]])
 
 AT_CLEANUP
+
+
+
+## ------------------------ ##
+## LAC: Exploratory stack.  ##
+## ------------------------ ##
+
+AT_SETUP([[LAC: Exploratory stack]])
+
+m4_pushdef([AT_LAC_CHECK], [
+
+AT_BISON_OPTION_PUSHDEFS([$1])
+
+AT_DATA_GRAMMAR([input.y],
+[[%code {
+  #include <stdio.h>
+  void yyerror (char const *);
+  int yylex (]AT_PURE_IF([[YYSTYPE *]], [[void]])[);
+}
+
+]$1[
+%define parse.error verbose
+%token 'c'
+
+%%
+
+// default reductions in inconsistent states
+// v   v v   v v v v   v v v v v v v
+S: A B A A B A A A A B A A A A A A A B C C A A A A A A A A A A A A B ;
+
+A: 'a' | /*empty*/ { printf ("inconsistent default reduction\n"); } ;
+B: 'b' ;
+C: /*empty*/ { printf ("consistent default reduction\n"); } ;
+
+%%
+
+void
+yyerror (char const *msg)
+{
+  fprintf (stderr, "%s\n", msg);
+}
+
+int
+yylex (]AT_PURE_IF([[YYSTYPE *v]], [[void]])[)
+{
+  static char const *input = "bbbbc";]AT_PURE_IF([[
+  *v = 0;]])[
+  return *input++;
+}
+
+int
+main (void)
+{
+  yydebug = 1;
+  return yyparse ();
+}
+]])
+
+# Give exactly the right amount of memory to be sure there's no
+# off-by-one error, for example.
+AT_BISON_CHECK([[-Dparse.lac=full -Dparse.lac.es-capacity=12 \
+                 -t -o input.c input.y]], [[0]], [],
+[[input.y: conflicts: 21 shift/reduce
+]])
+AT_COMPILE([[input]])
+AT_PARSER_CHECK([[./input > stdout.txt 2> stderr.txt]], [[1]])
+
+# Make sure syntax error doesn't forget that 'a' is expected.  It would
+# be forgotten without lookahead correction.
+AT_CHECK([[grep 'syntax error,' stderr.txt]], [[0]],
+[[syntax error, unexpected 'c', expecting 'a' or 'b'
+]])
+
+# Check number of default reductions in inconsistent states to be sure
+# syntax error is detected before unnecessary reductions are performed.
+AT_CHECK([[perl -0777 -ne 'print s/inconsistent default reduction//g;' \
+           < stdout.txt || exit 77]], [[0]], [[14]])
+
+# Check number of default reductions in consistent states to be sure
+# it is performed before the syntax error is detected.
+AT_CHECK([[perl -0777 -ne 'print s/\bconsistent default reduction//g;' \
+           < stdout.txt || exit 77]], [[0]], [[2]])
+
+AT_BISON_OPTION_POPDEFS
+])
+
+AT_LAC_CHECK([[%define api.push-pull pull]])
+AT_LAC_CHECK([[%define api.push-pull pull %define api.pure]])
+AT_LAC_CHECK([[%define api.push-pull both]])
+AT_LAC_CHECK([[%define api.push-pull both %define api.pure]])
+
+m4_popdef([AT_LAC_CHECK])
+
+AT_CLEANUP
+
+
+
+## ------------------------ ##
+## LAC: Memory exhaustion.  ##
+## ------------------------ ##
+
+AT_SETUP([[LAC: Memory exhaustion]])
+
+m4_pushdef([AT_LAC_CHECK], [
+
+AT_DATA_GRAMMAR([input.y],
+[[%code {
+  #include <stdio.h>
+  void yyerror (char const *);
+  int yylex (void);
+}
+
+%error-verbose
+
+%%
+
+S: A A A A A A A A A ;
+A: /*empty*/ | 'a' ;
+
+%%
+
+void
+yyerror (char const *msg)
+{
+  fprintf (stderr, "%s\n", msg);
+}
+
+int
+yylex (void)
+{
+  static char const *input = "]$1[";
+  return *input++;
+}
+
+int
+main (void)
+{
+  yydebug = 1;
+  return yyparse ();
+}
+]])
+
+AT_BISON_CHECK([[-Dparse.lac=full -Dparse.lac.es-capacity=8 \
+                 -t -o input.c input.y]], [[0]], [],
+[[input.y: conflicts: 8 shift/reduce
+]])
+AT_COMPILE([[input]])
+
+])
+
+# Check for memory exhaustion during parsing.
+AT_LAC_CHECK([[]])
+AT_PARSER_CHECK([[./input]], [[2]], [[]],
+[[Starting parse
+Entering state 0
+Reading a token: Now at end of input.
+LAC: initial context established for $end
+LAC: checking lookahead $end: R2 G3 R2 G5 R2 G6 R2 G7 R2 G8 R2 G9 R2 G10 R2 G11 R2 (max stack size exceeded)
+memory exhausted
+Cleanup: discarding lookahead token $end ()
+Stack now 0
+]])
+
+# Induce an immediate syntax error with an undefined token, and check
+# for memory exhaustion while building syntax error message.
+AT_LAC_CHECK([[z]], [[0]])
+AT_PARSER_CHECK([[./input]], [[2]], [[]],
+[[Starting parse
+Entering state 0
+Reading a token: Next token is token $undefined ()
+LAC: initial context established for $undefined
+LAC: checking lookahead $undefined: Always Err
+Constructing syntax error message
+LAC: checking lookahead $end: R2 G3 R2 G5 R2 G6 R2 G7 R2 G8 R2 G9 R2 G10 R2 G11 R2 (max stack size exceeded)
+syntax error
+memory exhausted
+Cleanup: discarding lookahead token $undefined ()
+Stack now 0
+]])
+
+m4_popdef([AT_LAC_CHECK])
+
+AT_CLEANUP