]> git.saurik.com Git - bison.git/commitdiff
Allow specification of semantic predicates.
authorPaul Hilfinger <Hilfinger@cs.berkeley.edu>
Fri, 23 Jul 2010 02:08:10 +0000 (19:08 -0700)
committerPaul Hilfinger <Hilfinger@cs.berkeley.edu>
Sat, 24 Jul 2010 02:06:09 +0000 (19:06 -0700)
These changes allow users to prefix an action with %? to indicate that it
is a semantic predicate---an expression that is evaluated immediately (not
deferred, even in GLR nondeterministic mode) and causes a syntax error if
false.  In GLR parsers, this has the effect of killing one of a set of
split-off parses, just as would an ordinary syntax error.

Changelog:

    * NEWS: Describe new semantic-predicate feature.
    * data/c.m4 (b4_predicate_case): New definition.
    * data/java.m4 (b4_predicate_case): New definition.
    * data/glr.c (yyimmediate): Add definition.
    (yydoAction): Remove comment, now obsolete.
    Do YY_REDUCE_PRINT here.
    (yyglrReduce): Alter comment to indicate that semantic values
    need not be deferred.
    Remove YY_REDUCE_PRINT from here; done in yydoAction.
    (yyprocessOneStack): Pass immediate flag.
    Delete stacks rejected by predicates in newly split-off parsers.
    Change handling of yyerr so that only current stack gets deleted
    when semantic predicate fails.
    (yyfillin): Don't crash if a semantic value is unresolved (as may
    happen in predicate rules).
    Copy lr state as well in debugging mode.
    Update comment on setting of yysval to include yyloc as well.
    (yy_reduce_print): Add yynormal argument.  Perform fillin properly.
    Report unresolved RHS values.
    (yyimmediate): New table.
    * src/gram.h (struct rule): Add is_predicate field.
    * src/output.c (user_actions_output): Use b4_predicate_case for
    predicates.
    (prepare_symbols): Output yyimmediate.
    * src/scan-gram.l: Add %? token, SC_PREDICATE state.
    * src/scan-code.l (code_props_rule_action_init): Add is_predicate
    argument.
    * src/scan-code.h (struct code_props): Add is_predicate field.
    (code_props_rule_action_init): New interface.
    * src/parse-gram.y (%?{...}): New token.
    (rhs): Add %?{...} rule.
    * src/parse-gram.c: Regenerate.
    * src/parse-gram.h: Regenerate.
    * src/reader.c (grammar_current_rule_action_append): Add
    immediate argument.
    (grammar_midrule_action): Use new interface for
    code_props_rule_action_init.
    (grammar_current_rule_action_append): Ditto.
    (packgram): Transfer is_predicate value.
    * src/reader.h (grammar_current_rule_action_append): New interface.
    * doc/bison.texinfo: Document semantic predicates (%?).

    * data/glr.c (yylhsNonterm, yyisDefaultedState,yyDefaultAction)
    (yygetLRActions,yynewGLRStackItem,yyaddDeferredAction,yyinitStateSet)
    (yyinitGLRStack,yyexpandGLRStack,yyupdateSplit,yymarkStackDeleted)
    (yyundeleteLastStack,yyglrShift,yyglrShiftDefer,yydoAction,yyglrReduce)
    (yyidenticalOptions,yymergeOptionSets,yyresolveStates,yyresolveAction)
    (yyresolveLocations,yyresolveValue,yyreducePrint): Update parameter
    names in comments and mention all parameters.
    (struct yyGLRState): Fix description of yyposn field.
    (yyresolveLocations): Correct comment so as not to imply action when
    yyn1==0.

16 files changed:
ChangeLog
NEWS
data/c.m4
data/glr.c
data/java.m4
doc/bison.texinfo
src/gram.h
src/output.c
src/parse-gram.c
src/parse-gram.h
src/parse-gram.y
src/reader.c
src/reader.h
src/scan-code.h
src/scan-code.l
src/scan-gram.l

index 29a119c7b5a327deb292d27397c127e069f39010..9a35e816dc9356ff60912785bac14652b86eefb3 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,58 @@
+2010-07-23  Paul Hilfinger  <hilfingr@EECS.Berkeley.EDU>
+
+       * NEWS: Describe new semantic-predicate feature.
+        * data/c.m4 (b4_predicate_case): New definition.
+        * data/java.m4 (b4_predicate_case): New definition.
+        * data/glr.c (yyimmediate): Add definition.
+        (yydoAction): Remove comment, now obsolete.
+        Do YY_REDUCE_PRINT here.
+        (yyglrReduce): Alter comment to indicate that semantic values
+        need not be deferred.
+        Remove YY_REDUCE_PRINT from here; done in yydoAction.
+        (yyprocessOneStack): Pass immediate flag.
+        Delete stacks rejected by predicates in newly split-off parsers.
+        Change handling of yyerr so that only current stack gets deleted
+        when semantic predicate fails.
+        (yyfillin): Don't crash if a semantic value is unresolved (as may
+        happen in predicate rules).
+        Copy lr state as well in debugging mode.
+        Update comment on setting of yysval to include yyloc as well.
+        (yy_reduce_print): Add yynormal argument.  Perform fillin properly.
+        Report unresolved RHS values.
+        (yyimmediate): New table.
+        * src/gram.h (struct rule): Add is_predicate field.
+        * src/output.c (user_actions_output): Use b4_predicate_case for
+        predicates.
+        (prepare_symbols): Output yyimmediate.
+        * src/scan-gram.l: Add %? token, SC_PREDICATE state.
+        * src/scan-code.l (code_props_rule_action_init): Add is_predicate
+        argument.
+        * src/scan-code.h (struct code_props): Add is_predicate field.
+        (code_props_rule_action_init): New interface.
+        * src/parse-gram.y (%?{...}): New token.
+        (rhs): Add %?{...} rule.
+        * src/parse-gram.c: Regenerate.
+        * src/parse-gram.h: Regenerate.
+        * src/reader.c (grammar_current_rule_action_append): Add
+        immediate argument.
+        (grammar_midrule_action): Use new interface for
+        code_props_rule_action_init.
+        (grammar_current_rule_action_append): Ditto.
+        (packgram): Transfer is_predicate value.
+        * src/reader.h (grammar_current_rule_action_append): New interface.
+        * doc/bison.texinfo: Document semantic predicates (%?).
+    
+        * data/glr.c (yylhsNonterm, yyisDefaultedState,yyDefaultAction)
+        (yygetLRActions,yynewGLRStackItem,yyaddDeferredAction,yyinitStateSet)
+        (yyinitGLRStack,yyexpandGLRStack,yyupdateSplit,yymarkStackDeleted)
+        (yyundeleteLastStack,yyglrShift,yyglrShiftDefer,yydoAction,yyglrReduce)
+        (yyidenticalOptions,yymergeOptionSets,yyresolveStates,yyresolveAction)
+        (yyresolveLocations,yyresolveValue,yyreducePrint): Update parameter
+        names in comments and mention all parameters.
+        (struct yyGLRState): Fix description of yyposn field.
+        (yyresolveLocations): Correct comment so as not to imply action when
+        yyn1==0.
+       
 2010-06-17  Paul Eggert  <eggert@cs.ucla.edu>
 
        Update from GFDL GFDL 1.2 to 1.3.
 2010-06-17  Paul Eggert  <eggert@cs.ucla.edu>
 
        Update from GFDL GFDL 1.2 to 1.3.
diff --git a/NEWS b/NEWS
index e5ebfe4bca11d54bbd8286fdc428211111340b1d..878756bdb1409ccc64468632c3b232f9091df94a 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -51,6 +51,15 @@ Bison News
   use of the %error-verbose directive is deprecated in favor of
   %define parse.error "verbose".
 
   use of the %error-verbose directive is deprecated in favor of
   %define parse.error "verbose".
 
+** Semantic predicates
+
+  The new, experimental, semantic-predicate feature allows actions of
+  the form %?{ BOOLEAN-EXPRESSION }, which cause syntax errors (as for
+  YYERROR) if the expression evaluates to 0, and are evaluated immediately
+  in GLR parsers, rather than being deferred.  The result is that they
+  allow the programmer to prune possible parses based on the values of
+  runtime expressions.
+
 * Changes in version 2.5 (????-??-??):
 
 ** Named References Support
 * Changes in version 2.5 (????-??-??):
 
 ** Named References Support
index 9e7b31937acf10e536991719f41d65131e763302..db685c9a04f8fa65ee34c4d58a737704a87cddfe 100644 (file)
--- a/data/c.m4
+++ b/data/c.m4
@@ -417,6 +417,15 @@ b4_syncline([@oline@], [@ofile@])
     break;])
 
 
     break;])
 
 
+# b4_predicate_case(LABEL, CONDITIONS)
+# ------------------------------------
+m4_define([b4_predicate_case],
+[  case $1:
+    if (! ($2)) YYERROR;
+b4_syncline([@oline@], [@ofile@])
+    break;])
+
+
 # b4_yydestruct_generate(FUNCTION-DECLARATOR)
 # -------------------------------------------
 # Generate the "yydestruct" function, which declaration is issued using
 # b4_yydestruct_generate(FUNCTION-DECLARATOR)
 # -------------------------------------------
 # Generate the "yydestruct" function, which declaration is issued using
index 3c6ea8d7f03944c8126d7ee231dadb4d414ebb12..b72aef7532df2f34e49658e0a725a6a84530bbe7 100644 (file)
@@ -402,6 +402,13 @@ static const ]b4_int_type_for([b4_merger])[ yymerger[] =
   ]b4_merger[
 };
 
   ]b4_merger[
 };
 
+/* YYIMMEDIATE[RULE-NUM] -- True iff rule #RULE-NUM is not to be deferred, as
+   in the case of predicates.  */
+static const yybool yyimmediate[] =
+{
+  ]b4_immediate[
+};
+
 /* YYCONFLP[YYPACT[STATE-NUM]] -- Pointer into YYCONFL of start of
    list of conflicting reductions corresponding to action entry for
    state STATE-NUM in yytable.  0 means no conflicts.  The list in
 /* YYCONFLP[YYPACT[STATE-NUM]] -- Pointer into YYCONFL of start of
    list of conflicting reductions corresponding to action entry for
    state STATE-NUM in yytable.  0 means no conflicts.  The list in
@@ -693,7 +700,7 @@ struct yyGLRState {
   yyStateNum yylrState;
   /** Preceding state in this stack */
   yyGLRState* yypred;
   yyStateNum yylrState;
   /** Preceding state in this stack */
   yyGLRState* yypred;
-  /** Source position of the first token produced by my symbol */
+  /** Source position of the last token produced by my symbol */
   size_t yyposn;
   union {
     /** First in a chain of alternative reductions producing the
   size_t yyposn;
   union {
     /** First in a chain of alternative reductions producing the
@@ -806,9 +813,16 @@ yyfillin (yyGLRStackItem *yyvsp, int yylow0, int yylow1)
   s = yyvsp[yylow0].yystate.yypred;
   for (i = yylow0-1; i >= yylow1; i -= 1)
     {
   s = yyvsp[yylow0].yystate.yypred;
   for (i = yylow0-1; i >= yylow1; i -= 1)
     {
-      YYASSERT (s->yyresolved);
-      yyvsp[i].yystate.yyresolved = yytrue;
-      yyvsp[i].yystate.yysemantics.yysval = s->yysemantics.yysval;
+#if YYDEBUG
+      yyvsp[i].yystate.yylrState = s->yylrState;
+#endif
+      yyvsp[i].yystate.yyresolved = s->yyresolved;
+      if (s->yyresolved)
+       yyvsp[i].yystate.yysemantics.yysval = s->yysemantics.yysval;
+      else
+       /* The effect of using yysval or yyloc (in an immediate rule) is
+         * undefined.  */
+       yyvsp[i].yystate.yysemantics.yyfirstVal = NULL;
       yyvsp[i].yystate.yyloc = s->yyloc;
       s = yyvsp[i].yystate.yypred = s->yypred;
     }
       yyvsp[i].yystate.yyloc = s->yyloc;
       s = yyvsp[i].yystate.yypred = s->yypred;
     }
@@ -948,7 +962,7 @@ yydestroyGLRState (char const *yymsg, yyGLRState *yys]b4_user_formals[)
     }
 }
 
     }
 }
 
-/** Left-hand-side symbol for rule #RULE.  */
+/** Left-hand-side symbol for rule #YYRULE.  */
 static inline yySymbol
 yylhsNonterm (yyRuleNum yyrule)
 {
 static inline yySymbol
 yylhsNonterm (yyRuleNum yyrule)
 {
@@ -958,7 +972,7 @@ yylhsNonterm (yyRuleNum yyrule)
 #define yypact_value_is_default(yystate) \
   ]b4_table_value_equals([[pact]], [[yystate]], [b4_pact_ninf])[
 
 #define yypact_value_is_default(yystate) \
   ]b4_table_value_equals([[pact]], [[yystate]], [b4_pact_ninf])[
 
-/** True iff LR state STATE has only a default reduction (regardless
+/** True iff LR state YYSTATE has only a default reduction (regardless
  *  of token).  */
 static inline yybool
 yyisDefaultedState (yyStateNum yystate)
  *  of token).  */
 static inline yybool
 yyisDefaultedState (yyStateNum yystate)
@@ -966,7 +980,7 @@ yyisDefaultedState (yyStateNum yystate)
   return yypact_value_is_default (yypact[yystate]);
 }
 
   return yypact_value_is_default (yypact[yystate]);
 }
 
-/** The default reduction for STATE, assuming it has one.  */
+/** The default reduction for YYSTATE, assuming it has one.  */
 static inline yyRuleNum
 yydefaultAction (yyStateNum yystate)
 {
 static inline yyRuleNum
 yydefaultAction (yyStateNum yystate)
 {
@@ -981,8 +995,8 @@ yydefaultAction (yyStateNum yystate)
  *    R < 0:  Reduce on rule -R.
  *    R = 0:  Error.
  *    R > 0:  Shift to state R.
  *    R < 0:  Reduce on rule -R.
  *    R = 0:  Error.
  *    R > 0:  Shift to state R.
- *  Set *CONFLICTS to a pointer into yyconfl to 0-terminated list of
- *  conflicting reductions.
+ *  Set *YYCONFLICTS to a pointer into yyconfl to a 0-terminated list
+ *  of conflicting reductions.
  */
 static inline void
 yygetLRActions (yyStateNum yystate, int yytoken,
  */
 static inline void
 yygetLRActions (yyStateNum yystate, int yytoken,
@@ -1031,9 +1045,10 @@ yyisErrorAction (int yyaction)
 
                                /* GLRStates */
 
 
                                /* GLRStates */
 
-/** Return a fresh GLRStackItem.  Callers should call
- * YY_RESERVE_GLRSTACK afterwards to make sure there is sufficient
- * headroom.  */
+/** Return a fresh GLRStackItem in YYSTACKP.  The item is an LR state
+ *  if YYISSTATE, and otherwise a semantic option.  Callers should call
+ *  YY_RESERVE_GLRSTACK afterwards to make sure there is sufficient
+ *  headroom.  */
 
 static inline yyGLRStackItem*
 yynewGLRStackItem (yyGLRStack* yystackp, yybool yyisState)
 
 static inline yyGLRStackItem*
 yynewGLRStackItem (yyGLRStack* yystackp, yybool yyisState)
@@ -1046,9 +1061,9 @@ yynewGLRStackItem (yyGLRStack* yystackp, yybool yyisState)
 }
 
 /** Add a new semantic action that will execute the action for rule
 }
 
 /** Add a new semantic action that will execute the action for rule
- *  RULENUM on the semantic values in RHS to the list of
- *  alternative actions for STATE.  Assumes that RHS comes from
- *  stack #K of *STACKP. */
+ *  YYRULE on the semantic values in YYRHS to the list of
+ *  alternative actions for YYSTATE.  Assumes that YYRHS comes from
+ *  stack #YYK of *YYSTACKP. */
 static void
 yyaddDeferredAction (yyGLRStack* yystackp, size_t yyk, yyGLRState* yystate,
                     yyGLRState* yyrhs, yyRuleNum yyrule)
 static void
 yyaddDeferredAction (yyGLRStack* yystackp, size_t yyk, yyGLRState* yystate,
                     yyGLRState* yyrhs, yyRuleNum yyrule)
@@ -1073,7 +1088,7 @@ yyaddDeferredAction (yyGLRStack* yystackp, size_t yyk, yyGLRState* yystate,
 
                                /* GLRStacks */
 
 
                                /* GLRStacks */
 
-/** Initialize SET to a singleton set containing an empty stack.  */
+/** Initialize YYSET to a singleton set containing an empty stack.  */
 static yybool
 yyinitStateSet (yyGLRStateSet* yyset)
 {
 static yybool
 yyinitStateSet (yyGLRStateSet* yyset)
 {
@@ -1099,8 +1114,8 @@ static void yyfreeStateSet (yyGLRStateSet* yyset)
   YYFREE (yyset->yylookaheadNeeds);
 }
 
   YYFREE (yyset->yylookaheadNeeds);
 }
 
-/** Initialize STACK to a single empty stack, with total maximum
- *  capacity for all stacks of SIZE.  */
+/** Initialize *YYSTACKP to a single empty stack, with total maximum
+ *  capacity for all stacks of YYSIZE.  */
 static yybool
 yyinitGLRStack (yyGLRStack* yystackp, size_t yysize)
 {
 static yybool
 yyinitGLRStack (yyGLRStack* yystackp, size_t yysize)
 {
@@ -1122,7 +1137,7 @@ yyinitGLRStack (yyGLRStack* yystackp, size_t yysize)
 # define YYRELOC(YYFROMITEMS,YYTOITEMS,YYX,YYTYPE) \
   &((YYTOITEMS) - ((YYFROMITEMS) - (yyGLRStackItem*) (YYX)))->YYTYPE
 
 # define YYRELOC(YYFROMITEMS,YYTOITEMS,YYX,YYTYPE) \
   &((YYTOITEMS) - ((YYFROMITEMS) - (yyGLRStackItem*) (YYX)))->YYTYPE
 
-/** If STACK is expandable, extend it.  WARNING: Pointers into the
+/** If *YYSTACKP is expandable, extend it.  WARNING: Pointers into the
     stack from outside should be considered invalid after this call.
     We always expand when there are 1 or fewer items left AFTER an
     allocation, so that we can avoid having external pointers exist
     stack from outside should be considered invalid after this call.
     We always expand when there are 1 or fewer items left AFTER an
     allocation, so that we can avoid having external pointers exist
@@ -1192,9 +1207,9 @@ yyfreeGLRStack (yyGLRStack* yystackp)
   yyfreeStateSet (&yystackp->yytops);
 }
 
   yyfreeStateSet (&yystackp->yytops);
 }
 
-/** Assuming that S is a GLRState somewhere on STACK, update the
- *  splitpoint of STACK, if needed, so that it is at least as deep as
- *  S.  */
+/** Assuming that YYS is a GLRState somewhere on *YYSTACKP, update the
+ *  splitpoint of *YYSTACKP, if needed, so that it is at least as deep as
+ *  YYS.  */
 static inline void
 yyupdateSplit (yyGLRStack* yystackp, yyGLRState* yys)
 {
 static inline void
 yyupdateSplit (yyGLRStack* yystackp, yyGLRState* yys)
 {
@@ -1202,7 +1217,7 @@ yyupdateSplit (yyGLRStack* yystackp, yyGLRState* yys)
     yystackp->yysplitPoint = yys;
 }
 
     yystackp->yysplitPoint = yys;
 }
 
-/** Invalidate stack #K in STACK.  */
+/** Invalidate stack #YYK in *YYSTACKP.  */
 static inline void
 yymarkStackDeleted (yyGLRStack* yystackp, size_t yyk)
 {
 static inline void
 yymarkStackDeleted (yyGLRStack* yystackp, size_t yyk)
 {
@@ -1211,8 +1226,8 @@ yymarkStackDeleted (yyGLRStack* yystackp, size_t yyk)
   yystackp->yytops.yystates[yyk] = NULL;
 }
 
   yystackp->yytops.yystates[yyk] = NULL;
 }
 
-/** Undelete the last stack that was marked as deleted.  Can only be
-    done once after a deletion, and only when all other stacks have
+/** Undelete the last stack in *YYSTACKP that was marked as deleted.  Can
+    only be done once after a deletion, and only when all other stacks have
     been deleted.  */
 static void
 yyundeleteLastStack (yyGLRStack* yystackp)
     been deleted.  */
 static void
 yyundeleteLastStack (yyGLRStack* yystackp)
@@ -1261,8 +1276,9 @@ yyremoveDeletes (yyGLRStack* yystackp)
     }
 }
 
     }
 }
 
-/** Shift to a new state on stack #K of STACK, corresponding to LR state
- * LRSTATE, at input position POSN, with (resolved) semantic value SVAL.  */
+/** Shift to a new state on stack #YYK of *YYSTACKP, corresponding to LR
+ * state YYLRSTATE, at input position YYPOSN, with (resolved) semantic
+ * value *YYVALP and source location *YYLOCP.  */
 static inline void
 yyglrShift (yyGLRStack* yystackp, size_t yyk, yyStateNum yylrState,
            size_t yyposn,
 static inline void
 yyglrShift (yyGLRStack* yystackp, size_t yyk, yyStateNum yylrState,
            size_t yyposn,
@@ -1281,7 +1297,7 @@ yyglrShift (yyGLRStack* yystackp, size_t yyk, yyStateNum yylrState,
   YY_RESERVE_GLRSTACK (yystackp);
 }
 
   YY_RESERVE_GLRSTACK (yystackp);
 }
 
-/** Shift stack #K of YYSTACK, to a new state corresponding to LR
+/** Shift stack #YYK of *YYSTACKP, to a new state corresponding to LR
  *  state YYLRSTATE, at input position YYPOSN, with the (unresolved)
  *  semantic value of YYRHS under the action for YYRULE.  */
 static inline void
  *  state YYLRSTATE, at input position YYPOSN, with the (unresolved)
  *  semantic value of YYRHS under the action for YYRULE.  */
 static inline void
@@ -1301,11 +1317,51 @@ yyglrShiftDefer (yyGLRStack* yystackp, size_t yyk, yyStateNum yylrState,
   yyaddDeferredAction (yystackp, yyk, yynewState, yyrhs, yyrule);
 }
 
   yyaddDeferredAction (yystackp, yyk, yynewState, yyrhs, yyrule);
 }
 
-/** Pop the symbols consumed by reduction #RULE from the top of stack
- *  #K of STACK, and perform the appropriate semantic action on their
+#if !YYDEBUG
+# define YY_REDUCE_PRINT(Args)
+#else
+# define YY_REDUCE_PRINT(Args)         \
+do {                                   \
+  if (yydebug)                         \
+    yy_reduce_print Args;              \
+} while (YYID (0))
+
+/*----------------------------------------------------------------------.
+| Report that stack #YYK of *YYSTACKP is going to be reduced by YYRULE. |
+`----------------------------------------------------------------------*/
+
+/*ARGSUSED*/ static inline void
+yy_reduce_print (int yynormal, yyGLRStackItem* yyrhsVals, size_t yyk, yyRuleNum yyrule]b4_user_formals[)
+{
+  int yynrhs = yyrhsLength (yyrule);
+  int yyi;
+]b4_parse_param_use[]dnl
+[  YYFPRINTF (stderr, "Reducing stack %lu by rule %d (line %lu):\n",
+            (unsigned long int) yyk, yyrule - 1,
+            (unsigned long int) yyrline[yyrule]);
+  if (! yynormal)
+    yyfillin (yyrhsVals, 1, -yynrhs);
+  /* The symbols being reduced.  */
+  for (yyi = 0; yyi < yynrhs; yyi++)
+    {
+      YYFPRINTF (stderr, "   $%d = ", yyi + 1);
+      yy_symbol_print (stderr,
+                      yystos[yyrhsVals[yyi - yynrhs + 1].yystate.yylrState],
+                      &yyrhsVals[yyi - yynrhs + 1].yystate.yysemantics.yysval
+                      ]b4_locations_if([, &]b4_rhs_location(yynrhs, yyi + 1))[]dnl
+                      b4_user_args[);
+      if (!yyrhsVals[yyi - yynrhs + 1].yystate.yyresolved)
+        YYFPRINTF (stderr, " (unresolved)");
+      YYFPRINTF (stderr, "\n");
+    }
+}
+#endif
+
+/** Pop the symbols consumed by reduction #YYRULE from the top of stack
+ *  #YYK of *YYSTACKP, and perform the appropriate semantic action on their
  *  semantic values.  Assumes that all ambiguities in semantic values
  *  semantic values.  Assumes that all ambiguities in semantic values
- *  have been previously resolved.  Set *VALP to the resulting value,
- *  and *LOCP to the computed location (if any).  Return value is as
+ *  have been previously resolved.  Set *YYVALP to the resulting value,
+ *  and *YYLOCP to the computed location (if any).  Return value is as
  *  for userAction.  */
 static inline YYRESULTTAG
 yydoAction (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
  *  for userAction.  */
 static inline YYRESULTTAG
 yydoAction (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
@@ -1321,15 +1377,12 @@ yydoAction (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
       yystackp->yynextFree -= yynrhs;
       yystackp->yyspaceLeft += yynrhs;
       yystackp->yytops.yystates[0] = & yystackp->yynextFree[-1].yystate;
       yystackp->yynextFree -= yynrhs;
       yystackp->yyspaceLeft += yynrhs;
       yystackp->yytops.yystates[0] = & yystackp->yynextFree[-1].yystate;
+      YY_REDUCE_PRINT ((1, yyrhs, yyk, yyrule]b4_user_args[));
       return yyuserAction (yyrule, yynrhs, yyrhs,
                           yyvalp, yylocp, yystackp]b4_user_args[);
     }
   else
     {
       return yyuserAction (yyrule, yynrhs, yyrhs,
                           yyvalp, yylocp, yystackp]b4_user_args[);
     }
   else
     {
-      /* At present, doAction is never called in nondeterministic
-       * mode, so this branch is never taken.  It is here in
-       * anticipation of a future feature that will allow immediate
-       * evaluation of selected actions in nondeterministic mode.  */
       int yyi;
       yyGLRState* yys;
       yyGLRStackItem yyrhsVals[YYMAXRHS + YYMAXLEFT + 1];
       int yyi;
       yyGLRState* yys;
       yyGLRStackItem yyrhsVals[YYMAXRHS + YYMAXLEFT + 1];
@@ -1345,60 +1398,21 @@ yydoAction (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
        }
       yyupdateSplit (yystackp, yys);
       yystackp->yytops.yystates[yyk] = yys;
        }
       yyupdateSplit (yystackp, yys);
       yystackp->yytops.yystates[yyk] = yys;
+      YY_REDUCE_PRINT ((0, yyrhsVals + YYMAXRHS + YYMAXLEFT - 1, yyk, yyrule]b4_user_args[));
       return yyuserAction (yyrule, yynrhs, yyrhsVals + YYMAXRHS + YYMAXLEFT - 1,
                           yyvalp, yylocp, yystackp]b4_user_args[);
     }
 }
 
       return yyuserAction (yyrule, yynrhs, yyrhsVals + YYMAXRHS + YYMAXLEFT - 1,
                           yyvalp, yylocp, yystackp]b4_user_args[);
     }
 }
 
-#if !YYDEBUG
-# define YY_REDUCE_PRINT(Args)
-#else
-# define YY_REDUCE_PRINT(Args)         \
-do {                                   \
-  if (yydebug)                         \
-    yy_reduce_print Args;              \
-} while (YYID (0))
-
-/*----------------------------------------------------------.
-| Report that the RULE is going to be reduced on stack #K.  |
-`----------------------------------------------------------*/
-
-/*ARGSUSED*/ static inline void
-yy_reduce_print (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule]b4_user_formals[)
-{
-  int yynrhs = yyrhsLength (yyrule);
-  yybool yynormal __attribute__ ((__unused__)) =
-    (yystackp->yysplitPoint == NULL);
-  yyGLRStackItem* yyvsp = (yyGLRStackItem*) yystackp->yytops.yystates[yyk];
-  int yylow = 1;
-  int yyi;
-]b4_parse_param_use[]dnl
-[  YYFPRINTF (stderr, "Reducing stack %lu by rule %d (line %lu):\n",
-            (unsigned long int) yyk, yyrule - 1,
-            (unsigned long int) yyrline[yyrule]);
-  /* The symbols being reduced.  */
-  for (yyi = 0; yyi < yynrhs; yyi++)
-    {
-      YYFPRINTF (stderr, "   $%d = ", yyi + 1);
-      yy_symbol_print (stderr,
-                       ]yystos@{b4_rhs_data(yynrhs, yyi + 1).yylrState@}[,
-                      &]b4_rhs_value(yynrhs, yyi + 1)[
-                      ]b4_locations_if([, &]b4_rhs_location(yynrhs, yyi + 1))[]dnl
-                      b4_user_args[);
-      YYFPRINTF (stderr, "\n");
-    }
-}
-#endif
-
-/** Pop items off stack #K of STACK according to grammar rule RULE,
+/** Pop items off stack #YYK of *YYSTACKP according to grammar rule YYRULE,
  *  and push back on the resulting nonterminal symbol.  Perform the
  *  and push back on the resulting nonterminal symbol.  Perform the
- *  semantic action associated with RULE and store its value with the
- *  newly pushed state, if FORCEEVAL or if STACK is currently
+ *  semantic action associated with YYRULE and store its value with the
+ *  newly pushed state, if YYFORCEEVAL or if *YYSTACKP is currently
  *  unambiguous.  Otherwise, store the deferred semantic action with
  *  the new state.  If the new state would have an identical input
  *  position, LR state, and predecessor to an existing state on the stack,
  *  unambiguous.  Otherwise, store the deferred semantic action with
  *  the new state.  If the new state would have an identical input
  *  position, LR state, and predecessor to an existing state on the stack,
- *  it is identified with that existing state, eliminating stack #K from
- *  the STACK.  In this case, the (necessarily deferred) semantic value is
+ *  it is identified with that existing state, eliminating stack #YYK from
+ *  *YYSTACKP.  In this case, the semantic value is
  *  added to the options for the existing state's semantic value.
  */
 static inline YYRESULTTAG
  *  added to the options for the existing state's semantic value.
  */
 static inline YYRESULTTAG
@@ -1409,12 +1423,19 @@ yyglrReduce (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
 
   if (yyforceEval || yystackp->yysplitPoint == NULL)
     {
 
   if (yyforceEval || yystackp->yysplitPoint == NULL)
     {
+      YYRESULTTAG yyflag;
       YYSTYPE yysval;
       YYLTYPE yyloc;
 
       YYSTYPE yysval;
       YYLTYPE yyloc;
 
-      YY_REDUCE_PRINT ((yystackp, yyk, yyrule]b4_user_args[));
-      YYCHK (yydoAction (yystackp, yyk, yyrule, &yysval,
-                        &yyloc]b4_user_args[));
+      yyflag = yydoAction (yystackp, yyk, yyrule, &yysval,
+                          &yyloc]b4_user_args[);
+      if (yyflag == yyerr)
+        {
+         YYDPRINTF ((stderr, "Parse on stack %lu rejected by rule #%d.\n",
+                    (unsigned long int) yyk, yyrule - 1));
+        }
+      if (yyflag != yyok)
+        return yyflag;      
       YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyrule], &yysval, &yyloc);
       yyglrShift (yystackp, yyk,
                  yyLRgotoState (yystackp->yytops.yystates[yyk]->yylrState,
       YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyrule], &yysval, &yyloc);
       yyglrShift (yystackp, yyk,
                  yyLRgotoState (yystackp->yytops.yystates[yyk]->yylrState,
@@ -1508,7 +1529,7 @@ yysplitStack (yyGLRStack* yystackp, size_t yyk)
   return yystackp->yytops.yysize-1;
 }
 
   return yystackp->yytops.yysize-1;
 }
 
-/** True iff Y0 and Y1 represent identical options at the top level.
+/** True iff YYY0 and YYY1 represent identical options at the top level.
  *  That is, they represent the same rule applied to RHS symbols
  *  that produce the same terminal symbols.  */
 static yybool
  *  That is, they represent the same rule applied to RHS symbols
  *  that produce the same terminal symbols.  */
 static yybool
@@ -1530,8 +1551,8 @@ yyidenticalOptions (yySemanticOption* yyy0, yySemanticOption* yyy1)
     return yyfalse;
 }
 
     return yyfalse;
 }
 
-/** Assuming identicalOptions (Y0,Y1), destructively merge the
- *  alternative semantic values for the RHS-symbols of Y1 and Y0.  */
+/** Assuming identicalOptions (YYY0,YYY1), destructively merge the
+ *  alternative semantic values for the RHS-symbols of YYY1 and YYY0.  */
 static void
 yymergeOptionSets (yySemanticOption* yyy0, yySemanticOption* yyy1)
 {
 static void
 yymergeOptionSets (yySemanticOption* yyy0, yySemanticOption* yyy1)
 {
@@ -1612,11 +1633,11 @@ static YYRESULTTAG yyresolveValue (yyGLRState* yys,
                                   yyGLRStack* yystackp]b4_user_formals[);
 
 
                                   yyGLRStack* yystackp]b4_user_formals[);
 
 
-/** Resolve the previous N states starting at and including state S.  If result
- *  != yyok, some states may have been left unresolved possibly with empty
- *  semantic option chains.  Regardless of whether result = yyok, each state
- *  has been left with consistent data so that yydestroyGLRState can be invoked
- *  if necessary.  */
+/** Resolve the previous YYN states starting at and including state YYS
+ *  on *YYSTACKP. If result != yyok, some states may have been left
+ *  unresolved possibly with empty semantic option chains.  Regardless
+ *  of whether result = yyok, each state has been left with consistent
+ *  data so that yydestroyGLRState can be invoked if necessary.  */
 static YYRESULTTAG
 yyresolveStates (yyGLRState* yys, int yyn,
                 yyGLRStack* yystackp]b4_user_formals[)
 static YYRESULTTAG
 yyresolveStates (yyGLRState* yys, int yyn,
                 yyGLRStack* yystackp]b4_user_formals[)
@@ -1631,9 +1652,10 @@ yyresolveStates (yyGLRState* yys, int yyn,
   return yyok;
 }
 
   return yyok;
 }
 
-/** Resolve the states for the RHS of OPT, perform its user action, and return
- *  the semantic value and location.  Regardless of whether result = yyok, all
- *  RHS states have been destroyed (assuming the user action destroys all RHS
+/** Resolve the states for the RHS of YYOPT on *YYSTACKP, perform its
+ *  user action, and return the semantic value and location in *YYVALP
+ *  and *YYLOCP.  Regardless of whether result = yyok, all RHS states
+ *  have been destroyed (assuming the user action destroys all RHS
  *  semantic values if invoked).  */
 static YYRESULTTAG
 yyresolveAction (yySemanticOption* yyopt, yyGLRStack* yystackp,
  *  semantic values if invoked).  */
 static YYRESULTTAG
 yyresolveAction (yySemanticOption* yyopt, yyGLRStack* yystackp,
@@ -1743,9 +1765,9 @@ yyreportAmbiguity (yySemanticOption* yyx0,
   return yyabort;
 }
 
   return yyabort;
 }
 
-/** Starting at and including state S1, resolve the location for each of the
- *  previous N1 states that is unresolved.  The first semantic option of a state
- *  is always chosen.  */
+/** Resolve the locations for each of the YYN1 states in *YYSTACKP,
+ *  ending at YYS1.  Has no effect on previously resolved states.
+ *  The first semantic option of a state is always chosen.  */
 static void
 yyresolveLocations (yyGLRState* yys1, int yyn1,
                    yyGLRStack *yystackp]b4_user_formals[)
 static void
 yyresolveLocations (yyGLRState* yys1, int yyn1,
                    yyGLRStack *yystackp]b4_user_formals[)
@@ -1801,11 +1823,12 @@ yyresolveLocations (yyGLRState* yys1, int yyn1,
     }
 }
 
     }
 }
 
-/** Resolve the ambiguity represented in state S, perform the indicated
- *  actions, and set the semantic value of S.  If result != yyok, the chain of
- *  semantic options in S has been cleared instead or it has been left
- *  unmodified except that redundant options may have been removed.  Regardless
- *  of whether result = yyok, S has been left with consistent data so that
+/** Resolve the ambiguity represented in state YYS in *YYSTACKP,
+ *  perform the indicated actions, and set the semantic value of YYS.
+ *  If result != yyok, the chain of semantic options in YYS has been
+ *  cleared instead or it has been left unmodified except that
+ *  redundant options may have been removed.  Regardless of whether
+ *  result = yyok, YYS has been left with consistent data so that
  *  yydestroyGLRState can be invoked if necessary.  */
 static YYRESULTTAG
 yyresolveValue (yyGLRState* yys, yyGLRStack* yystackp]b4_user_formals[)
  *  yydestroyGLRState can be invoked if necessary.  */
 static YYRESULTTAG
 yyresolveValue (yyGLRState* yys, yyGLRStack* yystackp]b4_user_formals[)
@@ -1950,6 +1973,7 @@ yyprocessOneStack (yyGLRStack* yystackp, size_t yyk,
   int yyaction;
   const short int* yyconflicts;
   yyRuleNum yyrule;
   int yyaction;
   const short int* yyconflicts;
   yyRuleNum yyrule;
+  YYRESULTTAG yyflag;
 
   while (yystackp->yytops.yystates[yyk] != NULL)
     {
 
   while (yystackp->yytops.yystates[yyk] != NULL)
     {
@@ -1969,11 +1993,21 @@ yyprocessOneStack (yyGLRStack* yystackp, size_t yyk,
              yymarkStackDeleted (yystackp, yyk);
              return yyok;
            }
              yymarkStackDeleted (yystackp, yyk);
              return yyok;
            }
-         YYCHK (yyglrReduce (yystackp, yyk, yyrule, yyfalse]b4_user_args[));
+         yyflag = yyglrReduce (yystackp, yyk, yyrule, yyimmediate[yyrule]]b4_user_args[);
+          if (yyflag == yyerr)
+            {
+             YYDPRINTF ((stderr, "Stack %lu dies (predicate failure or explicit user error).\n",
+                         (unsigned long int) yyk));
+             yymarkStackDeleted (yystackp, yyk);
+             return yyok;
+           }
+         if (yyflag != yyok)
+            return yyflag;
        }
       else
        {
          yySymbol yytoken;
        }
       else
        {
          yySymbol yytoken;
+
          yystackp->yytops.yylookaheadNeeds[yyk] = yytrue;
          if (yychar == YYEMPTY)
            {
          yystackp->yytops.yylookaheadNeeds[yyk] = yytrue;
          if (yychar == YYEMPTY)
            {
@@ -1996,14 +2030,25 @@ yyprocessOneStack (yyGLRStack* yystackp, size_t yyk,
 
          while (*yyconflicts != 0)
            {
 
          while (*yyconflicts != 0)
            {
+             YYRESULTTAG yyflag;
              size_t yynewStack = yysplitStack (yystackp, yyk);
              YYDPRINTF ((stderr, "Splitting off stack %lu from %lu.\n",
                          (unsigned long int) yynewStack,
                          (unsigned long int) yyk));
              size_t yynewStack = yysplitStack (yystackp, yyk);
              YYDPRINTF ((stderr, "Splitting off stack %lu from %lu.\n",
                          (unsigned long int) yynewStack,
                          (unsigned long int) yyk));
-             YYCHK (yyglrReduce (yystackp, yynewStack,
-                                 *yyconflicts, yyfalse]b4_user_args[));
-             YYCHK (yyprocessOneStack (yystackp, yynewStack,
-                                       yyposn]b4_pure_args[));
+             yyflag = yyglrReduce (yystackp, yynewStack,
+                                   *yyconflicts,
+                                   yyimmediate[*yyconflicts]]b4_user_args[);
+              if (yyflag == yyok)
+               YYCHK (yyprocessOneStack (yystackp, yynewStack,
+                                         yyposn]b4_pure_args[));
+             else if (yyflag == yyerr)
+               {
+                 YYDPRINTF ((stderr, "Stack %lu dies.\n", 
+                             (unsigned long int) yynewStack));
+                 yymarkStackDeleted (yystackp, yynewStack);
+               }
+             else
+               return yyflag;
              yyconflicts += 1;
            }
 
              yyconflicts += 1;
            }
 
@@ -2017,8 +2062,19 @@ yyprocessOneStack (yyGLRStack* yystackp, size_t yyk,
              break;
            }
          else
              break;
            }
          else
-           YYCHK (yyglrReduce (yystackp, yyk, -yyaction,
-                               yyfalse]b4_user_args[));
+            {
+             yyflag = yyglrReduce (yystackp, yyk, -yyaction,
+                                   yyimmediate[-yyaction]]b4_user_args[);
+             if (yyflag == yyerr)
+                {
+                 YYDPRINTF ((stderr, "Stack %lu dies (predicate failure or explicit user error).\n",
+                             (unsigned long int) yyk));
+                 yymarkStackDeleted (yystackp, yyk);
+                  break;
+               }
+             else if (yyflag != yyok)
+                return yyflag;
+            }
        }
     }
   return yyok;
        }
     }
   return yyok;
@@ -2249,7 +2305,6 @@ yyrecoverSyntaxError (yyGLRStack* yystackp]b4_user_formals[)
     }                                                                       \
   } while (YYID (0))
 
     }                                                                       \
   } while (YYID (0))
 
-
 /*----------.
 | yyparse.  |
 `----------*/
 /*----------.
 | yyparse.  |
 `----------*/
index 781a7df20885bad3024c30623908d6525a45baa1..32ff2156411649f51621b35c9fe1f95a0bc41bb3 100644 (file)
@@ -169,6 +169,13 @@ m4_define([b4_case], [  case $1:
   break;
     ])
 
   break;
     ])
 
+# b4_predicate_case(LABEL, CONDITIONS)
+# ------------------------------------
+m4_define([b4_predicate_case], [  case $1:
+     if (! ($2)) YYERROR;
+    break;
+    ])
+
 
 ## ---------------- ##
 ## Default values.  ##
 
 ## ---------------- ##
 ## Default values.  ##
index 3a4ee845b7fe1dbc08ddfbe564a5761d5274fac1..6d9d1be2a54a6660121eeec67e110a77b2126b87 100644 (file)
@@ -136,6 +136,7 @@ Writing @acronym{GLR} Parsers
 * Simple GLR Parsers::     Using @acronym{GLR} parsers on unambiguous grammars.
 * Merging GLR Parses::     Using @acronym{GLR} parsers to resolve ambiguities.
 * GLR Semantic Actions::   Deferred semantic actions have special concerns.
 * Simple GLR Parsers::     Using @acronym{GLR} parsers on unambiguous grammars.
 * Merging GLR Parses::     Using @acronym{GLR} parsers to resolve ambiguities.
 * GLR Semantic Actions::   Deferred semantic actions have special concerns.
+* Semantic Predicates::    Controlling a parse with arbitrary computations.
 * Compiler Requirements::  @acronym{GLR} parsers require a modern C compiler.
 
 Examples
 * Compiler Requirements::  @acronym{GLR} parsers require a modern C compiler.
 
 Examples
@@ -758,6 +759,7 @@ merged result.
 * Simple GLR Parsers::     Using @acronym{GLR} parsers on unambiguous grammars.
 * Merging GLR Parses::     Using @acronym{GLR} parsers to resolve ambiguities.
 * GLR Semantic Actions::   Deferred semantic actions have special concerns.
 * Simple GLR Parsers::     Using @acronym{GLR} parsers on unambiguous grammars.
 * Merging GLR Parses::     Using @acronym{GLR} parsers to resolve ambiguities.
 * GLR Semantic Actions::   Deferred semantic actions have special concerns.
+* Semantic Predicates::    Controlling a parse with arbitrary computations.
 * Compiler Requirements::  @acronym{GLR} parsers require a modern C compiler.
 @end menu
 
 * Compiler Requirements::  @acronym{GLR} parsers require a modern C compiler.
 @end menu
 
@@ -1163,6 +1165,65 @@ In a deferred semantic action, its effect is undefined.
 Also, see @ref{Location Default Action, ,Default Action for Locations}, which
 describes a special usage of @code{YYLLOC_DEFAULT} in @acronym{GLR} parsers.
 
 Also, see @ref{Location Default Action, ,Default Action for Locations}, which
 describes a special usage of @code{YYLLOC_DEFAULT} in @acronym{GLR} parsers.
 
+@node Semantic Predicates
+@subsection Controlling a Parse with Arbitrary Predicates
+@findex %?
+@cindex Semantic predicates in @acronym{GLR} parsers
+
+In addition to the @code{%dprec} and @code{%merge} directives,
+@acronym{GLR} parsers
+allow you to reject parses on the basis of arbitrary computations executed
+in user code, without having Bison treat this rejection as an error
+if there are alternative parses. (This feature is experimental and may
+evolve.  We welcome user feedback.)  For example,
+
+@smallexample
+widget :
+          %?@{ new_syntax @} "widget" id new_args   @{ $$ = f($3, $4); @}
+       |  %?@{ !new_syntax @} "widget" id old_args  @{ $$ = f($3, $4); @}
+       ;
+@end smallexample
+
+@noindent
+is one way to allow the same parser to handle two different syntaxes for 
+widgets.  The clause preceded by @code{%?} is treated like an ordinary
+action, except that its text is treated as an expression and is always
+evaluated immediately (even when in nondeterministic mode).  If the 
+expression yields 0 (false), the clause is treated as a syntax error,
+which, in a nondeterministic parser, causes the stack in which it is reduced 
+to die.  In a deterministic parser, it acts like YYERROR.
+
+As the example shows, predicates otherwise look like semantic actions, and
+therefore you must be take them into account when determining the numbers
+to use for denoting the semantic values of right-hand side symbols.
+Predicate actions, however, have no defined value, and may not be given
+labels.
+
+There is a subtle difference between semantic predicates and ordinary
+actions in nondeterministic mode, since the latter are deferred.
+For example, we could try to rewrite the previous example as 
+
+@smallexample
+widget :
+          @{ if (!new_syntax) YYERROR; @} "widget" id new_args  @{ $$ = f($3, $4); @}
+       |  @{ if (new_syntax) YYERROR; @} "widget" id old_args   @{ $$ = f($3, $4); @}
+       ;
+@end smallexample
+
+@noindent
+(reversing the sense of the predicate tests to cause an error when they are
+false).  However, this
+does @emph{not} have the same effect if @code{new_args} and @code{old_args}
+have overlapping syntax.
+Since the mid-rule actions testing @code{new_syntax} are deferred, 
+a @acronym{GLR} parser first encounters the unresolved ambiguous reduction 
+for cases where @code{new_args} and @code{old_args} recognize the same string
+@emph{before} performing the tests of @code{new_syntax}.  It therefore
+reports an error.
+
+Finally, be careful in writing predicates: deferred actions have not been
+evaluated, so that using them in a predicate will have undefined effects.
+
 @node Compiler Requirements
 @subsection Considerations when Compiling @acronym{GLR} Parsers
 @cindex @code{inline}
 @node Compiler Requirements
 @subsection Considerations when Compiling @acronym{GLR} Parsers
 @cindex @code{inline}
@@ -10610,6 +10671,19 @@ file.  @xref{Grammar Outline, ,Outline of a Bison
 Grammar}.
 @end deffn
 
 Grammar}.
 @end deffn
 
+@deffn {Directive} %?@{@var{expression}@}
+Predicate actions.  This is a type of action clause that may appear in
+rules. The expression is evaluated, and if false, causes a syntax error.  In
+@acronym{GLR} parsers during nondeterministic operation,  
+this silently causes an alternative parse to die.  During deterministic
+operation, it is the same as the effect of YYERROR.
+@xref{Semantic Predicates}.
+
+This feature is experimental.
+More user feedback will help to determine whether it should become a permanent
+feature.
+@end deffn
+
 @deffn {Construct} /*@dots{}*/
 Comment delimiters, as in C.
 @end deffn
 @deffn {Construct} /*@dots{}*/
 Comment delimiters, as in C.
 @end deffn
index 1b750fd1e07f670601e46f4a0981bfc9e385f8dc..85792d6f9785f62d31993c4cb7a0c4ed8637bdc9 100644 (file)
@@ -194,6 +194,7 @@ typedef struct
 
   location location;
   bool useful;
 
   location location;
   bool useful;
+  bool is_predicate;
 
   const char *action;
   location action_location;
 
   const char *action;
   location action_location;
index fa448a6f2748d282b140d340b292245027c239e6..6b29e5c056cd337fbe045ddce49b5e147b054728 100644 (file)
@@ -204,7 +204,7 @@ prepare_symbols (void)
 
 /*----------------------------------------------------------------.
 | Prepare the muscles related to the rules: r1, r2, rline, dprec, |
 
 /*----------------------------------------------------------------.
 | Prepare the muscles related to the rules: r1, r2, rline, dprec, |
-| merger.                                                         |
+| merger, immediate.                                              |
 `----------------------------------------------------------------*/
 
 static void
 `----------------------------------------------------------------*/
 
 static void
@@ -215,6 +215,7 @@ prepare_rules (void)
   unsigned int *r2 = xnmalloc (nrules, sizeof *r2);
   int *dprec = xnmalloc (nrules, sizeof *dprec);
   int *merger = xnmalloc (nrules, sizeof *merger);
   unsigned int *r2 = xnmalloc (nrules, sizeof *r2);
   int *dprec = xnmalloc (nrules, sizeof *dprec);
   int *merger = xnmalloc (nrules, sizeof *merger);
+  int *immediate = xnmalloc (nrules, sizeof *immediate);
 
   rule_number r;
   for (r = 0; r < nrules; ++r)
 
   rule_number r;
   for (r = 0; r < nrules; ++r)
@@ -229,6 +230,8 @@ prepare_rules (void)
       dprec[r] = rules[r].dprec;
       /* Merger-function index (GLR).  */
       merger[r] = rules[r].merger;
       dprec[r] = rules[r].dprec;
       /* Merger-function index (GLR).  */
       merger[r] = rules[r].merger;
+      /* Immediate reduction flags (GLR).  */
+      immediate[r] = rules[r].is_predicate;
     }
 
   muscle_insert_unsigned_int_table ("rline", rline, 0, 0, nrules);
     }
 
   muscle_insert_unsigned_int_table ("rline", rline, 0, 0, nrules);
@@ -236,6 +239,7 @@ prepare_rules (void)
   muscle_insert_unsigned_int_table ("r2", r2, 0, 0, nrules);
   muscle_insert_int_table ("dprec", dprec, 0, 0, nrules);
   muscle_insert_int_table ("merger", merger, 0, 0, nrules);
   muscle_insert_unsigned_int_table ("r2", r2, 0, 0, nrules);
   muscle_insert_int_table ("dprec", dprec, 0, 0, nrules);
   muscle_insert_int_table ("merger", merger, 0, 0, nrules);
+  muscle_insert_int_table ("immediate", immediate, 0, 0, nrules);
 
   MUSCLE_INSERT_INT ("rules_number", nrules);
   MUSCLE_INSERT_INT ("max_left_semantic_context", max_left_semantic_context);
 
   MUSCLE_INSERT_INT ("rules_number", nrules);
   MUSCLE_INSERT_INT ("max_left_semantic_context", max_left_semantic_context);
@@ -349,8 +353,9 @@ user_actions_output (FILE *out)
   for (r = 0; r < nrules; ++r)
     if (rules[r].action)
       {
   for (r = 0; r < nrules; ++r)
     if (rules[r].action)
       {
-       fprintf (out, "b4_case(%d, [b4_syncline(%d, ", r + 1,
-                rules[r].action_location.start.line);
+       fprintf (out, "b4_%scase(%d, [b4_syncline(%d, ",
+                rules[r].is_predicate ? "predicate_" : "",
+                r + 1, rules[r].action_location.start.line);
        escaped_output (out, rules[r].action_location.start.file);
        fprintf (out, ")\n[    %s]])\n\n", rules[r].action);
       }
        escaped_output (out, rules[r].action_location.start.file);
        fprintf (out, ")\n[    %s]])\n\n", rules[r].action);
       }
index 4fef5a2fda283e6ff47ceaa3de6047bc7c5a34e2..e5713416cfa08d8c73fc5d87689b516ad119247e 100644 (file)
@@ -1,8 +1,9 @@
-/* A Bison parser, made by GNU Bison 2.4.483-4ad39-dirty.  */
+/* A Bison parser, made by GNU Bison 2.4.516-804e.  */
 
 /* Implementation for Bison's Yacc-like parsers in C
 
 
 /* Implementation for Bison's Yacc-like parsers in C
 
-   Copyright (C) 1984, 1989-1990, 2000-2010 Free Software Foundation, Inc.
+   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+   2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -44,7 +45,7 @@
 #define YYBISON 1
 
 /* Bison version.  */
 #define YYBISON 1
 
 /* Bison version.  */
-#define YYBISON_VERSION "2.4.483-4ad39-dirty"
+#define YYBISON_VERSION "2.4.516-804e"
 
 /* Skeleton name.  */
 #define YYSKELETON_NAME "yacc.c"
 
 /* Skeleton name.  */
 #define YYSKELETON_NAME "yacc.c"
@@ -76,7 +77,8 @@
 #line 1 "src/parse-gram.y"
 /* Bison Grammar Parser                             -*- C -*-
 
 #line 1 "src/parse-gram.y"
 /* Bison Grammar Parser                             -*- C -*-
 
-   Copyright (C) 2002-2010 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+   Free Software Foundation, Inc.
 
    This file is part of Bison, the GNU Compiler Compiler.
 
 
    This file is part of Bison, the GNU Compiler Compiler.
 
@@ -127,7 +129,7 @@ static void gram_error (location const *, char const *);
 static char const *char_name (char);
 
 /* Line 252 of yacc.c  */
 static char const *char_name (char);
 
 /* Line 252 of yacc.c  */
-#line 131 "src/parse-gram.c"
+#line 133 "src/parse-gram.c"
 
 /* Enabling traces.  */
 #ifndef YYDEBUG
 
 /* Enabling traces.  */
 #ifndef YYDEBUG
@@ -149,7 +151,7 @@ static char const *char_name (char);
 
 /* "%code requires" blocks.  */
 /* Line 272 of yacc.c  */
 
 /* "%code requires" blocks.  */
 /* Line 272 of yacc.c  */
-#line 201 "src/parse-gram.y"
+#line 202 "src/parse-gram.y"
 
 # ifndef PARAM_TYPE
 #  define PARAM_TYPE
 
 # ifndef PARAM_TYPE
 #  define PARAM_TYPE
@@ -164,7 +166,7 @@ static char const *char_name (char);
 
 
 /* Line 272 of yacc.c  */
 
 
 /* Line 272 of yacc.c  */
-#line 168 "src/parse-gram.c"
+#line 170 "src/parse-gram.c"
 
 /* Tokens.  */
 #ifndef YYTOKENTYPE
 
 /* Tokens.  */
 #ifndef YYTOKENTYPE
@@ -211,21 +213,22 @@ static char const *char_name (char);
      PERCENT_VERBOSE = 293,
      PERCENT_YACC = 294,
      BRACED_CODE = 295,
      PERCENT_VERBOSE = 293,
      PERCENT_YACC = 294,
      BRACED_CODE = 295,
-     BRACKETED_ID = 296,
-     CHAR = 297,
-     EPILOGUE = 298,
-     EQUAL = 299,
-     ID = 300,
-     ID_COLON = 301,
-     PERCENT_PERCENT = 302,
-     PIPE = 303,
-     PROLOGUE = 304,
-     SEMICOLON = 305,
-     TAG = 306,
-     TAG_ANY = 307,
-     TAG_NONE = 308,
-     PERCENT_PARAM = 309,
-     PERCENT_UNION = 310
+     BRACED_PREDICATE = 296,
+     BRACKETED_ID = 297,
+     CHAR = 298,
+     EPILOGUE = 299,
+     EQUAL = 300,
+     ID = 301,
+     ID_COLON = 302,
+     PERCENT_PERCENT = 303,
+     PIPE = 304,
+     PROLOGUE = 305,
+     SEMICOLON = 306,
+     TAG = 307,
+     TAG_ANY = 308,
+     TAG_NONE = 309,
+     PERCENT_PARAM = 310,
+     PERCENT_UNION = 311
    };
 #endif
 /* Tokens.  */
    };
 #endif
 /* Tokens.  */
@@ -268,21 +271,22 @@ static char const *char_name (char);
 #define PERCENT_VERBOSE 293
 #define PERCENT_YACC 294
 #define BRACED_CODE 295
 #define PERCENT_VERBOSE 293
 #define PERCENT_YACC 294
 #define BRACED_CODE 295
-#define BRACKETED_ID 296
-#define CHAR 297
-#define EPILOGUE 298
-#define EQUAL 299
-#define ID 300
-#define ID_COLON 301
-#define PERCENT_PERCENT 302
-#define PIPE 303
-#define PROLOGUE 304
-#define SEMICOLON 305
-#define TAG 306
-#define TAG_ANY 307
-#define TAG_NONE 308
-#define PERCENT_PARAM 309
-#define PERCENT_UNION 310
+#define BRACED_PREDICATE 296
+#define BRACKETED_ID 297
+#define CHAR 298
+#define EPILOGUE 299
+#define EQUAL 300
+#define ID 301
+#define ID_COLON 302
+#define PERCENT_PERCENT 303
+#define PIPE 304
+#define PROLOGUE 305
+#define SEMICOLON 306
+#define TAG 307
+#define TAG_ANY 308
+#define TAG_NONE 309
+#define PERCENT_PARAM 310
+#define PERCENT_UNION 311
 
 
 
 
 
 
@@ -291,7 +295,7 @@ static char const *char_name (char);
 typedef union YYSTYPE
 {
 /* Line 277 of yacc.c  */
 typedef union YYSTYPE
 {
 /* Line 277 of yacc.c  */
-#line 87 "src/parse-gram.y"
+#line 88 "src/parse-gram.y"
 
   assoc assoc;
   char *code;
 
   assoc assoc;
   char *code;
@@ -304,13 +308,13 @@ typedef union YYSTYPE
   unsigned char character;
 
 /* Line 277 of yacc.c  */
   unsigned char character;
 
 /* Line 277 of yacc.c  */
-#line 225 "src/parse-gram.y"
+#line 226 "src/parse-gram.y"
 
   param_type param;
 
 
 /* Line 277 of yacc.c  */
 
   param_type param;
 
 
 /* Line 277 of yacc.c  */
-#line 314 "src/parse-gram.c"
+#line 318 "src/parse-gram.c"
 } YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
 } YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
@@ -334,10 +338,10 @@ typedef struct YYLTYPE
 /* Copy the second part of user declarations.  */
 
 /* Line 327 of yacc.c  */
 /* Copy the second part of user declarations.  */
 
 /* Line 327 of yacc.c  */
-#line 338 "src/parse-gram.c"
+#line 342 "src/parse-gram.c"
 /* Unqualified %code blocks.  */
 /* Line 328 of yacc.c  */
 /* Unqualified %code blocks.  */
 /* Line 328 of yacc.c  */
-#line 55 "src/parse-gram.y"
+#line 56 "src/parse-gram.y"
 
   static int current_prec = 0;
   static location current_lhs_location;
 
   static int current_prec = 0;
   static location current_lhs_location;
@@ -352,7 +356,7 @@ typedef struct YYLTYPE
   #define YYTYPE_UINT8 uint_fast8_t
 
 /* Line 328 of yacc.c  */
   #define YYTYPE_UINT8 uint_fast8_t
 
 /* Line 328 of yacc.c  */
-#line 214 "src/parse-gram.y"
+#line 215 "src/parse-gram.y"
 
   /** Add a lex-param and/or a parse-param.
    *
 
   /** Add a lex-param and/or a parse-param.
    *
@@ -365,7 +369,7 @@ typedef struct YYLTYPE
 
 
 /* Line 328 of yacc.c  */
 
 
 /* Line 328 of yacc.c  */
-#line 369 "src/parse-gram.c"
+#line 373 "src/parse-gram.c"
 
 #ifdef short
 # undef short
 
 #ifdef short
 # undef short
@@ -582,21 +586,21 @@ union yyalloc
 /* YYFINAL -- State number of the termination state.  */
 #define YYFINAL  3
 /* YYLAST -- Last index in YYTABLE.  */
 /* YYFINAL -- State number of the termination state.  */
 #define YYFINAL  3
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   162
+#define YYLAST   163
 
 /* YYNTOKENS -- Number of terminals.  */
 
 /* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  56
+#define YYNTOKENS  57
 /* YYNNTS -- Number of nonterminals.  */
 #define YYNNTS  36
 /* YYNRULES -- Number of rules.  */
 /* YYNNTS -- Number of nonterminals.  */
 #define YYNNTS  36
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  109
+#define YYNRULES  110
 /* YYNSTATES -- Number of states.  */
 /* YYNSTATES -- Number of states.  */
-#define YYNSTATES  148
+#define YYNSTATES  149
 
 /* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
    by yylex, with out-of-bounds checking.  */
 #define YYUNDEFTOK  2
 
 /* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
    by yylex, with out-of-bounds checking.  */
 #define YYUNDEFTOK  2
-#define YYMAXUTOK   310
+#define YYMAXUTOK   311
 
 #define YYTRANSLATE(YYX)                                               \
   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
 
 #define YYTRANSLATE(YYX)                                               \
   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@@ -636,24 +640,25 @@ static const yytype_uint8 yytranslate[] =
       25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
       35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
       45,    46,    47,    48,    49,    50,    51,    52,    53,    54,
       25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
       35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
       45,    46,    47,    48,    49,    50,    51,    52,    53,    54,
-      55
+      55,    56
 };
 
 #if YYDEBUG
   /* YYRLINEYYN -- Source line where rule number YYN was defined.    */
 static const yytype_uint16 yyrline[] =
 {
 };
 
 #if YYDEBUG
   /* YYRLINEYYN -- Source line where rule number YYN was defined.    */
 static const yytype_uint16 yyrline[] =
 {
-       0,   250,   250,   258,   260,   264,   265,   275,   279,   284,
-     285,   290,   295,   296,   297,   298,   299,   304,   313,   314,
-     315,   316,   317,   318,   319,   320,   320,   321,   322,   346,
-     347,   348,   349,   353,   354,   363,   364,   365,   369,   376,
-     383,   387,   391,   398,   413,   414,   418,   430,   430,   435,
-     435,   440,   451,   466,   467,   468,   469,   473,   474,   479,
-     481,   486,   487,   492,   494,   499,   500,   504,   505,   506,
-     507,   512,   517,   522,   528,   534,   545,   546,   555,   556,
-     562,   563,   564,   571,   571,   576,   577,   578,   583,   585,
-     587,   589,   591,   593,   598,   600,   611,   612,   617,   618,
-     619,   628,   648,   650,   659,   664,   665,   670,   677,   679
+       0,   251,   251,   259,   261,   265,   266,   276,   280,   285,
+     286,   291,   296,   297,   298,   299,   300,   305,   314,   315,
+     316,   317,   318,   319,   320,   321,   321,   322,   323,   347,
+     348,   349,   350,   354,   355,   364,   365,   366,   370,   377,
+     384,   388,   392,   399,   414,   415,   419,   431,   431,   436,
+     436,   441,   452,   467,   468,   469,   470,   474,   475,   480,
+     482,   487,   488,   493,   495,   500,   501,   505,   506,   507,
+     508,   513,   518,   523,   529,   535,   546,   547,   556,   557,
+     563,   564,   565,   572,   572,   577,   578,   579,   584,   586,
+     588,   590,   592,   594,   596,   601,   603,   613,   614,   619,
+     620,   621,   630,   650,   652,   661,   666,   667,   672,   679,
+     681
 };
 #endif
 
 };
 #endif
 
@@ -672,10 +677,10 @@ static const char *const yytname[] =
   "\"%name-prefix\"", "\"%no-default-prec\"", "\"%no-lines\"",
   "\"%nondeterministic-parser\"", "\"%output\"", "\"%require\"",
   "\"%skeleton\"", "\"%start\"", "\"%token-table\"", "\"%verbose\"",
   "\"%name-prefix\"", "\"%no-default-prec\"", "\"%no-lines\"",
   "\"%nondeterministic-parser\"", "\"%output\"", "\"%require\"",
   "\"%skeleton\"", "\"%start\"", "\"%token-table\"", "\"%verbose\"",
-  "\"%yacc\"", "\"{...}\"", "\"[identifier]\"", "\"char\"", "\"epilogue\"",
-  "\"=\"", "\"identifier\"", "\"identifier:\"", "\"%%\"", "\"|\"",
-  "\"%{...%}\"", "\";\"", "\"<tag>\"", "\"<*>\"", "\"<>\"", "\"%param\"",
-  "\"%union\"", "$accept", "input", "prologue_declarations",
+  "\"%yacc\"", "\"{...}\"", "\"%?{...}\"", "\"[identifier]\"", "\"char\"",
+  "\"epilogue\"", "\"=\"", "\"identifier\"", "\"identifier:\"", "\"%%\"",
+  "\"|\"", "\"%{...%}\"", "\";\"", "\"<tag>\"", "\"<*>\"", "\"<>\"",
+  "\"%param\"", "\"%union\"", "$accept", "input", "prologue_declarations",
   "prologue_declaration", "$@1", "params", "grammar_declaration",
   "union_name", "symbol_declaration", "$@2", "$@3",
   "precedence_declaration", "precedence_declarator", "tag.opt",
   "prologue_declaration", "$@1", "params", "grammar_declaration",
   "union_name", "symbol_declaration", "$@2", "$@3",
   "precedence_declaration", "precedence_declarator", "tag.opt",
@@ -697,16 +702,16 @@ static const yytype_uint16 yytoknum[] =
      275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
      285,   286,   287,   288,   289,   290,   291,   292,   293,   294,
      295,   296,   297,   298,   299,   300,   301,   302,   303,   304,
      275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
      285,   286,   287,   288,   289,   290,   291,   292,   293,   294,
      295,   296,   297,   298,   299,   300,   301,   302,   303,   304,
-     305,   306,   307,   308,   309,   310
+     305,   306,   307,   308,   309,   310,   311
 };
 # endif
 
 };
 # endif
 
-#define YYPACT_NINF -137
+#define YYPACT_NINF -50
 
 #define yypact_value_is_default(yystate) \
 
 #define yypact_value_is_default(yystate) \
-  ((yystate) == (-137))
+  ((yystate) == (-50))
 
 
-#define YYTABLE_NINF -109
+#define YYTABLE_NINF -110
 
 #define yytable_value_is_error(yytable_value) \
   YYID (0)
 
 #define yytable_value_is_error(yytable_value) \
   YYID (0)
@@ -715,21 +720,21 @@ static const yytype_uint16 yytoknum[] =
      STATE-NUM.    */
 static const yytype_int16 yypact[] =
 {
      STATE-NUM.    */
 static const yytype_int16 yypact[] =
 {
-    -137,    20,   106,  -137,  -137,  -137,    19,    -1,    36,  -137,
-    -137,  -137,  -137,    13,  -137,     0,    79,  -137,    89,    90,
-    -137,    41,  -137,    55,    93,    46,  -137,  -137,  -137,    47,
-      94,    95,    35,  -137,  -137,  -137,    16,  -137,  -137,  -137,
-      54,  -137,  -137,  -137,  -137,    49,    33,    33,    35,    12,
-      12,  -137,    61,  -137,  -137,  -137,    29,  -137,  -137,  -137,
-    -137,   100,  -137,  -137,  -137,   101,  -137,   103,  -137,  -137,
-    -137,  -137,  -137,  -137,  -137,  -137,    57,  -137,    58,     1,
-    -137,  -137,    68,    80,  -137,    61,  -137,    35,  -137,  -137,
-      33,    56,    33,    35,  -137,  -137,  -137,  -137,    12,  -137,
-    -137,    12,  -137,  -137,  -137,  -137,  -137,  -137,  -137,  -137,
-    -137,    78,  -137,  -137,  -137,  -137,  -137,    82,  -137,    35,
-    -137,   142,  -137,   144,  -137,  -137,  -137,  -137,  -137,  -137,
-    -137,  -137,  -137,    18,    27,  -137,  -137,    35,   145,    97,
-      68,    68,    27,  -137,  -137,  -137,  -137,  -137
+     -50,     4,   107,   -50,   -50,   -50,   -20,     3,    11,   -50,
+     -50,   -50,   -50,    14,   -50,    12,    68,   -50,    72,    73,
+     -50,     0,   -50,    45,    86,     2,   -50,   -50,   -50,    17,
+      95,    96,    32,   -50,   -50,   -50,    16,   -50,   -50,   -50,
+      54,   -50,   -50,   -50,   -50,    49,    -2,    -2,    32,    27,
+      27,   -50,    63,   -50,   -50,   -50,    37,   -50,   -50,   -50,
+     -50,   101,   -50,   -50,   -50,   103,   -50,   104,   -50,   -50,
+     -50,   -50,   -50,   -50,   -50,   -50,    57,   -50,    58,     1,
+     -50,   -50,    79,    70,   -50,    63,   -50,    32,   -50,   -50,
+      -2,    64,    -2,    32,   -50,   -50,   -50,   -50,    27,   -50,
+     -50,    27,   -50,   -50,   -50,   -50,   -50,   -50,   -50,   -50,
+     -50,    78,   -50,   -50,   -50,   -50,   -50,    83,   -50,    32,
+     -50,   143,   -50,   145,   -50,   -50,   -50,   -50,   -50,   -50,
+     -50,   -50,   -50,    43,    50,   -50,   -50,    32,   146,    97,
+      79,   -50,    79,    50,   -50,   -50,   -50,   -50,   -50
 };
 
   /* YYDEFACT[S] -- default reduction number in state S.  Performed when
 };
 
   /* YYDEFACT[S] -- default reduction number in state S.  Performed when
@@ -742,25 +747,25 @@ static const yytype_uint8 yydefact[] =
        7,     0,    16,     0,     0,     0,    41,    21,    22,     0,
        0,     0,     0,    29,    30,    31,     0,     6,    32,    25,
       44,     4,     5,    36,    35,    57,     0,     0,     0,     0,
        7,     0,    16,     0,     0,     0,    41,    21,    22,     0,
        0,     0,     0,    29,    30,    31,     0,     6,    32,    25,
       44,     4,     5,    36,    35,    57,     0,     0,     0,     0,
-       0,   101,     0,    42,    97,    96,    98,    10,    12,    13,
+       0,   102,     0,    42,    98,    97,    99,    10,    12,    13,
       14,     0,    17,    18,    19,     0,    23,     0,    27,    28,
       14,     0,    17,    18,    19,     0,    23,     0,    27,    28,
-     107,   103,   102,   105,    37,   106,     0,   104,     0,     0,
-      78,    80,    94,     0,    45,     0,    58,     0,    71,    76,
+     108,   104,   103,   106,    37,   107,     0,   105,     0,     0,
+      78,    80,    95,     0,    45,     0,    58,     0,    71,    76,
       50,    72,    48,    51,    63,    68,    69,    70,    38,    65,
       50,    72,    48,    51,    63,    68,    69,    70,    38,    65,
-      67,    39,    43,   100,    99,     8,    15,    20,    24,    82,
-      81,     0,    79,     2,    95,    83,    34,    26,    46,    52,
-      59,    61,    77,    73,    74,    64,    66,   109,    88,    33,
+      67,    39,    43,   101,   100,     8,    15,    20,    24,    82,
+      81,     0,    79,     2,    96,    83,    34,    26,    46,    52,
+      59,    61,    77,    73,    74,    64,    66,   110,    88,    33,
       60,    62,    75,    84,    85,    88,    87,     0,     0,     0,
       60,    62,    75,    84,    85,    88,    87,     0,     0,     0,
-      94,    94,    86,    91,    92,    93,    90,    89
+      95,    91,    95,    86,    92,    93,    94,    90,    89
 };
 
   /* YYPGOTO[NTERM-NUM].    */
 static const yytype_int16 yypgoto[] =
 {
 };
 
   /* YYPGOTO[NTERM-NUM].    */
 static const yytype_int16 yypgoto[] =
 {
-    -137,  -137,  -137,  -137,  -137,  -137,   148,  -137,  -137,  -137,
-    -137,  -137,  -137,  -137,  -137,    32,  -137,   102,    -9,    -4,
-     107,  -137,    83,  -137,  -137,  -137,    22,  -136,  -137,  -137,
-     -12,   -11,  -137,   -32,   -40,  -137
+     -50,   -50,   -50,   -50,   -50,   -50,   149,   -50,   -50,   -50,
+     -50,   -50,   -50,   -50,   -50,    33,   -50,   106,   -42,    -4,
+     112,   -50,    74,   -50,   -50,   -50,    19,   -45,   -50,   -50,
+     -16,    -8,   -50,   -32,   -49,   -50
 };
 
   /* YYDEFGOTO[NTERM-NUM].    */
 };
 
   /* YYDEFGOTO[NTERM-NUM].    */
@@ -777,81 +782,82 @@ static const yytype_int16 yydefgoto[] =
      number is the opposite.  If YYTABLE_NINF, syntax error.    */
 static const yytype_int16 yytable[] =
 {
      number is the opposite.  If YYTABLE_NINF, syntax error.    */
 static const yytype_int16 yytable[] =
 {
-      74,  -108,    76,    54,   146,   147,     4,     5,     6,     7,
-       8,     9,    10,    11,    12,    70,    94,    76,    13,    14,
-       3,     4,     5,     6,     7,     8,     9,    10,    11,    12,
-      70,    26,   103,    13,    14,    91,    91,    32,    70,    49,
-     102,   137,   138,   139,    60,    55,    26,    77,   111,    64,
-      66,   124,    32,    51,    71,   121,    40,    72,    52,    70,
-     123,   125,    77,    95,    96,    97,   135,   140,   136,    71,
-      48,    40,    72,   118,   104,    71,    50,    71,    72,    91,
-      72,    91,    57,   132,    88,    61,   122,   121,   122,   126,
-      65,    67,   126,    58,    59,    62,    63,    68,    69,    84,
-      86,    51,   141,   106,   107,   143,   108,   109,   110,   114,
-     141,     4,     5,     6,     7,     8,     9,    10,    11,    12,
-     116,   127,   129,    13,    14,    15,    16,    17,    18,    19,
-      20,    21,    22,    23,    24,    25,    26,    27,    28,    29,
-      30,    31,    32,    33,    34,    35,   131,    70,   145,   144,
-      42,   130,   101,    36,    92,    37,    38,   142,     0,     0,
-      39,    40,   112
+      74,  -109,    76,    60,     3,    64,     4,     5,     6,     7,
+       8,     9,    10,    11,    12,    54,    94,    76,    13,    14,
+      66,     4,     5,     6,     7,     8,     9,    10,    11,    12,
+      70,    26,    48,    13,    14,    70,   102,    32,    91,    91,
+     103,    71,   124,    49,    72,    61,    26,    65,    77,   111,
+      88,    50,    32,    70,    51,   121,   126,    40,    55,   126,
+      52,   125,    67,    77,   137,   138,   139,    70,   123,   118,
+      71,    57,    40,    72,   132,    71,    58,    59,    72,    95,
+      96,    97,    91,   104,    91,    62,   122,   121,   122,    63,
+     140,   141,   135,    71,   136,   147,    72,   148,    68,    69,
+      84,    86,   142,    51,   106,   144,   107,   108,   109,   110,
+     116,   142,     4,     5,     6,     7,     8,     9,    10,    11,
+      12,   114,   127,   129,    13,    14,    15,    16,    17,    18,
+      19,    20,    21,    22,    23,    24,    25,    26,    27,    28,
+      29,    30,    31,    32,    33,    34,    35,   131,    70,   146,
+     145,    42,   130,   112,   143,    36,   101,    37,    38,    92,
+       0,     0,    39,    40
 };
 
 static const yytype_int16 yycheck[] =
 {
 };
 
 static const yytype_int16 yycheck[] =
 {
-      32,     0,     1,     3,   140,   141,     5,     6,     7,     8,
+      32,     0,     1,     3,     0,     3,     5,     6,     7,     8,
        9,    10,    11,    12,    13,     3,    48,     1,    17,    18,
        9,    10,    11,    12,    13,     3,    48,     1,    17,    18,
-       0,     5,     6,     7,     8,     9,    10,    11,    12,    13,
-       3,    30,     3,    17,    18,    46,    47,    36,     3,    40,
-      52,    14,    15,    16,     3,    45,    30,    46,    47,     3,
-       3,    91,    36,    40,    42,    87,    55,    45,    45,     3,
-       4,    93,    46,    51,    52,    53,    48,    40,    50,    42,
-      51,    55,    45,    85,    45,    42,    40,    42,    45,    90,
-      45,    92,     3,   123,    51,    44,    90,   119,    92,    98,
-      44,    44,   101,     4,     4,    40,     3,     3,     3,    45,
-      51,    40,   134,     3,     3,   137,     3,    50,    50,    41,
-     142,     5,     6,     7,     8,     9,    10,    11,    12,    13,
-      40,    43,    40,    17,    18,    19,    20,    21,    22,    23,
-      24,    25,    26,    27,    28,    29,    30,    31,    32,    33,
-      34,    35,    36,    37,    38,    39,     4,     3,    51,     4,
-       2,   119,    50,    47,    47,    49,    50,   135,    -1,    -1,
-      54,    55,    79
+       3,     5,     6,     7,     8,     9,    10,    11,    12,    13,
+       3,    30,    52,    17,    18,     3,    52,    36,    46,    47,
+       3,    43,    91,    40,    46,    45,    30,    45,    47,    48,
+      52,    40,    36,     3,    40,    87,    98,    56,    46,   101,
+      46,    93,    45,    47,    14,    15,    16,     3,     4,    85,
+      43,     3,    56,    46,   123,    43,     4,     4,    46,    52,
+      53,    54,    90,    46,    92,    40,    90,   119,    92,     3,
+      40,    41,    49,    43,    51,   140,    46,   142,     3,     3,
+      46,    52,   134,    40,     3,   137,     3,     3,    51,    51,
+      40,   143,     5,     6,     7,     8,     9,    10,    11,    12,
+      13,    42,    44,    40,    17,    18,    19,    20,    21,    22,
+      23,    24,    25,    26,    27,    28,    29,    30,    31,    32,
+      33,    34,    35,    36,    37,    38,    39,     4,     3,    52,
+       4,     2,   119,    79,   135,    48,    50,    50,    51,    47,
+      -1,    -1,    55,    56
 };
 
   /* STOS_[STATE-NUM] -- The (internal number of the) accessing
      symbol of state STATE-NUM.    */
 static const yytype_uint8 yystos[] =
 {
 };
 
   /* STOS_[STATE-NUM] -- The (internal number of the) accessing
      symbol of state STATE-NUM.    */
 static const yytype_uint8 yystos[] =
 {
-       0,    57,    58,     0,     5,     6,     7,     8,     9,    10,
+       0,    58,    59,     0,     5,     6,     7,     8,     9,    10,
       11,    12,    13,    17,    18,    19,    20,    21,    22,    23,
       24,    25,    26,    27,    28,    29,    30,    31,    32,    33,
       11,    12,    13,    17,    18,    19,    20,    21,    22,    23,
       24,    25,    26,    27,    28,    29,    30,    31,    32,    33,
-      34,    35,    36,    37,    38,    39,    47,    49,    50,    54,
-      55,    59,    62,    64,    67,    68,    66,    65,    51,    40,
-      40,    40,    45,    86,     3,    45,    84,     3,     4,     4,
-       3,    44,    40,     3,     3,    44,     3,    44,     3,     3,
-       3,    42,    45,    87,    89,    90,     1,    46,    62,    77,
-      78,    79,    88,    60,    45,    63,    51,    69,    51,    75,
-      76,    87,    76,    72,    89,    51,    52,    53,    73,    74,
-      89,    73,    86,     3,    45,    85,     3,     3,     3,    50,
-      50,    47,    78,    91,    41,    83,    40,    61,    86,    70,
-      71,    89,    75,     4,    90,    89,    74,    43,    80,    40,
-      71,     4,    90,    81,    82,    48,    50,    14,    15,    16,
-      40,    89,    82,    89,     4,    51,    83,    83
+      34,    35,    36,    37,    38,    39,    48,    50,    51,    55,
+      56,    60,    63,    65,    68,    69,    67,    66,    52,    40,
+      40,    40,    46,    87,     3,    46,    85,     3,     4,     4,
+       3,    45,    40,     3,     3,    45,     3,    45,     3,     3,
+       3,    43,    46,    88,    90,    91,     1,    47,    63,    78,
+      79,    80,    89,    61,    46,    64,    52,    70,    52,    76,
+      77,    88,    77,    73,    90,    52,    53,    54,    74,    75,
+      90,    74,    87,     3,    46,    86,     3,     3,     3,    51,
+      51,    48,    79,    92,    42,    84,    40,    62,    87,    71,
+      72,    90,    76,     4,    91,    90,    75,    44,    81,    40,
+      72,     4,    91,    82,    83,    49,    51,    14,    15,    16,
+      40,    41,    90,    83,    90,     4,    52,    84,    84
 };
 
   /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.    */
 static const yytype_uint8 yyr1[] =
 {
 };
 
   /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.    */
 static const yytype_uint8 yyr1[] =
 {
-       0,    56,    57,    58,    58,    59,    59,    59,    59,    59,
-      59,    59,    59,    59,    59,    59,    59,    59,    59,    59,
-      59,    59,    59,    59,    59,    60,    59,    59,    59,    59,
-      59,    59,    59,    61,    61,    62,    62,    62,    62,    62,
-      62,    62,    62,    62,    63,    63,    62,    65,    64,    66,
-      64,    64,    67,    68,    68,    68,    68,    69,    69,    70,
-      70,    71,    71,    72,    72,    73,    73,    74,    74,    74,
-      74,    75,    75,    75,    75,    75,    76,    76,    77,    77,
-      78,    78,    78,    80,    79,    81,    81,    81,    82,    82,
-      82,    82,    82,    82,    83,    83,    84,    84,    85,    85,
-      85,    86,    87,    87,    88,    89,    89,    90,    91,    91
+       0,    57,    58,    59,    59,    60,    60,    60,    60,    60,
+      60,    60,    60,    60,    60,    60,    60,    60,    60,    60,
+      60,    60,    60,    60,    60,    61,    60,    60,    60,    60,
+      60,    60,    60,    62,    62,    63,    63,    63,    63,    63,
+      63,    63,    63,    63,    64,    64,    63,    66,    65,    67,
+      65,    65,    68,    69,    69,    69,    69,    70,    70,    71,
+      71,    72,    72,    73,    73,    74,    74,    75,    75,    75,
+      75,    76,    76,    76,    76,    76,    77,    77,    78,    78,
+      79,    79,    79,    81,    80,    82,    82,    82,    83,    83,
+      83,    83,    83,    83,    83,    84,    84,    85,    85,    86,
+      86,    86,    87,    88,    88,    89,    90,    90,    91,    92,
+      92
 };
 
   /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.    */
 };
 
   /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.    */
@@ -866,8 +872,9 @@ static const yytype_uint8 yyr2[] =
        2,     1,     2,     1,     2,     1,     2,     1,     1,     1,
        1,     1,     1,     2,     2,     3,     1,     2,     1,     2,
        1,     2,     2,     0,     4,     1,     3,     2,     0,     3,
        2,     1,     2,     1,     2,     1,     2,     1,     1,     1,
        1,     1,     1,     2,     2,     3,     1,     2,     1,     2,
        1,     2,     2,     0,     4,     1,     3,     2,     0,     3,
-       3,     3,     3,     3,     0,     1,     1,     1,     0,     1,
-       1,     1,     1,     1,     1,     1,     1,     1,     0,     2
+       3,     2,     3,     3,     3,     0,     1,     1,     1,     0,
+       1,     1,     1,     1,     1,     1,     1,     1,     1,     0,
+       2
 };
 
 
 };
 
 
@@ -1027,106 +1034,106 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp)
             case 3: // "string"
 
 /* Line 729 of yacc.c  */
             case 3: // "string"
 
 /* Line 729 of yacc.c  */
-#line 174 "src/parse-gram.y"
+#line 175 "src/parse-gram.y"
         { fputs (quotearg_style (c_quoting_style, ((*yyvaluep).chars)), stderr); }
 /* Line 729 of yacc.c  */
         { fputs (quotearg_style (c_quoting_style, ((*yyvaluep).chars)), stderr); }
 /* Line 729 of yacc.c  */
-#line 1034 "src/parse-gram.c"
+#line 1041 "src/parse-gram.c"
         break;
 
             case 4: // "integer"
 
 /* Line 729 of yacc.c  */
         break;
 
             case 4: // "integer"
 
 /* Line 729 of yacc.c  */
-#line 187 "src/parse-gram.y"
+#line 188 "src/parse-gram.y"
         { fprintf (stderr, "%d", ((*yyvaluep).integer)); }
 /* Line 729 of yacc.c  */
         { fprintf (stderr, "%d", ((*yyvaluep).integer)); }
 /* Line 729 of yacc.c  */
-#line 1043 "src/parse-gram.c"
+#line 1050 "src/parse-gram.c"
         break;
 
             case 24: // "%<flag>"
 
 /* Line 729 of yacc.c  */
         break;
 
             case 24: // "%<flag>"
 
 /* Line 729 of yacc.c  */
-#line 183 "src/parse-gram.y"
+#line 184 "src/parse-gram.y"
         { fprintf (stderr, "%%%s", ((*yyvaluep).uniqstr)); }
 /* Line 729 of yacc.c  */
         { fprintf (stderr, "%%%s", ((*yyvaluep).uniqstr)); }
 /* Line 729 of yacc.c  */
-#line 1052 "src/parse-gram.c"
+#line 1059 "src/parse-gram.c"
         break;
 
             case 40: // "{...}"
 
 /* Line 729 of yacc.c  */
         break;
 
             case 40: // "{...}"
 
 /* Line 729 of yacc.c  */
-#line 176 "src/parse-gram.y"
+#line 177 "src/parse-gram.y"
         { fprintf (stderr, "{\n%s\n}", ((*yyvaluep).code)); }
 /* Line 729 of yacc.c  */
         { fprintf (stderr, "{\n%s\n}", ((*yyvaluep).code)); }
 /* Line 729 of yacc.c  */
-#line 1061 "src/parse-gram.c"
+#line 1068 "src/parse-gram.c"
         break;
 
         break;
 
-            case 41: // "[identifier]"
+            case 42: // "[identifier]"
 
 /* Line 729 of yacc.c  */
 
 /* Line 729 of yacc.c  */
-#line 181 "src/parse-gram.y"
+#line 182 "src/parse-gram.y"
         { fprintf (stderr, "[%s]", ((*yyvaluep).uniqstr)); }
 /* Line 729 of yacc.c  */
         { fprintf (stderr, "[%s]", ((*yyvaluep).uniqstr)); }
 /* Line 729 of yacc.c  */
-#line 1070 "src/parse-gram.c"
+#line 1077 "src/parse-gram.c"
         break;
 
         break;
 
-            case 42: // "char"
+            case 43: // "char"
 
 /* Line 729 of yacc.c  */
 
 /* Line 729 of yacc.c  */
-#line 168 "src/parse-gram.y"
+#line 169 "src/parse-gram.y"
         { fputs (char_name (((*yyvaluep).character)), stderr); }
 /* Line 729 of yacc.c  */
         { fputs (char_name (((*yyvaluep).character)), stderr); }
 /* Line 729 of yacc.c  */
-#line 1079 "src/parse-gram.c"
+#line 1086 "src/parse-gram.c"
         break;
 
         break;
 
-            case 43: // "epilogue"
+            case 44: // "epilogue"
 
 /* Line 729 of yacc.c  */
 
 /* Line 729 of yacc.c  */
-#line 176 "src/parse-gram.y"
+#line 177 "src/parse-gram.y"
         { fprintf (stderr, "{\n%s\n}", ((*yyvaluep).chars)); }
 /* Line 729 of yacc.c  */
         { fprintf (stderr, "{\n%s\n}", ((*yyvaluep).chars)); }
 /* Line 729 of yacc.c  */
-#line 1088 "src/parse-gram.c"
+#line 1095 "src/parse-gram.c"
         break;
 
         break;
 
-            case 45: // "identifier"
+            case 46: // "identifier"
 
 /* Line 729 of yacc.c  */
 
 /* Line 729 of yacc.c  */
-#line 180 "src/parse-gram.y"
+#line 181 "src/parse-gram.y"
         { fputs (((*yyvaluep).uniqstr), stderr); }
 /* Line 729 of yacc.c  */
         { fputs (((*yyvaluep).uniqstr), stderr); }
 /* Line 729 of yacc.c  */
-#line 1097 "src/parse-gram.c"
+#line 1104 "src/parse-gram.c"
         break;
 
         break;
 
-            case 46: // "identifier:"
+            case 47: // "identifier:"
 
 /* Line 729 of yacc.c  */
 
 /* Line 729 of yacc.c  */
-#line 182 "src/parse-gram.y"
+#line 183 "src/parse-gram.y"
         { fprintf (stderr, "%s:", ((*yyvaluep).uniqstr)); }
 /* Line 729 of yacc.c  */
         { fprintf (stderr, "%s:", ((*yyvaluep).uniqstr)); }
 /* Line 729 of yacc.c  */
-#line 1106 "src/parse-gram.c"
+#line 1113 "src/parse-gram.c"
         break;
 
         break;
 
-            case 49: // "%{...%}"
+            case 50: // "%{...%}"
 
 /* Line 729 of yacc.c  */
 
 /* Line 729 of yacc.c  */
-#line 176 "src/parse-gram.y"
+#line 177 "src/parse-gram.y"
         { fprintf (stderr, "{\n%s\n}", ((*yyvaluep).chars)); }
 /* Line 729 of yacc.c  */
         { fprintf (stderr, "{\n%s\n}", ((*yyvaluep).chars)); }
 /* Line 729 of yacc.c  */
-#line 1115 "src/parse-gram.c"
+#line 1122 "src/parse-gram.c"
         break;
 
         break;
 
-            case 51: // "<tag>"
+            case 52: // "<tag>"
 
 /* Line 729 of yacc.c  */
 
 /* Line 729 of yacc.c  */
-#line 184 "src/parse-gram.y"
+#line 185 "src/parse-gram.y"
         { fprintf (stderr, "<%s>", ((*yyvaluep).uniqstr)); }
 /* Line 729 of yacc.c  */
         { fprintf (stderr, "<%s>", ((*yyvaluep).uniqstr)); }
 /* Line 729 of yacc.c  */
-#line 1124 "src/parse-gram.c"
+#line 1131 "src/parse-gram.c"
         break;
 
         break;
 
-            case 54: // "%param"
+            case 55: // "%param"
 
 /* Line 729 of yacc.c  */
 
 /* Line 729 of yacc.c  */
-#line 230 "src/parse-gram.y"
+#line 231 "src/parse-gram.y"
         {
   switch (((*yyvaluep).param))
     {
         {
   switch (((*yyvaluep).param))
     {
@@ -1140,79 +1147,79 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp)
     }
 }
 /* Line 729 of yacc.c  */
     }
 }
 /* Line 729 of yacc.c  */
-#line 1144 "src/parse-gram.c"
+#line 1151 "src/parse-gram.c"
         break;
 
         break;
 
-            case 71: // symbol.prec
+            case 72: // symbol.prec
 
 /* Line 729 of yacc.c  */
 
 /* Line 729 of yacc.c  */
-#line 190 "src/parse-gram.y"
+#line 191 "src/parse-gram.y"
         { fprintf (stderr, "%s", ((*yyvaluep).symbol)->tag); }
 /* Line 729 of yacc.c  */
         { fprintf (stderr, "%s", ((*yyvaluep).symbol)->tag); }
 /* Line 729 of yacc.c  */
-#line 1153 "src/parse-gram.c"
+#line 1160 "src/parse-gram.c"
         break;
 
         break;
 
-            case 84: // variable
+            case 85: // variable
 
 /* Line 729 of yacc.c  */
 
 /* Line 729 of yacc.c  */
-#line 180 "src/parse-gram.y"
+#line 181 "src/parse-gram.y"
         { fputs (((*yyvaluep).uniqstr), stderr); }
 /* Line 729 of yacc.c  */
         { fputs (((*yyvaluep).uniqstr), stderr); }
 /* Line 729 of yacc.c  */
-#line 1162 "src/parse-gram.c"
+#line 1169 "src/parse-gram.c"
         break;
 
         break;
 
-            case 85: // content.opt
+            case 86: // content.opt
 
 /* Line 729 of yacc.c  */
 
 /* Line 729 of yacc.c  */
-#line 176 "src/parse-gram.y"
+#line 177 "src/parse-gram.y"
         { fprintf (stderr, "{\n%s\n}", ((*yyvaluep).chars)); }
 /* Line 729 of yacc.c  */
         { fprintf (stderr, "{\n%s\n}", ((*yyvaluep).chars)); }
 /* Line 729 of yacc.c  */
-#line 1171 "src/parse-gram.c"
+#line 1178 "src/parse-gram.c"
         break;
 
         break;
 
-            case 86: // braceless
+            case 87: // braceless
 
 /* Line 729 of yacc.c  */
 
 /* Line 729 of yacc.c  */
-#line 176 "src/parse-gram.y"
+#line 177 "src/parse-gram.y"
         { fprintf (stderr, "{\n%s\n}", ((*yyvaluep).chars)); }
 /* Line 729 of yacc.c  */
         { fprintf (stderr, "{\n%s\n}", ((*yyvaluep).chars)); }
 /* Line 729 of yacc.c  */
-#line 1180 "src/parse-gram.c"
+#line 1187 "src/parse-gram.c"
         break;
 
         break;
 
-            case 87: // id
+            case 88: // id
 
 /* Line 729 of yacc.c  */
 
 /* Line 729 of yacc.c  */
-#line 190 "src/parse-gram.y"
+#line 191 "src/parse-gram.y"
         { fprintf (stderr, "%s", ((*yyvaluep).symbol)->tag); }
 /* Line 729 of yacc.c  */
         { fprintf (stderr, "%s", ((*yyvaluep).symbol)->tag); }
 /* Line 729 of yacc.c  */
-#line 1189 "src/parse-gram.c"
+#line 1196 "src/parse-gram.c"
         break;
 
         break;
 
-            case 88: // id_colon
+            case 89: // id_colon
 
 /* Line 729 of yacc.c  */
 
 /* Line 729 of yacc.c  */
-#line 191 "src/parse-gram.y"
+#line 192 "src/parse-gram.y"
         { fprintf (stderr, "%s:", ((*yyvaluep).symbol)->tag); }
 /* Line 729 of yacc.c  */
         { fprintf (stderr, "%s:", ((*yyvaluep).symbol)->tag); }
 /* Line 729 of yacc.c  */
-#line 1198 "src/parse-gram.c"
+#line 1205 "src/parse-gram.c"
         break;
 
         break;
 
-            case 89: // symbol
+            case 90: // symbol
 
 /* Line 729 of yacc.c  */
 
 /* Line 729 of yacc.c  */
-#line 190 "src/parse-gram.y"
+#line 191 "src/parse-gram.y"
         { fprintf (stderr, "%s", ((*yyvaluep).symbol)->tag); }
 /* Line 729 of yacc.c  */
         { fprintf (stderr, "%s", ((*yyvaluep).symbol)->tag); }
 /* Line 729 of yacc.c  */
-#line 1207 "src/parse-gram.c"
+#line 1214 "src/parse-gram.c"
         break;
 
         break;
 
-            case 90: // string_as_id
+            case 91: // string_as_id
 
 /* Line 729 of yacc.c  */
 
 /* Line 729 of yacc.c  */
-#line 190 "src/parse-gram.y"
+#line 191 "src/parse-gram.y"
         { fprintf (stderr, "%s", ((*yyvaluep).symbol)->tag); }
 /* Line 729 of yacc.c  */
         { fprintf (stderr, "%s", ((*yyvaluep).symbol)->tag); }
 /* Line 729 of yacc.c  */
-#line 1216 "src/parse-gram.c"
+#line 1223 "src/parse-gram.c"
         break;
 
       default:
         break;
 
       default:
@@ -1743,7 +1750,7 @@ YYLTYPE yylloc;
 
 /* User initialization code.  */
 /* Line 1214 of yacc.c  */
 
 /* User initialization code.  */
 /* Line 1214 of yacc.c  */
-#line 79 "src/parse-gram.y"
+#line 80 "src/parse-gram.y"
 {
   /* Bison's grammar can initial empty locations, hence a default
      location is needed. */
 {
   /* Bison's grammar can initial empty locations, hence a default
      location is needed. */
@@ -1751,7 +1758,7 @@ YYLTYPE yylloc;
   boundary_set (&yylloc.end, current_file, 1, 1);
 }
 /* Line 1214 of yacc.c  */
   boundary_set (&yylloc.end, current_file, 1, 1);
 }
 /* Line 1214 of yacc.c  */
-#line 1755 "src/parse-gram.c"
+#line 1762 "src/parse-gram.c"
   yylsp[0] = yylloc;
 
   goto yysetstate;
   yylsp[0] = yylloc;
 
   goto yysetstate;
@@ -1938,7 +1945,7 @@ yyreduce:
     {
         case 6:
 /* Line 1427 of yacc.c  */
     {
         case 6:
 /* Line 1427 of yacc.c  */
-#line 266 "src/parse-gram.y"
+#line 267 "src/parse-gram.y"
     {
       code_props plain_code;
       code_props_plain_init (&plain_code, (yyvsp[0].chars), (yylsp[0]));
     {
       code_props plain_code;
       code_props_plain_init (&plain_code, (yyvsp[0].chars), (yylsp[0]));
@@ -1949,106 +1956,106 @@ yyreduce:
       code_scanner_last_string_free ();
     }
 /* Line 1427 of yacc.c  */
       code_scanner_last_string_free ();
     }
 /* Line 1427 of yacc.c  */
-#line 1953 "src/parse-gram.c"
+#line 1960 "src/parse-gram.c"
     break;
 
   case 7:
 /* Line 1427 of yacc.c  */
     break;
 
   case 7:
 /* Line 1427 of yacc.c  */
-#line 276 "src/parse-gram.y"
+#line 277 "src/parse-gram.y"
     {
       muscle_percent_define_ensure ((yyvsp[0].uniqstr), (yylsp[0]), true);
     }
 /* Line 1427 of yacc.c  */
     {
       muscle_percent_define_ensure ((yyvsp[0].uniqstr), (yylsp[0]), true);
     }
 /* Line 1427 of yacc.c  */
-#line 1963 "src/parse-gram.c"
+#line 1970 "src/parse-gram.c"
     break;
 
   case 8:
 /* Line 1427 of yacc.c  */
     break;
 
   case 8:
 /* Line 1427 of yacc.c  */
-#line 280 "src/parse-gram.y"
+#line 281 "src/parse-gram.y"
     {
       muscle_percent_define_insert ((yyvsp[-1].uniqstr), (yylsp[-1]), (yyvsp[0].chars),
                                     MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE);
     }
 /* Line 1427 of yacc.c  */
     {
       muscle_percent_define_insert ((yyvsp[-1].uniqstr), (yylsp[-1]), (yyvsp[0].chars),
                                     MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE);
     }
 /* Line 1427 of yacc.c  */
-#line 1974 "src/parse-gram.c"
+#line 1981 "src/parse-gram.c"
     break;
 
   case 9:
 /* Line 1427 of yacc.c  */
     break;
 
   case 9:
 /* Line 1427 of yacc.c  */
-#line 284 "src/parse-gram.y"
+#line 285 "src/parse-gram.y"
     { defines_flag = true; }
 /* Line 1427 of yacc.c  */
     { defines_flag = true; }
 /* Line 1427 of yacc.c  */
-#line 1982 "src/parse-gram.c"
+#line 1989 "src/parse-gram.c"
     break;
 
   case 10:
 /* Line 1427 of yacc.c  */
     break;
 
   case 10:
 /* Line 1427 of yacc.c  */
-#line 286 "src/parse-gram.y"
+#line 287 "src/parse-gram.y"
     {
       defines_flag = true;
       spec_defines_file = xstrdup ((yyvsp[0].chars));
     }
 /* Line 1427 of yacc.c  */
     {
       defines_flag = true;
       spec_defines_file = xstrdup ((yyvsp[0].chars));
     }
 /* Line 1427 of yacc.c  */
-#line 1993 "src/parse-gram.c"
+#line 2000 "src/parse-gram.c"
     break;
 
   case 11:
 /* Line 1427 of yacc.c  */
     break;
 
   case 11:
 /* Line 1427 of yacc.c  */
-#line 291 "src/parse-gram.y"
+#line 292 "src/parse-gram.y"
     {
       muscle_percent_define_insert ("parse.error", (yylsp[0]), "verbose",
                                     MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE);
     }
 /* Line 1427 of yacc.c  */
     {
       muscle_percent_define_insert ("parse.error", (yylsp[0]), "verbose",
                                     MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE);
     }
 /* Line 1427 of yacc.c  */
-#line 2004 "src/parse-gram.c"
+#line 2011 "src/parse-gram.c"
     break;
 
   case 12:
 /* Line 1427 of yacc.c  */
     break;
 
   case 12:
 /* Line 1427 of yacc.c  */
-#line 295 "src/parse-gram.y"
+#line 296 "src/parse-gram.y"
     { expected_sr_conflicts = (yyvsp[0].integer); }
 /* Line 1427 of yacc.c  */
     { expected_sr_conflicts = (yyvsp[0].integer); }
 /* Line 1427 of yacc.c  */
-#line 2012 "src/parse-gram.c"
+#line 2019 "src/parse-gram.c"
     break;
 
   case 13:
 /* Line 1427 of yacc.c  */
     break;
 
   case 13:
 /* Line 1427 of yacc.c  */
-#line 296 "src/parse-gram.y"
+#line 297 "src/parse-gram.y"
     { expected_rr_conflicts = (yyvsp[0].integer); }
 /* Line 1427 of yacc.c  */
     { expected_rr_conflicts = (yyvsp[0].integer); }
 /* Line 1427 of yacc.c  */
-#line 2020 "src/parse-gram.c"
+#line 2027 "src/parse-gram.c"
     break;
 
   case 14:
 /* Line 1427 of yacc.c  */
     break;
 
   case 14:
 /* Line 1427 of yacc.c  */
-#line 297 "src/parse-gram.y"
+#line 298 "src/parse-gram.y"
     { spec_file_prefix = (yyvsp[0].chars); }
 /* Line 1427 of yacc.c  */
     { spec_file_prefix = (yyvsp[0].chars); }
 /* Line 1427 of yacc.c  */
-#line 2028 "src/parse-gram.c"
+#line 2035 "src/parse-gram.c"
     break;
 
   case 15:
 /* Line 1427 of yacc.c  */
     break;
 
   case 15:
 /* Line 1427 of yacc.c  */
-#line 298 "src/parse-gram.y"
+#line 299 "src/parse-gram.y"
     { spec_file_prefix = (yyvsp[0].chars); }
 /* Line 1427 of yacc.c  */
     { spec_file_prefix = (yyvsp[0].chars); }
 /* Line 1427 of yacc.c  */
-#line 2036 "src/parse-gram.c"
+#line 2043 "src/parse-gram.c"
     break;
 
   case 16:
 /* Line 1427 of yacc.c  */
     break;
 
   case 16:
 /* Line 1427 of yacc.c  */
-#line 300 "src/parse-gram.y"
+#line 301 "src/parse-gram.y"
     {
       nondeterministic_parser = true;
       glr_parser = true;
     }
 /* Line 1427 of yacc.c  */
     {
       nondeterministic_parser = true;
       glr_parser = true;
     }
 /* Line 1427 of yacc.c  */
-#line 2047 "src/parse-gram.c"
+#line 2054 "src/parse-gram.c"
     break;
 
   case 17:
 /* Line 1427 of yacc.c  */
     break;
 
   case 17:
 /* Line 1427 of yacc.c  */
-#line 305 "src/parse-gram.y"
+#line 306 "src/parse-gram.y"
     {
       code_props action;
       code_props_symbol_action_init (&action, (yyvsp[0].code), (yylsp[0]));
     {
       code_props action;
       code_props_symbol_action_init (&action, (yyvsp[0].code), (yylsp[0]));
@@ -2058,92 +2065,92 @@ yyreduce:
       code_scanner_last_string_free ();
     }
 /* Line 1427 of yacc.c  */
       code_scanner_last_string_free ();
     }
 /* Line 1427 of yacc.c  */
-#line 2062 "src/parse-gram.c"
+#line 2069 "src/parse-gram.c"
     break;
 
   case 18:
 /* Line 1427 of yacc.c  */
     break;
 
   case 18:
 /* Line 1427 of yacc.c  */
-#line 313 "src/parse-gram.y"
+#line 314 "src/parse-gram.y"
     { language_argmatch ((yyvsp[0].chars), grammar_prio, (yylsp[-1])); }
 /* Line 1427 of yacc.c  */
     { language_argmatch ((yyvsp[0].chars), grammar_prio, (yylsp[-1])); }
 /* Line 1427 of yacc.c  */
-#line 2070 "src/parse-gram.c"
+#line 2077 "src/parse-gram.c"
     break;
 
   case 19:
 /* Line 1427 of yacc.c  */
     break;
 
   case 19:
 /* Line 1427 of yacc.c  */
-#line 314 "src/parse-gram.y"
+#line 315 "src/parse-gram.y"
     { spec_name_prefix = (yyvsp[0].chars); }
 /* Line 1427 of yacc.c  */
     { spec_name_prefix = (yyvsp[0].chars); }
 /* Line 1427 of yacc.c  */
-#line 2078 "src/parse-gram.c"
+#line 2085 "src/parse-gram.c"
     break;
 
   case 20:
 /* Line 1427 of yacc.c  */
     break;
 
   case 20:
 /* Line 1427 of yacc.c  */
-#line 315 "src/parse-gram.y"
+#line 316 "src/parse-gram.y"
     { spec_name_prefix = (yyvsp[0].chars); }
 /* Line 1427 of yacc.c  */
     { spec_name_prefix = (yyvsp[0].chars); }
 /* Line 1427 of yacc.c  */
-#line 2086 "src/parse-gram.c"
+#line 2093 "src/parse-gram.c"
     break;
 
   case 21:
 /* Line 1427 of yacc.c  */
     break;
 
   case 21:
 /* Line 1427 of yacc.c  */
-#line 316 "src/parse-gram.y"
+#line 317 "src/parse-gram.y"
     { no_lines_flag = true; }
 /* Line 1427 of yacc.c  */
     { no_lines_flag = true; }
 /* Line 1427 of yacc.c  */
-#line 2094 "src/parse-gram.c"
+#line 2101 "src/parse-gram.c"
     break;
 
   case 22:
 /* Line 1427 of yacc.c  */
     break;
 
   case 22:
 /* Line 1427 of yacc.c  */
-#line 317 "src/parse-gram.y"
+#line 318 "src/parse-gram.y"
     { nondeterministic_parser = true; }
 /* Line 1427 of yacc.c  */
     { nondeterministic_parser = true; }
 /* Line 1427 of yacc.c  */
-#line 2102 "src/parse-gram.c"
+#line 2109 "src/parse-gram.c"
     break;
 
   case 23:
 /* Line 1427 of yacc.c  */
     break;
 
   case 23:
 /* Line 1427 of yacc.c  */
-#line 318 "src/parse-gram.y"
+#line 319 "src/parse-gram.y"
     { spec_outfile = (yyvsp[0].chars); }
 /* Line 1427 of yacc.c  */
     { spec_outfile = (yyvsp[0].chars); }
 /* Line 1427 of yacc.c  */
-#line 2110 "src/parse-gram.c"
+#line 2117 "src/parse-gram.c"
     break;
 
   case 24:
 /* Line 1427 of yacc.c  */
     break;
 
   case 24:
 /* Line 1427 of yacc.c  */
-#line 319 "src/parse-gram.y"
+#line 320 "src/parse-gram.y"
     { spec_outfile = (yyvsp[0].chars); }
 /* Line 1427 of yacc.c  */
     { spec_outfile = (yyvsp[0].chars); }
 /* Line 1427 of yacc.c  */
-#line 2118 "src/parse-gram.c"
+#line 2125 "src/parse-gram.c"
     break;
 
   case 25:
 /* Line 1427 of yacc.c  */
     break;
 
   case 25:
 /* Line 1427 of yacc.c  */
-#line 320 "src/parse-gram.y"
+#line 321 "src/parse-gram.y"
     { current_param = (yyvsp[0].param); }
 /* Line 1427 of yacc.c  */
     { current_param = (yyvsp[0].param); }
 /* Line 1427 of yacc.c  */
-#line 2126 "src/parse-gram.c"
+#line 2133 "src/parse-gram.c"
     break;
 
   case 26:
 /* Line 1427 of yacc.c  */
     break;
 
   case 26:
 /* Line 1427 of yacc.c  */
-#line 320 "src/parse-gram.y"
+#line 321 "src/parse-gram.y"
     { current_param = param_none; }
 /* Line 1427 of yacc.c  */
     { current_param = param_none; }
 /* Line 1427 of yacc.c  */
-#line 2134 "src/parse-gram.c"
+#line 2141 "src/parse-gram.c"
     break;
 
   case 27:
 /* Line 1427 of yacc.c  */
     break;
 
   case 27:
 /* Line 1427 of yacc.c  */
-#line 321 "src/parse-gram.y"
+#line 322 "src/parse-gram.y"
     { version_check (&(yylsp[0]), (yyvsp[0].chars)); }
 /* Line 1427 of yacc.c  */
     { version_check (&(yylsp[0]), (yyvsp[0].chars)); }
 /* Line 1427 of yacc.c  */
-#line 2142 "src/parse-gram.c"
+#line 2149 "src/parse-gram.c"
     break;
 
   case 28:
 /* Line 1427 of yacc.c  */
     break;
 
   case 28:
 /* Line 1427 of yacc.c  */
-#line 323 "src/parse-gram.y"
+#line 324 "src/parse-gram.y"
     {
       char const *skeleton_user = (yyvsp[0].chars);
       if (strchr (skeleton_user, '/'))
     {
       char const *skeleton_user = (yyvsp[0].chars);
       if (strchr (skeleton_user, '/'))
@@ -2168,62 +2175,62 @@ yyreduce:
       skeleton_arg (skeleton_user, grammar_prio, (yylsp[-1]));
     }
 /* Line 1427 of yacc.c  */
       skeleton_arg (skeleton_user, grammar_prio, (yylsp[-1]));
     }
 /* Line 1427 of yacc.c  */
-#line 2172 "src/parse-gram.c"
+#line 2179 "src/parse-gram.c"
     break;
 
   case 29:
 /* Line 1427 of yacc.c  */
     break;
 
   case 29:
 /* Line 1427 of yacc.c  */
-#line 346 "src/parse-gram.y"
+#line 347 "src/parse-gram.y"
     { token_table_flag = true; }
 /* Line 1427 of yacc.c  */
     { token_table_flag = true; }
 /* Line 1427 of yacc.c  */
-#line 2180 "src/parse-gram.c"
+#line 2187 "src/parse-gram.c"
     break;
 
   case 30:
 /* Line 1427 of yacc.c  */
     break;
 
   case 30:
 /* Line 1427 of yacc.c  */
-#line 347 "src/parse-gram.y"
+#line 348 "src/parse-gram.y"
     { report_flag |= report_states; }
 /* Line 1427 of yacc.c  */
     { report_flag |= report_states; }
 /* Line 1427 of yacc.c  */
-#line 2188 "src/parse-gram.c"
+#line 2195 "src/parse-gram.c"
     break;
 
   case 31:
 /* Line 1427 of yacc.c  */
     break;
 
   case 31:
 /* Line 1427 of yacc.c  */
-#line 348 "src/parse-gram.y"
+#line 349 "src/parse-gram.y"
     { yacc_flag = true; }
 /* Line 1427 of yacc.c  */
     { yacc_flag = true; }
 /* Line 1427 of yacc.c  */
-#line 2196 "src/parse-gram.c"
+#line 2203 "src/parse-gram.c"
     break;
 
   case 33:
 /* Line 1427 of yacc.c  */
     break;
 
   case 33:
 /* Line 1427 of yacc.c  */
-#line 353 "src/parse-gram.y"
+#line 354 "src/parse-gram.y"
     { add_param (current_param, (yyvsp[0].code), (yylsp[0])); }
 /* Line 1427 of yacc.c  */
     { add_param (current_param, (yyvsp[0].code), (yylsp[0])); }
 /* Line 1427 of yacc.c  */
-#line 2204 "src/parse-gram.c"
+#line 2211 "src/parse-gram.c"
     break;
 
   case 34:
 /* Line 1427 of yacc.c  */
     break;
 
   case 34:
 /* Line 1427 of yacc.c  */
-#line 354 "src/parse-gram.y"
+#line 355 "src/parse-gram.y"
     { add_param (current_param, (yyvsp[0].code), (yylsp[0])); }
 /* Line 1427 of yacc.c  */
     { add_param (current_param, (yyvsp[0].code), (yylsp[0])); }
 /* Line 1427 of yacc.c  */
-#line 2212 "src/parse-gram.c"
+#line 2219 "src/parse-gram.c"
     break;
 
   case 37:
 /* Line 1427 of yacc.c  */
     break;
 
   case 37:
 /* Line 1427 of yacc.c  */
-#line 366 "src/parse-gram.y"
+#line 367 "src/parse-gram.y"
     {
       grammar_start_symbol_set ((yyvsp[0].symbol), (yylsp[0]));
     }
 /* Line 1427 of yacc.c  */
     {
       grammar_start_symbol_set ((yyvsp[0].symbol), (yylsp[0]));
     }
 /* Line 1427 of yacc.c  */
-#line 2222 "src/parse-gram.c"
+#line 2229 "src/parse-gram.c"
     break;
 
   case 38:
 /* Line 1427 of yacc.c  */
     break;
 
   case 38:
 /* Line 1427 of yacc.c  */
-#line 370 "src/parse-gram.y"
+#line 371 "src/parse-gram.y"
     {
       symbol_list *list;
       for (list = (yyvsp[0].list); list; list = list->next)
     {
       symbol_list *list;
       for (list = (yyvsp[0].list); list; list = list->next)
@@ -2231,12 +2238,12 @@ yyreduce:
       symbol_list_free ((yyvsp[0].list));
     }
 /* Line 1427 of yacc.c  */
       symbol_list_free ((yyvsp[0].list));
     }
 /* Line 1427 of yacc.c  */
-#line 2235 "src/parse-gram.c"
+#line 2242 "src/parse-gram.c"
     break;
 
   case 39:
 /* Line 1427 of yacc.c  */
     break;
 
   case 39:
 /* Line 1427 of yacc.c  */
-#line 377 "src/parse-gram.y"
+#line 378 "src/parse-gram.y"
     {
       symbol_list *list;
       for (list = (yyvsp[0].list); list; list = list->next)
     {
       symbol_list *list;
       for (list = (yyvsp[0].list); list; list = list->next)
@@ -2244,32 +2251,32 @@ yyreduce:
       symbol_list_free ((yyvsp[0].list));
     }
 /* Line 1427 of yacc.c  */
       symbol_list_free ((yyvsp[0].list));
     }
 /* Line 1427 of yacc.c  */
-#line 2248 "src/parse-gram.c"
+#line 2255 "src/parse-gram.c"
     break;
 
   case 40:
 /* Line 1427 of yacc.c  */
     break;
 
   case 40:
 /* Line 1427 of yacc.c  */
-#line 384 "src/parse-gram.y"
+#line 385 "src/parse-gram.y"
     {
       default_prec = true;
     }
 /* Line 1427 of yacc.c  */
     {
       default_prec = true;
     }
 /* Line 1427 of yacc.c  */
-#line 2258 "src/parse-gram.c"
+#line 2265 "src/parse-gram.c"
     break;
 
   case 41:
 /* Line 1427 of yacc.c  */
     break;
 
   case 41:
 /* Line 1427 of yacc.c  */
-#line 388 "src/parse-gram.y"
+#line 389 "src/parse-gram.y"
     {
       default_prec = false;
     }
 /* Line 1427 of yacc.c  */
     {
       default_prec = false;
     }
 /* Line 1427 of yacc.c  */
-#line 2268 "src/parse-gram.c"
+#line 2275 "src/parse-gram.c"
     break;
 
   case 42:
 /* Line 1427 of yacc.c  */
     break;
 
   case 42:
 /* Line 1427 of yacc.c  */
-#line 392 "src/parse-gram.y"
+#line 393 "src/parse-gram.y"
     {
       /* Do not invoke muscle_percent_code_grow here since it invokes
          muscle_user_name_list_grow.  */
     {
       /* Do not invoke muscle_percent_code_grow here since it invokes
          muscle_user_name_list_grow.  */
@@ -2277,89 +2284,89 @@ yyreduce:
       code_scanner_last_string_free ();
     }
 /* Line 1427 of yacc.c  */
       code_scanner_last_string_free ();
     }
 /* Line 1427 of yacc.c  */
-#line 2281 "src/parse-gram.c"
+#line 2288 "src/parse-gram.c"
     break;
 
   case 43:
 /* Line 1427 of yacc.c  */
     break;
 
   case 43:
 /* Line 1427 of yacc.c  */
-#line 399 "src/parse-gram.y"
+#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 1427 of yacc.c  */
     {
       muscle_percent_code_grow ((yyvsp[-1].uniqstr), (yylsp[-1]), (yyvsp[0].chars), (yylsp[0]));
       code_scanner_last_string_free ();
     }
 /* Line 1427 of yacc.c  */
-#line 2292 "src/parse-gram.c"
+#line 2299 "src/parse-gram.c"
     break;
 
   case 44:
 /* Line 1427 of yacc.c  */
     break;
 
   case 44:
 /* Line 1427 of yacc.c  */
-#line 413 "src/parse-gram.y"
+#line 414 "src/parse-gram.y"
     {}
 /* Line 1427 of yacc.c  */
     {}
 /* Line 1427 of yacc.c  */
-#line 2300 "src/parse-gram.c"
+#line 2307 "src/parse-gram.c"
     break;
 
   case 45:
 /* Line 1427 of yacc.c  */
     break;
 
   case 45:
 /* Line 1427 of yacc.c  */
-#line 414 "src/parse-gram.y"
+#line 415 "src/parse-gram.y"
     { muscle_code_grow ("union_name", (yyvsp[0].uniqstr), (yylsp[0])); }
 /* Line 1427 of yacc.c  */
     { muscle_code_grow ("union_name", (yyvsp[0].uniqstr), (yylsp[0])); }
 /* Line 1427 of yacc.c  */
-#line 2308 "src/parse-gram.c"
+#line 2315 "src/parse-gram.c"
     break;
 
   case 46:
 /* Line 1427 of yacc.c  */
     break;
 
   case 46:
 /* Line 1427 of yacc.c  */
-#line 419 "src/parse-gram.y"
+#line 420 "src/parse-gram.y"
     {
       union_seen = true;
       muscle_code_grow ("stype", (yyvsp[0].chars), (yylsp[0]));
       code_scanner_last_string_free ();
     }
 /* Line 1427 of yacc.c  */
     {
       union_seen = true;
       muscle_code_grow ("stype", (yyvsp[0].chars), (yylsp[0]));
       code_scanner_last_string_free ();
     }
 /* Line 1427 of yacc.c  */
-#line 2320 "src/parse-gram.c"
+#line 2327 "src/parse-gram.c"
     break;
 
   case 47:
 /* Line 1427 of yacc.c  */
     break;
 
   case 47:
 /* Line 1427 of yacc.c  */
-#line 430 "src/parse-gram.y"
+#line 431 "src/parse-gram.y"
     { current_class = nterm_sym; }
 /* Line 1427 of yacc.c  */
     { current_class = nterm_sym; }
 /* Line 1427 of yacc.c  */
-#line 2328 "src/parse-gram.c"
+#line 2335 "src/parse-gram.c"
     break;
 
   case 48:
 /* Line 1427 of yacc.c  */
     break;
 
   case 48:
 /* Line 1427 of yacc.c  */
-#line 431 "src/parse-gram.y"
+#line 432 "src/parse-gram.y"
     {
       current_class = unknown_sym;
       current_type = NULL;
     }
 /* Line 1427 of yacc.c  */
     {
       current_class = unknown_sym;
       current_type = NULL;
     }
 /* Line 1427 of yacc.c  */
-#line 2339 "src/parse-gram.c"
+#line 2346 "src/parse-gram.c"
     break;
 
   case 49:
 /* Line 1427 of yacc.c  */
     break;
 
   case 49:
 /* Line 1427 of yacc.c  */
-#line 435 "src/parse-gram.y"
+#line 436 "src/parse-gram.y"
     { current_class = token_sym; }
 /* Line 1427 of yacc.c  */
     { current_class = token_sym; }
 /* Line 1427 of yacc.c  */
-#line 2347 "src/parse-gram.c"
+#line 2354 "src/parse-gram.c"
     break;
 
   case 50:
 /* Line 1427 of yacc.c  */
     break;
 
   case 50:
 /* Line 1427 of yacc.c  */
-#line 436 "src/parse-gram.y"
+#line 437 "src/parse-gram.y"
     {
       current_class = unknown_sym;
       current_type = NULL;
     }
 /* Line 1427 of yacc.c  */
     {
       current_class = unknown_sym;
       current_type = NULL;
     }
 /* Line 1427 of yacc.c  */
-#line 2358 "src/parse-gram.c"
+#line 2365 "src/parse-gram.c"
     break;
 
   case 51:
 /* Line 1427 of yacc.c  */
     break;
 
   case 51:
 /* Line 1427 of yacc.c  */
-#line 441 "src/parse-gram.y"
+#line 442 "src/parse-gram.y"
     {
       symbol_list *list;
       tag_seen = true;
     {
       symbol_list *list;
       tag_seen = true;
@@ -2368,12 +2375,12 @@ yyreduce:
       symbol_list_free ((yyvsp[0].list));
     }
 /* Line 1427 of yacc.c  */
       symbol_list_free ((yyvsp[0].list));
     }
 /* Line 1427 of yacc.c  */
-#line 2372 "src/parse-gram.c"
+#line 2379 "src/parse-gram.c"
     break;
 
   case 52:
 /* Line 1427 of yacc.c  */
     break;
 
   case 52:
 /* Line 1427 of yacc.c  */
-#line 452 "src/parse-gram.y"
+#line 453 "src/parse-gram.y"
     {
       symbol_list *list;
       ++current_prec;
     {
       symbol_list *list;
       ++current_prec;
@@ -2386,202 +2393,202 @@ yyreduce:
       current_type = NULL;
     }
 /* Line 1427 of yacc.c  */
       current_type = NULL;
     }
 /* Line 1427 of yacc.c  */
-#line 2390 "src/parse-gram.c"
+#line 2397 "src/parse-gram.c"
     break;
 
   case 53:
 /* Line 1427 of yacc.c  */
     break;
 
   case 53:
 /* Line 1427 of yacc.c  */
-#line 466 "src/parse-gram.y"
+#line 467 "src/parse-gram.y"
     { (yyval.assoc) = left_assoc; }
 /* Line 1427 of yacc.c  */
     { (yyval.assoc) = left_assoc; }
 /* Line 1427 of yacc.c  */
-#line 2398 "src/parse-gram.c"
+#line 2405 "src/parse-gram.c"
     break;
 
   case 54:
 /* Line 1427 of yacc.c  */
     break;
 
   case 54:
 /* Line 1427 of yacc.c  */
-#line 467 "src/parse-gram.y"
+#line 468 "src/parse-gram.y"
     { (yyval.assoc) = right_assoc; }
 /* Line 1427 of yacc.c  */
     { (yyval.assoc) = right_assoc; }
 /* Line 1427 of yacc.c  */
-#line 2406 "src/parse-gram.c"
+#line 2413 "src/parse-gram.c"
     break;
 
   case 55:
 /* Line 1427 of yacc.c  */
     break;
 
   case 55:
 /* Line 1427 of yacc.c  */
-#line 468 "src/parse-gram.y"
+#line 469 "src/parse-gram.y"
     { (yyval.assoc) = non_assoc; }
 /* Line 1427 of yacc.c  */
     { (yyval.assoc) = non_assoc; }
 /* Line 1427 of yacc.c  */
-#line 2414 "src/parse-gram.c"
+#line 2421 "src/parse-gram.c"
     break;
 
   case 56:
 /* Line 1427 of yacc.c  */
     break;
 
   case 56:
 /* Line 1427 of yacc.c  */
-#line 469 "src/parse-gram.y"
+#line 470 "src/parse-gram.y"
     { (yyval.assoc) = precedence_assoc; }
 /* Line 1427 of yacc.c  */
     { (yyval.assoc) = precedence_assoc; }
 /* Line 1427 of yacc.c  */
-#line 2422 "src/parse-gram.c"
+#line 2429 "src/parse-gram.c"
     break;
 
   case 57:
 /* Line 1427 of yacc.c  */
     break;
 
   case 57:
 /* Line 1427 of yacc.c  */
-#line 473 "src/parse-gram.y"
+#line 474 "src/parse-gram.y"
     { current_type = NULL; }
 /* Line 1427 of yacc.c  */
     { current_type = NULL; }
 /* Line 1427 of yacc.c  */
-#line 2430 "src/parse-gram.c"
+#line 2437 "src/parse-gram.c"
     break;
 
   case 58:
 /* Line 1427 of yacc.c  */
     break;
 
   case 58:
 /* Line 1427 of yacc.c  */
-#line 474 "src/parse-gram.y"
+#line 475 "src/parse-gram.y"
     { current_type = (yyvsp[0].uniqstr); tag_seen = true; }
 /* Line 1427 of yacc.c  */
     { current_type = (yyvsp[0].uniqstr); tag_seen = true; }
 /* Line 1427 of yacc.c  */
-#line 2438 "src/parse-gram.c"
+#line 2445 "src/parse-gram.c"
     break;
 
   case 59:
 /* Line 1427 of yacc.c  */
     break;
 
   case 59:
 /* Line 1427 of yacc.c  */
-#line 480 "src/parse-gram.y"
+#line 481 "src/parse-gram.y"
     { (yyval.list) = symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0])); }
 /* Line 1427 of yacc.c  */
     { (yyval.list) = symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0])); }
 /* Line 1427 of yacc.c  */
-#line 2446 "src/parse-gram.c"
+#line 2453 "src/parse-gram.c"
     break;
 
   case 60:
 /* Line 1427 of yacc.c  */
     break;
 
   case 60:
 /* Line 1427 of yacc.c  */
-#line 482 "src/parse-gram.y"
+#line 483 "src/parse-gram.y"
     { (yyval.list) = symbol_list_prepend ((yyvsp[-1].list), symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0]))); }
 /* Line 1427 of yacc.c  */
     { (yyval.list) = symbol_list_prepend ((yyvsp[-1].list), symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0]))); }
 /* Line 1427 of yacc.c  */
-#line 2454 "src/parse-gram.c"
+#line 2461 "src/parse-gram.c"
     break;
 
   case 61:
 /* Line 1427 of yacc.c  */
     break;
 
   case 61:
 /* Line 1427 of yacc.c  */
-#line 486 "src/parse-gram.y"
+#line 487 "src/parse-gram.y"
     { (yyval.symbol) = (yyvsp[0].symbol); }
 /* Line 1427 of yacc.c  */
     { (yyval.symbol) = (yyvsp[0].symbol); }
 /* Line 1427 of yacc.c  */
-#line 2462 "src/parse-gram.c"
+#line 2469 "src/parse-gram.c"
     break;
 
   case 62:
 /* Line 1427 of yacc.c  */
     break;
 
   case 62:
 /* Line 1427 of yacc.c  */
-#line 487 "src/parse-gram.y"
+#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 1427 of yacc.c  */
     { (yyval.symbol) = (yyvsp[-1].symbol); symbol_user_token_number_set ((yyvsp[-1].symbol), (yyvsp[0].integer), (yylsp[0])); }
 /* Line 1427 of yacc.c  */
-#line 2470 "src/parse-gram.c"
+#line 2477 "src/parse-gram.c"
     break;
 
   case 63:
 /* Line 1427 of yacc.c  */
     break;
 
   case 63:
 /* Line 1427 of yacc.c  */
-#line 493 "src/parse-gram.y"
+#line 494 "src/parse-gram.y"
     { (yyval.list) = symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0])); }
 /* Line 1427 of yacc.c  */
     { (yyval.list) = symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0])); }
 /* Line 1427 of yacc.c  */
-#line 2478 "src/parse-gram.c"
+#line 2485 "src/parse-gram.c"
     break;
 
   case 64:
 /* Line 1427 of yacc.c  */
     break;
 
   case 64:
 /* Line 1427 of yacc.c  */
-#line 495 "src/parse-gram.y"
+#line 496 "src/parse-gram.y"
     { (yyval.list) = symbol_list_prepend ((yyvsp[-1].list), symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0]))); }
 /* Line 1427 of yacc.c  */
     { (yyval.list) = symbol_list_prepend ((yyvsp[-1].list), symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0]))); }
 /* Line 1427 of yacc.c  */
-#line 2486 "src/parse-gram.c"
+#line 2493 "src/parse-gram.c"
     break;
 
   case 65:
 /* Line 1427 of yacc.c  */
     break;
 
   case 65:
 /* Line 1427 of yacc.c  */
-#line 499 "src/parse-gram.y"
+#line 500 "src/parse-gram.y"
     { (yyval.list) = (yyvsp[0].list); }
 /* Line 1427 of yacc.c  */
     { (yyval.list) = (yyvsp[0].list); }
 /* Line 1427 of yacc.c  */
-#line 2494 "src/parse-gram.c"
+#line 2501 "src/parse-gram.c"
     break;
 
   case 66:
 /* Line 1427 of yacc.c  */
     break;
 
   case 66:
 /* Line 1427 of yacc.c  */
-#line 500 "src/parse-gram.y"
+#line 501 "src/parse-gram.y"
     { (yyval.list) = symbol_list_prepend ((yyvsp[-1].list), (yyvsp[0].list)); }
 /* Line 1427 of yacc.c  */
     { (yyval.list) = symbol_list_prepend ((yyvsp[-1].list), (yyvsp[0].list)); }
 /* Line 1427 of yacc.c  */
-#line 2502 "src/parse-gram.c"
+#line 2509 "src/parse-gram.c"
     break;
 
   case 67:
 /* Line 1427 of yacc.c  */
     break;
 
   case 67:
 /* Line 1427 of yacc.c  */
-#line 504 "src/parse-gram.y"
+#line 505 "src/parse-gram.y"
     { (yyval.list) = symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0])); }
 /* Line 1427 of yacc.c  */
     { (yyval.list) = symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0])); }
 /* Line 1427 of yacc.c  */
-#line 2510 "src/parse-gram.c"
+#line 2517 "src/parse-gram.c"
     break;
 
   case 68:
 /* Line 1427 of yacc.c  */
     break;
 
   case 68:
 /* Line 1427 of yacc.c  */
-#line 505 "src/parse-gram.y"
+#line 506 "src/parse-gram.y"
     { (yyval.list) = symbol_list_type_new ((yyvsp[0].uniqstr), (yylsp[0])); }
 /* Line 1427 of yacc.c  */
     { (yyval.list) = symbol_list_type_new ((yyvsp[0].uniqstr), (yylsp[0])); }
 /* Line 1427 of yacc.c  */
-#line 2518 "src/parse-gram.c"
+#line 2525 "src/parse-gram.c"
     break;
 
   case 69:
 /* Line 1427 of yacc.c  */
     break;
 
   case 69:
 /* Line 1427 of yacc.c  */
-#line 506 "src/parse-gram.y"
+#line 507 "src/parse-gram.y"
     { (yyval.list) = symbol_list_default_tagged_new ((yylsp[0])); }
 /* Line 1427 of yacc.c  */
     { (yyval.list) = symbol_list_default_tagged_new ((yylsp[0])); }
 /* Line 1427 of yacc.c  */
-#line 2526 "src/parse-gram.c"
+#line 2533 "src/parse-gram.c"
     break;
 
   case 70:
 /* Line 1427 of yacc.c  */
     break;
 
   case 70:
 /* Line 1427 of yacc.c  */
-#line 507 "src/parse-gram.y"
+#line 508 "src/parse-gram.y"
     { (yyval.list) = symbol_list_default_tagless_new ((yylsp[0])); }
 /* Line 1427 of yacc.c  */
     { (yyval.list) = symbol_list_default_tagless_new ((yylsp[0])); }
 /* Line 1427 of yacc.c  */
-#line 2534 "src/parse-gram.c"
+#line 2541 "src/parse-gram.c"
     break;
 
   case 71:
 /* Line 1427 of yacc.c  */
     break;
 
   case 71:
 /* Line 1427 of yacc.c  */
-#line 513 "src/parse-gram.y"
+#line 514 "src/parse-gram.y"
     {
        current_type = (yyvsp[0].uniqstr);
        tag_seen = true;
      }
 /* Line 1427 of yacc.c  */
     {
        current_type = (yyvsp[0].uniqstr);
        tag_seen = true;
      }
 /* Line 1427 of yacc.c  */
-#line 2545 "src/parse-gram.c"
+#line 2552 "src/parse-gram.c"
     break;
 
   case 72:
 /* Line 1427 of yacc.c  */
     break;
 
   case 72:
 /* Line 1427 of yacc.c  */
-#line 518 "src/parse-gram.y"
+#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 1427 of yacc.c  */
     {
        symbol_class_set ((yyvsp[0].symbol), current_class, (yylsp[0]), true);
        symbol_type_set ((yyvsp[0].symbol), current_type, (yylsp[0]));
      }
 /* Line 1427 of yacc.c  */
-#line 2556 "src/parse-gram.c"
+#line 2563 "src/parse-gram.c"
     break;
 
   case 73:
 /* Line 1427 of yacc.c  */
     break;
 
   case 73:
 /* Line 1427 of yacc.c  */
-#line 523 "src/parse-gram.y"
+#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 1427 of yacc.c  */
     {
       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 1427 of yacc.c  */
-#line 2568 "src/parse-gram.c"
+#line 2575 "src/parse-gram.c"
     break;
 
   case 74:
 /* Line 1427 of yacc.c  */
     break;
 
   case 74:
 /* Line 1427 of yacc.c  */
-#line 529 "src/parse-gram.y"
+#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 1427 of yacc.c  */
     {
       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 1427 of yacc.c  */
-#line 2580 "src/parse-gram.c"
+#line 2587 "src/parse-gram.c"
     break;
 
   case 75:
 /* Line 1427 of yacc.c  */
     break;
 
   case 75:
 /* Line 1427 of yacc.c  */
-#line 535 "src/parse-gram.y"
+#line 536 "src/parse-gram.y"
     {
       symbol_class_set ((yyvsp[-2].symbol), current_class, (yylsp[-2]), true);
       symbol_type_set ((yyvsp[-2].symbol), current_type, (yylsp[-2]));
     {
       symbol_class_set ((yyvsp[-2].symbol), current_class, (yylsp[-2]), true);
       symbol_type_set ((yyvsp[-2].symbol), current_type, (yylsp[-2]));
@@ -2589,136 +2596,144 @@ yyreduce:
       symbol_make_alias ((yyvsp[-2].symbol), (yyvsp[0].symbol), (yyloc));
     }
 /* Line 1427 of yacc.c  */
       symbol_make_alias ((yyvsp[-2].symbol), (yyvsp[0].symbol), (yyloc));
     }
 /* Line 1427 of yacc.c  */
-#line 2593 "src/parse-gram.c"
+#line 2600 "src/parse-gram.c"
     break;
 
   case 82:
 /* Line 1427 of yacc.c  */
     break;
 
   case 82:
 /* Line 1427 of yacc.c  */
-#line 565 "src/parse-gram.y"
+#line 566 "src/parse-gram.y"
     {
       yyerrok;
     }
 /* Line 1427 of yacc.c  */
     {
       yyerrok;
     }
 /* Line 1427 of yacc.c  */
-#line 2603 "src/parse-gram.c"
+#line 2610 "src/parse-gram.c"
     break;
 
   case 83:
 /* Line 1427 of yacc.c  */
     break;
 
   case 83:
 /* Line 1427 of yacc.c  */
-#line 571 "src/parse-gram.y"
+#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 1427 of yacc.c  */
     { current_lhs = (yyvsp[-1].symbol); current_lhs_location = (yylsp[-1]);
     current_lhs_named_ref = (yyvsp[0].named_ref); }
 /* Line 1427 of yacc.c  */
-#line 2612 "src/parse-gram.c"
+#line 2619 "src/parse-gram.c"
     break;
 
   case 85:
 /* Line 1427 of yacc.c  */
     break;
 
   case 85:
 /* Line 1427 of yacc.c  */
-#line 576 "src/parse-gram.y"
+#line 577 "src/parse-gram.y"
     { grammar_current_rule_end ((yylsp[0])); }
 /* Line 1427 of yacc.c  */
     { grammar_current_rule_end ((yylsp[0])); }
 /* Line 1427 of yacc.c  */
-#line 2620 "src/parse-gram.c"
+#line 2627 "src/parse-gram.c"
     break;
 
   case 86:
 /* Line 1427 of yacc.c  */
     break;
 
   case 86:
 /* Line 1427 of yacc.c  */
-#line 577 "src/parse-gram.y"
+#line 578 "src/parse-gram.y"
     { grammar_current_rule_end ((yylsp[0])); }
 /* Line 1427 of yacc.c  */
     { grammar_current_rule_end ((yylsp[0])); }
 /* Line 1427 of yacc.c  */
-#line 2628 "src/parse-gram.c"
+#line 2635 "src/parse-gram.c"
     break;
 
   case 88:
 /* Line 1427 of yacc.c  */
     break;
 
   case 88:
 /* Line 1427 of yacc.c  */
-#line 583 "src/parse-gram.y"
+#line 584 "src/parse-gram.y"
     { grammar_current_rule_begin (current_lhs, current_lhs_location,
                                  current_lhs_named_ref); }
 /* Line 1427 of yacc.c  */
     { grammar_current_rule_begin (current_lhs, current_lhs_location,
                                  current_lhs_named_ref); }
 /* Line 1427 of yacc.c  */
-#line 2637 "src/parse-gram.c"
+#line 2644 "src/parse-gram.c"
     break;
 
   case 89:
 /* Line 1427 of yacc.c  */
     break;
 
   case 89:
 /* Line 1427 of yacc.c  */
-#line 586 "src/parse-gram.y"
+#line 587 "src/parse-gram.y"
     { grammar_current_rule_symbol_append ((yyvsp[-1].symbol), (yylsp[-1]), (yyvsp[0].named_ref)); }
 /* Line 1427 of yacc.c  */
     { grammar_current_rule_symbol_append ((yyvsp[-1].symbol), (yylsp[-1]), (yyvsp[0].named_ref)); }
 /* Line 1427 of yacc.c  */
-#line 2645 "src/parse-gram.c"
+#line 2652 "src/parse-gram.c"
     break;
 
   case 90:
 /* Line 1427 of yacc.c  */
     break;
 
   case 90:
 /* Line 1427 of yacc.c  */
-#line 588 "src/parse-gram.y"
-    { grammar_current_rule_action_append ((yyvsp[-1].code), (yylsp[-1]), (yyvsp[0].named_ref)); }
+#line 589 "src/parse-gram.y"
+    { grammar_current_rule_action_append ((yyvsp[-1].code), (yylsp[-1]), (yyvsp[0].named_ref), false); }
 /* Line 1427 of yacc.c  */
 /* Line 1427 of yacc.c  */
-#line 2653 "src/parse-gram.c"
+#line 2660 "src/parse-gram.c"
     break;
 
   case 91:
 /* Line 1427 of yacc.c  */
     break;
 
   case 91:
 /* Line 1427 of yacc.c  */
-#line 590 "src/parse-gram.y"
-    { grammar_current_rule_prec_set ((yyvsp[0].symbol), (yylsp[0])); }
+#line 591 "src/parse-gram.y"
+    { grammar_current_rule_action_append ((yyvsp[0].code), (yylsp[0]), NULL, true); }
 /* Line 1427 of yacc.c  */
 /* Line 1427 of yacc.c  */
-#line 2661 "src/parse-gram.c"
+#line 2668 "src/parse-gram.c"
     break;
 
   case 92:
 /* Line 1427 of yacc.c  */
     break;
 
   case 92:
 /* Line 1427 of yacc.c  */
-#line 592 "src/parse-gram.y"
-    { grammar_current_rule_dprec_set ((yyvsp[0].integer), (yylsp[0])); }
+#line 593 "src/parse-gram.y"
+    { grammar_current_rule_prec_set ((yyvsp[0].symbol), (yylsp[0])); }
 /* Line 1427 of yacc.c  */
 /* Line 1427 of yacc.c  */
-#line 2669 "src/parse-gram.c"
+#line 2676 "src/parse-gram.c"
     break;
 
   case 93:
 /* Line 1427 of yacc.c  */
     break;
 
   case 93:
 /* Line 1427 of yacc.c  */
-#line 594 "src/parse-gram.y"
-    { grammar_current_rule_merge_set ((yyvsp[0].uniqstr), (yylsp[0])); }
+#line 595 "src/parse-gram.y"
+    { grammar_current_rule_dprec_set ((yyvsp[0].integer), (yylsp[0])); }
 /* Line 1427 of yacc.c  */
 /* Line 1427 of yacc.c  */
-#line 2677 "src/parse-gram.c"
+#line 2684 "src/parse-gram.c"
     break;
 
   case 94:
 /* Line 1427 of yacc.c  */
     break;
 
   case 94:
 /* Line 1427 of yacc.c  */
-#line 598 "src/parse-gram.y"
-    { (yyval.named_ref) = 0; }
+#line 597 "src/parse-gram.y"
+    { grammar_current_rule_merge_set ((yyvsp[0].uniqstr), (yylsp[0])); }
 /* Line 1427 of yacc.c  */
 /* Line 1427 of yacc.c  */
-#line 2685 "src/parse-gram.c"
+#line 2692 "src/parse-gram.c"
     break;
 
   case 95:
 /* Line 1427 of yacc.c  */
     break;
 
   case 95:
 /* Line 1427 of yacc.c  */
-#line 600 "src/parse-gram.y"
+#line 601 "src/parse-gram.y"
+    { (yyval.named_ref) = 0; }
+/* Line 1427 of yacc.c  */
+#line 2700 "src/parse-gram.c"
+    break;
+
+  case 96:
+/* Line 1427 of yacc.c  */
+#line 603 "src/parse-gram.y"
     { (yyval.named_ref) = named_ref_new((yyvsp[0].uniqstr), (yylsp[0])); }
 /* Line 1427 of yacc.c  */
     { (yyval.named_ref) = named_ref_new((yyvsp[0].uniqstr), (yylsp[0])); }
 /* Line 1427 of yacc.c  */
-#line 2693 "src/parse-gram.c"
+#line 2708 "src/parse-gram.c"
     break;
 
     break;
 
-  case 97:
+  case 98:
 /* Line 1427 of yacc.c  */
 /* Line 1427 of yacc.c  */
-#line 612 "src/parse-gram.y"
+#line 614 "src/parse-gram.y"
     { (yyval.uniqstr) = uniqstr_new ((yyvsp[0].chars)); }
 /* Line 1427 of yacc.c  */
     { (yyval.uniqstr) = uniqstr_new ((yyvsp[0].chars)); }
 /* Line 1427 of yacc.c  */
-#line 2701 "src/parse-gram.c"
+#line 2716 "src/parse-gram.c"
     break;
 
     break;
 
-  case 98:
+  case 99:
 /* Line 1427 of yacc.c  */
 /* Line 1427 of yacc.c  */
-#line 617 "src/parse-gram.y"
+#line 619 "src/parse-gram.y"
     { (yyval.chars) = ""; }
 /* Line 1427 of yacc.c  */
     { (yyval.chars) = ""; }
 /* Line 1427 of yacc.c  */
-#line 2709 "src/parse-gram.c"
+#line 2724 "src/parse-gram.c"
     break;
 
     break;
 
-  case 99:
+  case 100:
 /* Line 1427 of yacc.c  */
 /* Line 1427 of yacc.c  */
-#line 618 "src/parse-gram.y"
+#line 620 "src/parse-gram.y"
     { (yyval.chars) = (yyvsp[0].uniqstr); }
 /* Line 1427 of yacc.c  */
     { (yyval.chars) = (yyvsp[0].uniqstr); }
 /* Line 1427 of yacc.c  */
-#line 2717 "src/parse-gram.c"
+#line 2732 "src/parse-gram.c"
     break;
 
     break;
 
-  case 101:
+  case 102:
 /* Line 1427 of yacc.c  */
 /* Line 1427 of yacc.c  */
-#line 629 "src/parse-gram.y"
+#line 631 "src/parse-gram.y"
     {
       code_props plain_code;
       (yyvsp[0].code)[strlen ((yyvsp[0].code)) - 1] = '\n';
     {
       code_props plain_code;
       (yyvsp[0].code)[strlen ((yyvsp[0].code)) - 1] = '\n';
@@ -2728,51 +2743,51 @@ yyreduce:
       (yyval.chars) = plain_code.code;
     }
 /* Line 1427 of yacc.c  */
       (yyval.chars) = plain_code.code;
     }
 /* Line 1427 of yacc.c  */
-#line 2732 "src/parse-gram.c"
+#line 2747 "src/parse-gram.c"
     break;
 
     break;
 
-  case 102:
+  case 103:
 /* Line 1427 of yacc.c  */
 /* Line 1427 of yacc.c  */
-#line 649 "src/parse-gram.y"
+#line 651 "src/parse-gram.y"
     { (yyval.symbol) = symbol_from_uniqstr ((yyvsp[0].uniqstr), (yylsp[0])); }
 /* Line 1427 of yacc.c  */
     { (yyval.symbol) = symbol_from_uniqstr ((yyvsp[0].uniqstr), (yylsp[0])); }
 /* Line 1427 of yacc.c  */
-#line 2740 "src/parse-gram.c"
+#line 2755 "src/parse-gram.c"
     break;
 
     break;
 
-  case 103:
+  case 104:
 /* Line 1427 of yacc.c  */
 /* Line 1427 of yacc.c  */
-#line 651 "src/parse-gram.y"
+#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 1427 of yacc.c  */
     {
       (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 1427 of yacc.c  */
-#line 2752 "src/parse-gram.c"
+#line 2767 "src/parse-gram.c"
     break;
 
     break;
 
-  case 104:
+  case 105:
 /* Line 1427 of yacc.c  */
 /* Line 1427 of yacc.c  */
-#line 659 "src/parse-gram.y"
+#line 661 "src/parse-gram.y"
     { (yyval.symbol) = symbol_from_uniqstr ((yyvsp[0].uniqstr), (yylsp[0])); }
 /* Line 1427 of yacc.c  */
     { (yyval.symbol) = symbol_from_uniqstr ((yyvsp[0].uniqstr), (yylsp[0])); }
 /* Line 1427 of yacc.c  */
-#line 2760 "src/parse-gram.c"
+#line 2775 "src/parse-gram.c"
     break;
 
     break;
 
-  case 107:
+  case 108:
 /* Line 1427 of yacc.c  */
 /* Line 1427 of yacc.c  */
-#line 671 "src/parse-gram.y"
+#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 1427 of yacc.c  */
     {
       (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 1427 of yacc.c  */
-#line 2771 "src/parse-gram.c"
+#line 2786 "src/parse-gram.c"
     break;
 
     break;
 
-  case 109:
+  case 110:
 /* Line 1427 of yacc.c  */
 /* Line 1427 of yacc.c  */
-#line 680 "src/parse-gram.y"
+#line 682 "src/parse-gram.y"
     {
       code_props plain_code;
       code_props_plain_init (&plain_code, (yyvsp[0].chars), (yylsp[0]));
     {
       code_props plain_code;
       code_props_plain_init (&plain_code, (yyvsp[0].chars), (yylsp[0]));
@@ -2782,12 +2797,12 @@ yyreduce:
       code_scanner_last_string_free ();
     }
 /* Line 1427 of yacc.c  */
       code_scanner_last_string_free ();
     }
 /* Line 1427 of yacc.c  */
-#line 2786 "src/parse-gram.c"
+#line 2801 "src/parse-gram.c"
     break;
 
 
 /* Line 1427 of yacc.c  */
     break;
 
 
 /* Line 1427 of yacc.c  */
-#line 2791 "src/parse-gram.c"
+#line 2806 "src/parse-gram.c"
       default: break;
     }
   /* User semantic actions sometimes alter yychar, and that requires
       default: break;
     }
   /* User semantic actions sometimes alter yychar, and that requires
@@ -3015,7 +3030,7 @@ yyreturn:
 }
 
 /* Line 1657 of yacc.c  */
 }
 
 /* Line 1657 of yacc.c  */
-#line 690 "src/parse-gram.y"
+#line 692 "src/parse-gram.y"
 
 
 
 
 
 
index 3363499a5a33f3b9f9f81990b21b7e1dbfa22cc9..d8eea03cb90de0623eee46434e0d7f9b400a5efb 100644 (file)
@@ -1,8 +1,9 @@
-/* A Bison parser, made by GNU Bison 2.4.483-4ad39-dirty.  */
+/* A Bison parser, made by GNU Bison 2.4.516-804e.  */
 
 /* Interface for Bison's Yacc-like parsers in C
 
 
 /* Interface for Bison's Yacc-like parsers in C
 
-   Copyright (C) 1984, 1989-1990, 2000-2010 Free Software Foundation, Inc.
+   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+   2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -31,7 +32,7 @@
    version 2.2 of Bison.  */
 /* "%code requires" blocks.  */
 /* Line 1658 of yacc.c  */
    version 2.2 of Bison.  */
 /* "%code requires" blocks.  */
 /* Line 1658 of yacc.c  */
-#line 201 "src/parse-gram.y"
+#line 202 "src/parse-gram.y"
 
 # ifndef PARAM_TYPE
 #  define PARAM_TYPE
 
 # ifndef PARAM_TYPE
 #  define PARAM_TYPE
@@ -46,7 +47,7 @@
 
 
 /* Line 1658 of yacc.c  */
 
 
 /* Line 1658 of yacc.c  */
-#line 50 "src/parse-gram.h"
+#line 51 "src/parse-gram.h"
 
 /* Tokens.  */
 #ifndef YYTOKENTYPE
 
 /* Tokens.  */
 #ifndef YYTOKENTYPE
      PERCENT_VERBOSE = 293,
      PERCENT_YACC = 294,
      BRACED_CODE = 295,
      PERCENT_VERBOSE = 293,
      PERCENT_YACC = 294,
      BRACED_CODE = 295,
-     BRACKETED_ID = 296,
-     CHAR = 297,
-     EPILOGUE = 298,
-     EQUAL = 299,
-     ID = 300,
-     ID_COLON = 301,
-     PERCENT_PERCENT = 302,
-     PIPE = 303,
-     PROLOGUE = 304,
-     SEMICOLON = 305,
-     TAG = 306,
-     TAG_ANY = 307,
-     TAG_NONE = 308,
-     PERCENT_PARAM = 309,
-     PERCENT_UNION = 310
+     BRACED_PREDICATE = 296,
+     BRACKETED_ID = 297,
+     CHAR = 298,
+     EPILOGUE = 299,
+     EQUAL = 300,
+     ID = 301,
+     ID_COLON = 302,
+     PERCENT_PERCENT = 303,
+     PIPE = 304,
+     PROLOGUE = 305,
+     SEMICOLON = 306,
+     TAG = 307,
+     TAG_ANY = 308,
+     TAG_NONE = 309,
+     PERCENT_PARAM = 310,
+     PERCENT_UNION = 311
    };
 #endif
 /* Tokens.  */
    };
 #endif
 /* Tokens.  */
 #define PERCENT_VERBOSE 293
 #define PERCENT_YACC 294
 #define BRACED_CODE 295
 #define PERCENT_VERBOSE 293
 #define PERCENT_YACC 294
 #define BRACED_CODE 295
-#define BRACKETED_ID 296
-#define CHAR 297
-#define EPILOGUE 298
-#define EQUAL 299
-#define ID 300
-#define ID_COLON 301
-#define PERCENT_PERCENT 302
-#define PIPE 303
-#define PROLOGUE 304
-#define SEMICOLON 305
-#define TAG 306
-#define TAG_ANY 307
-#define TAG_NONE 308
-#define PERCENT_PARAM 309
-#define PERCENT_UNION 310
+#define BRACED_PREDICATE 296
+#define BRACKETED_ID 297
+#define CHAR 298
+#define EPILOGUE 299
+#define EQUAL 300
+#define ID 301
+#define ID_COLON 302
+#define PERCENT_PERCENT 303
+#define PIPE 304
+#define PROLOGUE 305
+#define SEMICOLON 306
+#define TAG 307
+#define TAG_ANY 308
+#define TAG_NONE 309
+#define PERCENT_PARAM 310
+#define PERCENT_UNION 311
 
 
 
 
 
 
 typedef union YYSTYPE
 {
 /* Line 1658 of yacc.c  */
 typedef union YYSTYPE
 {
 /* Line 1658 of yacc.c  */
-#line 87 "src/parse-gram.y"
+#line 88 "src/parse-gram.y"
 
   assoc assoc;
   char *code;
 
   assoc assoc;
   char *code;
@@ -186,13 +189,13 @@ typedef union YYSTYPE
   unsigned char character;
 
 /* Line 1658 of yacc.c  */
   unsigned char character;
 
 /* Line 1658 of yacc.c  */
-#line 225 "src/parse-gram.y"
+#line 226 "src/parse-gram.y"
 
   param_type param;
 
 
 /* Line 1658 of yacc.c  */
 
   param_type param;
 
 
 /* Line 1658 of yacc.c  */
-#line 196 "src/parse-gram.h"
+#line 199 "src/parse-gram.h"
 } YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
 } YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
index b897d6915fbd59b24a24d0bd2b52048d736bbf0b..d588dfa8ab0f2ba015414a37cf7f8059e058d6cd 100644 (file)
@@ -118,7 +118,6 @@ static char const *char_name (char);
 %token PERCENT_DPREC         "%dprec"
 %token PERCENT_MERGE         "%merge"
 
 %token PERCENT_DPREC         "%dprec"
 %token PERCENT_MERGE         "%merge"
 
-
 /*----------------------.
 | Global Declarations.  |
 `----------------------*/
 /*----------------------.
 | Global Declarations.  |
 `----------------------*/
@@ -151,6 +150,7 @@ static char const *char_name (char);
 ;
 
 %token BRACED_CODE     "{...}"
 ;
 
 %token BRACED_CODE     "{...}"
+%token BRACED_PREDICATE "%?{...}"
 %token BRACKETED_ID    "[identifier]"
 %token CHAR            "char"
 %token EPILOGUE        "epilogue"
 %token BRACKETED_ID    "[identifier]"
 %token CHAR            "char"
 %token EPILOGUE        "epilogue"
@@ -171,7 +171,7 @@ static char const *char_name (char);
 /* braceless is not to be used for rule or symbol actions, as it
    calls code_props_plain_init.  */
 %type <chars> STRING "%{...%}" EPILOGUE braceless content.opt
 /* braceless is not to be used for rule or symbol actions, as it
    calls code_props_plain_init.  */
 %type <chars> STRING "%{...%}" EPILOGUE braceless content.opt
-%type <code> "{...}"
+%type <code> "{...}" "%?{...}"
 %printer { fputs (quotearg_style (c_quoting_style, $$), stderr); }
         STRING
 %printer { fprintf (stderr, "{\n%s\n}", $$); }
 %printer { fputs (quotearg_style (c_quoting_style, $$), stderr); }
         STRING
 %printer { fprintf (stderr, "{\n%s\n}", $$); }
@@ -586,7 +586,9 @@ rhs:
 | rhs symbol named_ref.opt
     { grammar_current_rule_symbol_append ($2, @2, $3); }
 | rhs "{...}" named_ref.opt
 | rhs symbol named_ref.opt
     { grammar_current_rule_symbol_append ($2, @2, $3); }
 | rhs "{...}" named_ref.opt
-    { grammar_current_rule_action_append ($2, @2, $3); }
+    { grammar_current_rule_action_append ($2, @2, $3, false); }
+| rhs "%?{...}" 
+    { grammar_current_rule_action_append ($2, @2, NULL, true); }
 | rhs "%prec" symbol
     { grammar_current_rule_prec_set ($3, @3); }
 | rhs "%dprec" INT
 | rhs "%prec" symbol
     { grammar_current_rule_prec_set ($3, @3); }
 | rhs "%dprec" INT
@@ -601,7 +603,6 @@ named_ref.opt:
   BRACKETED_ID   { $$ = named_ref_new($1, @1); }
 ;
 
   BRACKETED_ID   { $$ = named_ref_new($1, @1); }
 ;
 
-
 /*---------------------------.
 | variable and content.opt.  |
 `---------------------------*/
 /*---------------------------.
 | variable and content.opt.  |
 `---------------------------*/
index 791fe181bad8998758aa734fa4731082c7c7749a..e64741cb2389b1a03cb809254255631a80ca93a9 100644 (file)
@@ -377,7 +377,8 @@ grammar_midrule_action (void)
   code_props_rule_action_init (&midrule->action_props,
                                current_rule->action_props.code,
                                current_rule->action_props.location,
   code_props_rule_action_init (&midrule->action_props,
                                current_rule->action_props.code,
                                current_rule->action_props.location,
-                               midrule, 0);
+                               midrule, 0,
+                              current_rule->action_props.is_predicate);
   code_props_none_init (&current_rule->action_props);
 
   if (previous_rule_end)
   code_props_none_init (&current_rule->action_props);
 
   if (previous_rule_end)
@@ -468,14 +469,14 @@ grammar_current_rule_symbol_append (symbol *sym, location loc,
 
 void
 grammar_current_rule_action_append (const char *action, location loc,
 
 void
 grammar_current_rule_action_append (const char *action, location loc,
-                                   named_ref *name)
+                                   named_ref *name, bool is_predicate)
 {
   if (current_rule->action_props.code)
     grammar_midrule_action ();
   /* After all symbol declarations have been parsed, packgram invokes
      code_props_translate_code.  */
   code_props_rule_action_init (&current_rule->action_props, action, loc,
 {
   if (current_rule->action_props.code)
     grammar_midrule_action ();
   /* After all symbol declarations have been parsed, packgram invokes
      code_props_translate_code.  */
   code_props_rule_action_init (&current_rule->action_props, action, loc,
-                               current_rule, name);
+                               current_rule, name, is_predicate);
 }
 
 \f
 }
 
 \f
@@ -516,6 +517,7 @@ packgram (void)
       rules[ruleno].useful = true;
       rules[ruleno].action = p->action_props.code;
       rules[ruleno].action_location = p->action_props.location;
       rules[ruleno].useful = true;
       rules[ruleno].action = p->action_props.code;
       rules[ruleno].action_location = p->action_props.location;
+      rules[ruleno].is_predicate = p->action_props.is_predicate;
 
       /* If the midrule's $$ is set or its $n is used, remove the `$' from the
         symbol name so that it's a user-defined symbol so that the default
 
       /* If the midrule's $$ is set or its $n is used, remove the `$' from the
         symbol name so that it's a user-defined symbol so that the default
index 7d37f817a6e669380af0afa94fb2c3c455aec11f..da8a6c7e81723a8eb7cebc7a71496775477b8292 100644 (file)
@@ -53,7 +53,7 @@ void grammar_current_rule_merge_set (uniqstr name, location loc);
 void grammar_current_rule_symbol_append (symbol *sym, location loc,
                                         named_ref *named_ref);
 void grammar_current_rule_action_append (const char *action, location loc,
 void grammar_current_rule_symbol_append (symbol *sym, location loc,
                                         named_ref *named_ref);
 void grammar_current_rule_action_append (const char *action, location loc,
-                                        named_ref *named_ref);
+                                        named_ref *named_ref, bool);
 void reader (void);
 void free_merger_functions (void);
 
 void reader (void);
 void free_merger_functions (void);
 
index 81a2afbe5dc6ab5911c54c7812e66d7d74a89ad3..79edc6e8e82749b65e471177c9e52f931bd375ac 100644 (file)
@@ -63,6 +63,13 @@ typedef struct code_props {
    */
   bool is_value_used;
 
    */
   bool is_value_used;
 
+  /**
+   * \c true iff this code is an action that is not to be deferred in
+   * a non-deterministic parser.
+   */
+  bool is_predicate;
+
+
   /** \c NULL iff \c code_props::kind is not \c CODE_PROPS_RULE_ACTION.  */
   struct symbol_list *rule;
 
   /** \c NULL iff \c code_props::kind is not \c CODE_PROPS_RULE_ACTION.  */
   struct symbol_list *rule;
 
@@ -80,7 +87,7 @@ void code_props_none_init (code_props *self);
 
 /** Equivalent to \c code_props_none_init.  */
 #define CODE_PROPS_NONE_INIT \
 
 /** Equivalent to \c code_props_none_init.  */
 #define CODE_PROPS_NONE_INIT \
-  {CODE_PROPS_NONE, NULL, EMPTY_LOCATION_INIT, false, NULL, NULL}
+  {CODE_PROPS_NONE, NULL, EMPTY_LOCATION_INIT, false, false, NULL, NULL}
 
 /** Initialized by \c CODE_PROPS_NONE_INIT with no further modification.  */
 extern code_props const code_props_none;
 
 /** Initialized by \c CODE_PROPS_NONE_INIT with no further modification.  */
 extern code_props const code_props_none;
@@ -134,7 +141,7 @@ void code_props_symbol_action_init (code_props *self, char const *code,
  */
 void code_props_rule_action_init (code_props *self, char const *code,
                                   location code_loc, struct symbol_list *rule,
  */
 void code_props_rule_action_init (code_props *self, char const *code,
                                   location code_loc, struct symbol_list *rule,
-                                  named_ref *name);
+                                  named_ref *name, bool is_predicate);
 
 /**
  * \pre
 
 /**
  * \pre
index cb5d3a39f47871c976f611c3b153b40ad6435468..200fdf4ec7ac618940475b721b5134d3d20f1c71 100644 (file)
@@ -902,7 +902,7 @@ code_props_symbol_action_init (code_props *self, char const *code,
 void
 code_props_rule_action_init (code_props *self, char const *code,
                              location code_loc, symbol_list *rule,
 void
 code_props_rule_action_init (code_props *self, char const *code,
                              location code_loc, symbol_list *rule,
-                            named_ref *name)
+                            named_ref *name, bool is_predicate)
 {
   self->kind = CODE_PROPS_RULE_ACTION;
   self->code = code;
 {
   self->kind = CODE_PROPS_RULE_ACTION;
   self->code = code;
@@ -910,6 +910,7 @@ code_props_rule_action_init (code_props *self, char const *code,
   self->is_value_used = false;
   self->rule = rule;
   self->named_ref = name;
   self->is_value_used = false;
   self->rule = rule;
   self->named_ref = name;
+  self->is_predicate = is_predicate;
 }
 
 void
 }
 
 void
index 9d3d34280b8de5ef60f6eb63fa0213e3ab5232c6..462d007d370ce93afdce53fce4ae7afa0fc648fe 100644 (file)
@@ -106,11 +106,12 @@ static void unexpected_newline (boundary, char const *);
  /* A complex tag, with nested angles brackets. */
 %x SC_TAG
 
  /* A complex tag, with nested angles brackets. */
 %x SC_TAG
 
- /* Three types of user code:
+ /* Four types of user code:
     - prologue (code between `%{' `%}' in the first section, before %%);
     - actions, printers, union, etc, (between braced in the middle section);
     - prologue (code between `%{' `%}' in the first section, before %%);
     - actions, printers, union, etc, (between braced in the middle section);
-    - epilogue (everything after the second %%). */
-%x SC_PROLOGUE SC_BRACED_CODE SC_EPILOGUE
+    - epilogue (everything after the second %%). 
+    - predicate (code between `%?{' and `{' in middle section); */
+%x SC_PROLOGUE SC_BRACED_CODE SC_EPILOGUE SC_PREDICATE
  /* C and C++ comments in code. */
 %x SC_COMMENT SC_LINE_COMMENT
  /* Strings and characters in code. */
  /* C and C++ comments in code. */
 %x SC_COMMENT SC_LINE_COMMENT
  /* Strings and characters in code. */
@@ -285,6 +286,13 @@ splice      (\\[ \f\t\v]*\n)*
     BEGIN SC_BRACED_CODE;
   }
 
     BEGIN SC_BRACED_CODE;
   }
 
+  /* Semantic predicate. */
+  "%?"[ \f\n\t\v]*"{" {
+    nesting = 0;
+    code_start = loc->start;
+    BEGIN SC_PREDICATE;
+  }
+
   /* A type. */
   "<*>"       return TAG_ANY;
   "<>"        return TAG_NONE;
   /* A type. */
   "<*>"       return TAG_ANY;
   "<>"        return TAG_NONE;
@@ -661,7 +669,7 @@ splice       (\\[ \f\t\v]*\n)*
   | Strings, comments etc. can be found in user code.  |
   `---------------------------------------------------*/
 
   | Strings, comments etc. can be found in user code.  |
   `---------------------------------------------------*/
 
-<SC_BRACED_CODE,SC_PROLOGUE,SC_EPILOGUE>
+<SC_BRACED_CODE,SC_PROLOGUE,SC_EPILOGUE,SC_PREDICATE>
 {
   "'" {
     STRING_GROW;
 {
   "'" {
     STRING_GROW;
@@ -691,14 +699,32 @@ splice     (\\[ \f\t\v]*\n)*
 
 
   /*-----------------------------------------------------------.
 
 
   /*-----------------------------------------------------------.
-  | Scanning some code in braces (actions). The initial "{" is |
-  | already eaten.                                             |
+  | Scanning some code in braces (actions, predicates). The    |
+  | initial "{" is already eaten.                              |
   `-----------------------------------------------------------*/
 
   `-----------------------------------------------------------*/
 
-<SC_BRACED_CODE>
+<SC_BRACED_CODE,SC_PREDICATE>
 {
   "{"|"<"{splice}"%"  STRING_GROW; nesting++;
   "%"{splice}">"      STRING_GROW; nesting--;
 {
   "{"|"<"{splice}"%"  STRING_GROW; nesting++;
   "%"{splice}">"      STRING_GROW; nesting--;
+
+  /* Tokenize `<<%' correctly (as `<<' `%') rather than incorrrectly
+     (as `<' `<%').  */
+  "<"{splice}"<"  STRING_GROW;
+
+  <<EOF>> {
+    int token = (YY_START == SC_BRACED_CODE) ? BRACED_CODE : BRACED_PREDICATE;
+    unexpected_eof (code_start, "}");
+    STRING_FINISH;
+    loc->start = code_start;
+    val->code = last_string;
+    BEGIN INITIAL;
+    return token;
+  }
+}
+
+<SC_BRACED_CODE>
+{
   "}" {
     obstack_1grow (&obstack_for_string, '}');
 
   "}" {
     obstack_1grow (&obstack_for_string, '}');
 
@@ -712,22 +738,25 @@ splice     (\\[ \f\t\v]*\n)*
        return BRACED_CODE;
       }
   }
        return BRACED_CODE;
       }
   }
+}
 
 
-  /* Tokenize `<<%' correctly (as `<<' `%') rather than incorrrectly
-     (as `<' `<%').  */
-  "<"{splice}"<"  STRING_GROW;
-
-  <<EOF>> {
-    unexpected_eof (code_start, "}");
-    STRING_FINISH;
-    loc->start = code_start;
-    val->code = last_string;
-    BEGIN INITIAL;
-    return BRACED_CODE;
+<SC_PREDICATE>
+{
+  "}" {
+    --nesting;
+    if (nesting < 0)
+      {
+       STRING_FINISH;
+       loc->start = code_start;
+       val->code = last_string;
+       BEGIN INITIAL;
+       return BRACED_PREDICATE;
+      }
+    else
+      obstack_1grow (&obstack_for_string, '}');
   }
 }
 
   }
 }
 
-
   /*--------------------------------------------------------------.
   | Scanning some prologue: from "%{" (already scanned) to "%}".  |
   `--------------------------------------------------------------*/
   /*--------------------------------------------------------------.
   | Scanning some prologue: from "%{" (already scanned) to "%}".  |
   `--------------------------------------------------------------*/
@@ -774,8 +803,8 @@ splice       (\\[ \f\t\v]*\n)*
   | By default, grow the string obstack with the input.  |
   `-----------------------------------------------------*/
 
   | By default, grow the string obstack with the input.  |
   `-----------------------------------------------------*/
 
-<SC_COMMENT,SC_LINE_COMMENT,SC_BRACED_CODE,SC_PROLOGUE,SC_EPILOGUE,SC_STRING,SC_CHARACTER,SC_ESCAPED_STRING,SC_ESCAPED_CHARACTER>.     |
-<SC_COMMENT,SC_LINE_COMMENT,SC_BRACED_CODE,SC_PROLOGUE,SC_EPILOGUE>\n  STRING_GROW;
+<SC_COMMENT,SC_LINE_COMMENT,SC_BRACED_CODE,SC_PREDICATE,SC_PROLOGUE,SC_EPILOGUE,SC_STRING,SC_CHARACTER,SC_ESCAPED_STRING,SC_ESCAPED_CHARACTER>.        |
+  <SC_COMMENT,SC_LINE_COMMENT,SC_BRACED_CODE,SC_PREDICATE,SC_PROLOGUE,SC_EPILOGUE>\n   STRING_GROW;
 
 %%
 
 
 %%