]> git.saurik.com Git - bison.git/commitdiff
Merge remote-tracking branch 'origin/maint'
authorAkim Demaille <akim@lrde.epita.fr>
Fri, 27 Jul 2012 14:22:45 +0000 (16:22 +0200)
committerAkim Demaille <akim@lrde.epita.fr>
Fri, 27 Jul 2012 14:35:49 +0000 (16:35 +0200)
* origin/maint: (29 commits)
  regen
  synclines: remove spurious empty line
  also support $<foo>$ in the %initial-action
  skeletons: b4_dollar_pushdef and popdef to simpify complex definitions
  regen
  printer/destructor: translate only once
  factor the handling of m4 escaping
  news: schedule the removal of the ";" hack
  style changes in the scanners
  regen
  support $<tag>$ in printers and destructors
  scan-code: factor the handling of the type in $<TYPE>$
  muscles: fix another occurrence of unescaped type name
  glr.cc: fix the handling of yydebug
  gnulib: update
  formatting changes
  tests: fix an assertion
  tests: adjust to GCC 4.8, which displays caret errors
  be sure to properly escape type names
  obstack_quote: escape and quote for M4
  muscles: shuffle responsabilities
  muscles: make private functions static
  muscles: rename private functions/macros
  obstack_escape: escape M4 characters
  remove dead macro
  maint: style changes
  doc: avoid problems with case insensitive file systems
  configure: fix botched quoting
  news: fix typo.

Conflicts:
NEWS
data/c.m4
data/glr.cc
data/lalr1.cc
examples/rpcalc/local.mk
src/muscle-tab.h
src/output.c
src/parse-gram.c
src/parse-gram.h
src/parse-gram.y
src/scan-code.l
src/symlist.c
src/symlist.h
src/symtab.h
tests/calc.at

29 files changed:
1  2 
NEWS
THANKS
TODO
configure.ac
data/bison.m4
data/c-like.m4
data/c.m4
data/glr.c
data/glr.cc
data/java.m4
data/lalr1.cc
data/lalr1.java
data/local.mk
data/yacc.c
doc/bison.texi
src/muscle-tab.c
src/muscle-tab.h
src/output.c
src/parse-gram.y
src/scan-code.h
src/scan-code.l
src/scan-skel.l
src/symlist.c
src/symlist.h
src/symtab.h
src/system.h
tests/actions.at
tests/input.at
tests/local.at

diff --combined NEWS
index fe23b5562002c0a727c27dc50c2795b2606e6fc3,b99290c92662b1e099ebf2e3a1955850136b9b6d..150068eefb4fa38751c625da35f7975b4afad436
--- 1/NEWS
--- 2/NEWS
+++ b/NEWS
  GNU Bison NEWS
  
 +* Noteworthy changes in release ?.? (????-??-??) [?]
 +
 +** Incompatible changes
 +
 +*** Obsolete features
 +
 +  Support for YYFAIL is removed, as announced since Bison 2.4.2.
 +  Support for yystype and yyltype (instead of YYSTYPE and YYLTYPE)
 +  is removed, as announced in Bison 1.875.
 +
 +** Warnings
 +
 +*** Warning categories are now displayed in warnings
 +
 +  For instance:
 +
 +  foo.y:4.6: warning: type clash on default action: <foo> != <bar> [-Wother]
 +
 +*** Useless semantic types
 +
 +  Bison now warns about useless (uninhabited) semantic types.  Since
 +  semantic types are not declared to Bison (they are defined in the opaque
 +  %union structure), it is %printer/%destructor directives about useless
 +  types that trigger the warning:
 +
 +    %token <type1> term
 +    %type  <type2> nterm
 +    %printer    {} <type1> <type3>
 +    %destructor {} <type2> <type4>
 +    %%
 +    nterm: term { $$ = $1; };
 +
 +    3.28-34: warning: type <type3> is used, but is not associated to any symbol
 +    4.28-34: warning: type <type4> is used, but is not associated to any symbol
 +
 +*** Undeclared symbols
 +
 +  Bison used to raise an error for %printer and %destructor directives for
 +  undefined symbols.
 +
 +    %printer    {} symbol1
 +    %destructor {} symbol2
 +    %%
 +    exp: "a";
 +
 +  This is now only a warning.
 +
 +*** Useless destructors or printers
 +
 +  Bison now warns about useless destructors or printers.  In the following
 +  example, the printer for <type1>, and the destructor for <type2> are
 +  useless: all symbols of <type1> (token1) already have a printer, and all
 +  symbols of type <type2> (token2) already have a destructor.
 +
 +    %token <type1> token1
 +           <type2> token2
 +           <type3> token3
 +           <type4> token4
 +    %printer    {} token1 <type1> <type3>
 +    %destructor {} token2 <type2> <type4>
 +
 +** Additional yylex/yyparse arguments
 +
 +  The new directive %param declares additional arguments to both yylex and
 +  yyparse.  The %lex-param, %parse-param, and %param directives support one
 +  or more arguments.  Instead of
 +
 +    %lex-param   {arg1_type *arg1}
 +    %lex-param   {arg2_type *arg2}
 +    %parse-param {arg1_type *arg1}
 +    %parse-param {arg2_type *arg2}
 +
 +  one may now declare
 +
 +    %param {arg1_type *arg1} {arg2_type *arg2}
 +
 +** Java skeleton improvements
 +
 +  The constants for token names were moved to the Lexer interface.
 +  Also, it is possible to add code to the parser's constructors using
 +  "%code init" and "%define init_throws".
 +
 +** C++ skeleton improvements
 +
 +  The C++ parser features a syntax_error exception, which can be
 +  thrown from the scanner or from user rules to raise syntax errors.
 +  This facilitates reporting errors caught in sub-functions (e.g.,
 +  rejecting too large integral literals from a conversion function
 +  used by the scanner, or rejecting invalid combinations from a
 +  factory invoked by the user actions).
 +
 +** Variable api.tokens.prefix
 +
 +  The variable api.tokens.prefix changes the way tokens are identified in
 +  the generated files.  This is especially useful to avoid collisions
 +  with identifiers in the target language.  For instance
 +
 +    %token FILE for ERROR
 +    %define api.tokens.prefix "TOK_"
 +    %%
 +    start: FILE for ERROR;
 +
 +  will generate the definition of the symbols TOK_FILE, TOK_for, and
 +  TOK_ERROR in the generated sources.  In particular, the scanner must
 +  use these prefixed token names, although the grammar itself still
 +  uses the short names (as in the sample rule given above).
 +
 +** Variable api.namespace
 +
 +  The "namespace" variable is renamed "api.namespace".  Backward
 +  compatibility is ensured, but upgrading is recommended.
 +
 +** Variable parse.error
 +
 +  The variable error controls the verbosity of error messages.  The
 +  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
 +  run-time expressions.
 +
  * Noteworthy changes in release ?.? (????-??-??) [?]
  
+  Bison no longer executes user-specified M4 code when processing a grammar.
+ ** Future Changes
+   In addition to the removal of the features announced in Bison 2.6, the
+   next major release will remove the "Temporary hack for adding a semicolon
+   to the user action", as announced in the release 2.5.  Instead of:
+     exp: exp "+" exp { $$ = $1 + $3 };
+   write:
+     exp: exp "+" exp { $$ = $1 + $3; };
+ ** Bug fixes
+ *** Type names are now properly escaped.
+ *** glr.cc: set_debug_level and debug_level work as expected.
+ *** Stray @ or $ in actions
+   While Bison used to warn about stray $ or @ in action rules, it did not
+   for other actions such as printers, destructors, or initial actions.  It
+   now does.
+ ** Type names in actions
+   For consistency with rule actions, it is now possible to qualify $$ by a
+   type-name in destructors, printers, and initial actions.  For instance:
+     %printer { fprintf (yyo, "(%d, %f)", $<ival>$, $<fval>$); } <*> <>;
+   will display two values for each typed and untyped symbol (provided
+   that YYSTYPE has both "ival" and "fval" fields).
  
  * Noteworthy changes in release 2.6 (2012-07-19) [stable]
  
 -** Future Changes
 +** Future changes:
  
    The next major release of Bison will drop support for the following
    deprecated features.  Please report disagreements to bug-bison@gnu.org.
  
- *** K&C parsers
+ *** K&C parsers
  
    Support for generating parsers in K&R C will be removed.  Parsers
    generated for C support ISO C90, and are tested with ISO C99 and ISO C11
@@@ -1933,8 -1841,7 +1968,8 @@@ along with this program.  If not, see <
   LocalWords:  namespaces strerror const autoconfiguration Dconst Autoconf's FDL
   LocalWords:  Automake TMPDIR LESSEQ ylwrap endif yydebug YYTOKEN YYLSP ival hh
   LocalWords:  extern YYTOKENTYPE TOKENTYPE yytokentype tokentype STYPE lval pdf
 - LocalWords:  lang yyoutput dvi html ps POSIX lvalp llocp
 + LocalWords:  lang yyoutput dvi html ps POSIX lvalp llocp Wother nterm arg init
 + LocalWords:  TOK
  
  Local Variables:
  mode: outline
diff --combined THANKS
index c0c274cb448f9dccad3ddcb95d47c1f5eaa02e90,75037b1f0196c75af16e75e03ab84130f429008f..5e76b1d16d497975817955bb92ce24fcb2129a26
--- 1/THANKS
--- 2/THANKS
+++ b/THANKS
@@@ -13,6 -13,7 +13,7 @@@ Anthony Heading           ajrh@ajrh.ne
  Arnold Robbins            arnold@skeeve.com
  Art Haas                  ahaas@neosoft.com
  Baron Schwartz            baron@sequent.org
+ Ben Pfaff                 blp@cs.stanford.edu
  Benoit Perrot             benoit.perrot@epita.fr
  Bernd Kiefer              kiefer@dfki.de
  Bert Deknuydt             Bert.Deknuydt@esat.kuleuven.ac.be
@@@ -70,7 -71,6 +71,7 @@@ Matt Kraai                kraai@alumni.
  Matt Rosing               rosing@peakfive.com
  Michael Hayes             m.hayes@elec.canterbury.ac.nz
  Michael Raskin            7c6f434c@mail.ru
 +Michiel De Wilde          mdewilde.agilent@gmail.com
  Mickael Labau             labau_m@epita.fr
  Mike Castle               dalgoda@ix.netcom.com
  Neil Booth                NeilB@earthling.net
@@@ -88,7 -88,6 +89,7 @@@ Per Allansson             per@appgate.c
  Peter Fales               psfales@lucent.com
  Peter Hamorsky            hamo@upjs.sk
  Piotr Gackiewicz          gacek@intertel.com.pl
 +Quentin Hocquet           hocquet@gostai.com
  Quoc Peyrot               chojin@lrde.epita.fr
  R Blake                   blakers@mac.com
  Raja R Harinath           harinath@cs.umn.edu
diff --combined TODO
index dfd6cfe3aaed6b173ff29f119b3f18ff3b6c21aa,4f628a20aa4f3577ffc1a004030587c4395e17a8..6457742526d82946cfa5954ea2a2bdf6e890f64f
--- 1/TODO
--- 2/TODO
+++ b/TODO
@@@ -1,7 -1,14 +1,11 @@@
  * Short term
++** scan-code.l
++Avoid variables for format strings, as then GCC cannot check them.
++show_sub_messages should call show_sub_message.
++
  ** Variable names.
  What should we name `variant' and `lex_symbol'?
  
 -** Use b4_symbol in all the skeleton
 -Move its definition in the more standard places and deploy it in other
 -skeletons.  Then remove the older system, including the tables
 -generated by output.c
 -
 -** Update the documentation on gnu.org
 -
  ** Get rid of fake #lines [Bison: ...]
  Possibly as simple as checking whether the column number is nonnegative.
  
@@@ -32,6 -39,10 +36,6 @@@ as lr0.cc, why upper case
  Enhance bench.pl with %b to run different bisons.
  
  * Various
 -** Warnings
 -Warnings about type tags that are used in printer and dtors, but not
 -for symbols?
 -
  ** YYERRCODE
  Defined to 256, but not used, not documented.  Probably the token
  number for the error token, which POSIX wants to be 256, but which
@@@ -77,6 -88,9 +81,6 @@@ so both 256 and 257 are "mysterious"
    "\"end of command\"", "error", "$undefined", "\"=\"", "\"break\"",
  
  
 -** YYFAIL
 -It is seems to be *really* obsolete now, shall we remove it?
 -
  ** yychar == yyempty_
  The code in yyerrlab reads:
  
diff --combined configure.ac
index cf42d2c67a297de499bcb2b93060ff9b06298cd4,b9d2ea69798e4fa9fd01b665eea6c63a2e7e55e2..328d9294b7af1ff539466ccb1ee8b1ef934c9db4
@@@ -45,9 -45,7 +45,9 @@@ AC_CONFIG_MACRO_DIR([m4]
  # releases, we want to be able run make dist without being required to
  # add a bogus NEWS entry.  In that case, the version string
  # automatically contains a dash, which we also let disable gnits.
 -AM_INIT_AUTOMAKE([1.11.1 dist-xz silent-rules]
 +AM_INIT_AUTOMAKE([1.11.1 dist-xz nostdinc
 +                 color-tests parallel-tests
 +                 silent-rules]
                   m4_bmatch(m4_defn([AC_PACKAGE_VERSION]), [[-_]],
                             [gnu], [gnits]))
  AM_SILENT_RULES([yes])
@@@ -73,7 -71,6 +73,7 @@@ if test "$enable_gcc_warnings" = yes; t
    warn_c='-Wbad-function-cast -Wmissing-declarations -Wmissing-prototypes
      -Wshadow -Wstrict-prototypes'
    warn_cxx='-Wnoexcept'
 +
    AC_LANG_PUSH([C])
    for i in $warn_common $warn_c;
    do
@@@ -90,7 -87,7 +90,7 @@@
    do
      gl_WARN_ADD([$i], [WARN_CXXFLAGS])
    done
 -  gl_WARN_ADD([ -Wzero-as-null-pointer-constant], [WARN_CXXFLAGS],
 +  gl_WARN_ADD([-Wzero-as-null-pointer-constant], [WARN_CXXFLAGS],
                [AC_LANG_PROGRAM([], [nullptr])])
    gl_WARN_ADD([-Werror], [WERROR_CXXFLAGS])
    # Warnings for the test suite only.
@@@ -108,8 -105,8 +108,8 @@@ AC_ARG_ENABLE([yacc]
    , [enable_yacc=yes])
  case $enable_yacc in
  yes)
 -  YACC_SCRIPT=yacc
 -  YACC_LIBRARY=liby.a;;
 +  YACC_SCRIPT=src/yacc
 +  YACC_LIBRARY=lib/liby.a;;
  *)
    YACC_SCRIPT=
    YACC_LIBRARY=;;
@@@ -126,10 -123,6 +126,10 @@@ AC_PROG_GNU_M
  AC_DEFINE_UNQUOTED([M4], ["$M4"], [Define to the GNU M4 executable name.])
  AC_DEFINE_UNQUOTED([M4_GNU_OPTION], ["$M4_GNU"], [Define to "-g" if GNU M4
  supports -g, otherwise to "".])
 +AC_PATH_PROG([PERL], [perl])
 +if test -z "$PERL"; then
 +   AC_MSG_ERROR([perl not found])
 +fi
  AM_MISSING_PROG([HELP2MAN], [help2man])
  AC_PATH_PROG([XSLTPROC], [xsltproc])
  AC_SUBST([XSLTPROC])
@@@ -167,7 -160,7 +167,7 @@@ AC_CONFIG_FILES([etc/bench.pl], [chmod 
  
  # Initialize the test suite.
  AC_CONFIG_TESTDIR(tests)
 -AC_CONFIG_FILES([tests/Makefile tests/atlocal])
 +AC_CONFIG_FILES([tests/atlocal])
  AC_CONFIG_FILES([tests/bison], [chmod +x tests/bison])
  AC_CHECK_PROGS([VALGRIND], [valgrind])
  case $VALGRIND:$host_os in
      # VALGRIND+=' --suppressions=$(abs_top_srcdir)/build-aux/darwin11.4.0.valgrind'
      VALGRIND=;;
    *:*)
-     AC_SUBST([VALGRIND_PREBISON], [$VALGRIND -q]);;
+     AC_SUBST([VALGRIND_PREBISON], ["$VALGRIND -q"]);;
  esac
  
  AM_MISSING_PROG([AUTOM4TE], [autom4te])
  # Needed by tests/atlocal.in.
  AC_SUBST([GCC])
  
 -gt_JAVACOMP([1.3])
 +gt_JAVACOMP([1.3], [1.4])
  gt_JAVAEXEC
  
 +# We use gnulib, but from lib/local.mk instead of lib/Makefile.am.
 +# So prefix paths with lib/.  See also etc/prefix-gnulib-mk.
 +gl_LIBOBJS=`echo "$gl_LIBOBJS" | sed -e 's, , lib/,g'`
 +# Listing the names of the variables to prefix is error-prone.
 +# Rather, adjust all the AC_SUBST variables whose name ends in '_H',
 +# and whose content ends in '.h'.
 +for ac_var in $ac_subst_vars
 +do
 +  eval "ac_val=\$$ac_var"
 +  case $ac_var=$ac_val in
 +    (*_H=*.h) eval "$ac_var=lib/\$$ac_var";;
 +  esac
 +done
  AC_CONFIG_FILES([Makefile
 -               build-aux/Makefile
 -               po/Makefile.in
 -               data/Makefile
 -               etc/Makefile
 -               examples/Makefile
 -                  examples/calc++/Makefile
 -               lib/Makefile src/Makefile
 -               doc/Makefile
 -                 doc/yacc.1])
 +                 po/Makefile.in
 +                 doc/yacc.1])
  AC_OUTPUT
diff --combined data/bison.m4
index 1db75a8e653bb0dd47eefd9935dee36a84681b7f,fac86f2a0132f8e0d67507dc0e77671023f3a7f2..f2126ef40b0fb081e0ea44df332757c2d953246c
  ## Identification.  ##
  ## ---------------- ##
  
 -# b4_copyright(TITLE, YEARS)
 -# --------------------------
 +# b4_copyright(TITLE, [YEARS])
 +# ----------------------------
 +# If YEARS are not defined, use b4_copyright_years.
  m4_define([b4_copyright],
  [b4_comment([A Bison parser, made by GNU Bison b4_version.])
  
  b4_comment([$1
  
 -m4_text_wrap([Copyright (C) $2 Free Software Foundation, Inc.], [   ])
 +]m4_dquote(m4_text_wrap([Copyright (C)
 +]m4_ifval([$2], [[$2]], [m4_defn([b4_copyright_years])])[
 +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
@@@ -197,87 -194,6 +197,87 @@@ m4_define([b4_ints_in]
  [m4_eval([$3 <= $1 && $1 <= $4 && $3 <= $2 && $2 <= $4])])
  
  
 +# b4_subtract(LHS, RHS)
 +# ---------------------
 +# Evaluate LHS - RHS if they are integer literals, otherwise expand
 +# to (LHS) - (RHS).
 +m4_define([b4_subtract],
 +[m4_bmatch([$1$2], [^[0123456789]*$],
 +           [m4_eval([$1 - $2])],
 +           [($1) - ($2)])])
 +
 +# b4_args(ARG1, ...)
 +# _b4_args(ARG1, ...)
 +# -------------------
 +# Join with comma, skipping empty arguments.
 +# b4_args calls itself recursively until it sees the first non-empty
 +# argument, then calls _b4_args which prepends each non-empty argument
 +# with a comma.
 +m4_define([b4_args],
 +[m4_if([$#$1],
 +       [1], [],
 +       [m4_ifval([$1],
 +                 [$1[]_$0(m4_shift($@))],
 +                 [$0(m4_shift($@))])])])
 +
 +# _b4_args(ARGS1, ...)
 +# --------------------
 +m4_define([_b4_args],
 +[m4_if([$#$1],
 +       [1], [],
 +       [m4_ifval([$1], [, $1])[]$0(m4_shift($@))])])
 +
 +
 +
 +
 +# b4_integral_parser_tables_map(MACRO)
 +# -------------------------------------
 +# Map MACRO on all the integral tables.  MACRO is expected to have
 +# the signature MACRO(TABLE-NAME, CONTENT, COMMENT).
 +m4_define([b4_integral_parser_tables_map],
 +[$1([pact], [b4_pact],
 +    [[YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
 +STATE-NUM.]])
 +
 +$1([defact], [b4_defact],
 +   [[YYDEFACT[S] -- default reduction number in state S.  Performed when
 +YYTABLE does not specify something else to do.  Zero means the default
 +is an error.]])
 +
 +$1([pgoto], [b4_pgoto], [[YYPGOTO[NTERM-NUM].]])
 +
 +$1([defgoto], [b4_defgoto], [[YYDEFGOTO[NTERM-NUM].]])
 +
 +$1([table], [b4_table],
 +   [[YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
 +positive, shift that token.  If negative, reduce the rule which
 +number is the opposite.  If YYTABLE_NINF, syntax error.]])
 +
 +$1([check], [b4_check])
 +
 +$1([stos], [b4_stos],
 +   [[STOS_[STATE-NUM] -- The (internal number of the) accessing
 +symbol of state STATE-NUM.]])
 +
 +$1([r1], [b4_r1],
 +   [[YYR1[YYN] -- Symbol number of symbol that rule YYN derives.]])
 +
 +$1([r2], [b4_r2],
 +   [[YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.]])
 +])
 +
 +
 +# b4_parser_tables_declare
 +# b4_parser_tables_define
 +# ------------------------
 +# Define/declare the (deterministic) parser tables.
 +m4_define([b4_parser_tables_declare],
 +[b4_integral_parser_tables_map([b4_integral_parser_table_declare])])
 +
 +m4_define([b4_parser_tables_define],
 +[b4_integral_parser_tables_map([b4_integral_parser_table_define])])
 +
 +
  
  ## ------------------ ##
  ## Decoding options.  ##
  m4_define([b4_flag_if],
  [m4_case(b4_$1_flag,
           [0], [$3],
 -       [1], [$2],
 -       [m4_fatal([invalid $1 value: ]$1)])])
 +         [1], [$2],
 +         [m4_fatal([invalid $1 value: ]$1)])])
  
  
  # b4_define_flag_if(FLAG)
@@@ -316,166 -232,15 +316,164 @@@ m4_define([b4_$3_if]
  # -----------------------------
  # Expand IF-TRUE, if FLAG is true, IF-FALSE otherwise.
  b4_define_flag_if([defines])            # Whether headers are requested.
 -b4_define_flag_if([error_verbose])      # Whether error are verbose.
  b4_define_flag_if([glr])                # Whether a GLR parser is requested.
 -b4_define_flag_if([locations])          # Whether locations are tracked.
  b4_define_flag_if([nondeterministic])   # Whether conflicts should be handled.
  b4_define_flag_if([token_table])        # Whether yytoken_table is demanded.
  b4_define_flag_if([yacc])               # Whether POSIX Yacc is emulated.
  
 -# yytoken_table is needed to support verbose errors.
 -b4_error_verbose_if([m4_define([b4_token_table_flag], [1])])
 +
 +## --------- ##
 +## Symbols.  ##
 +## --------- ##
 +
 +# In order to unify the handling of the various aspects of symbols
 +# (tag, type_name, whether terminal, etc.), bison.exe defines one
 +# macro per (token, field), where field can has_id, id, etc.: see
 +# src/output.c:prepare_symbols_definitions().
 +#
 +# The following macros provide access to these values.
 +
 +# b4_symbol_(NUM, FIELD)
 +# ----------------------
 +# Recover a FIELD about symbol #NUM.  Thanks to m4_indir, fails if
 +# undefined.
 +m4_define([b4_symbol_],
 +[m4_indir([b4_symbol($1, $2)])])
 +
 +
 +# b4_symbol(NUM, FIELD)
 +# ---------------------
 +# Recover a FIELD about symbol #NUM.  Thanks to m4_indir, fails if
 +# undefined.  If FIELD = id, prepend the prefix.
 +m4_define([b4_symbol],
 +[m4_case([$2],
 +         [id],    [m4_do([b4_percent_define_get([api.tokens.prefix])],
 +                         [b4_symbol_([$1], [id])])],
 +         [b4_symbol_($@)])])
 +
 +
 +# b4_symbol_if(NUM, FIELD, IF-TRUE, IF-FALSE)
 +# -------------------------------------------
 +# If FIELD about symbol #NUM is 1 expand IF-TRUE, if is 0, expand IF-FALSE.
 +# Otherwise an error.
 +m4_define([b4_symbol_if],
 +[m4_case(b4_symbol([$1], [$2]),
 +         [1], [$3],
 +         [0], [$4],
 +         [m4_fatal([$0: field $2 of $1 is not a Boolean:] b4_symbol([$1], [$2]))])])
 +
 +
 +# b4_symbol_action_location(SYMBOL-NUM, KIND)
 +# -------------------------------------------
 +# Report the location of the KIND action as FILE:LINE.
 +m4_define([b4_symbol_action_location],
 +[b4_symbol([$1], [$2_file]):b4_syncline([b4_symbol([$1], [$2_line])])])
 +
 +
 +# b4_symbol_action(SYMBOL-NUM, KIND)
 +# ----------------------------------
 +# Run the action KIND (destructor or printer) for SYMBOL-NUM.
 +# Same as in C, but using references instead of pointers.
 +m4_define([b4_symbol_action],
 +[b4_symbol_if([$1], [has_$2],
- [m4_pushdef([b4_dollar_dollar],
-     [b4_symbol_value([(*yyvaluep)],
-                      b4_symbol_if([$1], [has_type],
-                                   [b4_symbol([$1], [type])]))])dnl
- m4_pushdef([b4_at_dollar], [(*yylocationp)])dnl
++[b4_dollar_pushdef([(*yyvaluep)],
++                   b4_symbol_if([$1], [has_type],
++                                [m4_dquote(b4_symbol([$1], [type]))]),
++                   [(*yylocationp)])dnl
 +      b4_symbol_case_([$1])[]dnl
 +b4_syncline([b4_symbol([$1], [$2_line])], ["b4_symbol([$1], [$2_file])"])
 +        b4_symbol([$1], [$2])
 +b4_syncline([@oline@], [@ofile@])
 +        break;
 +
- m4_popdef([b4_at_dollar])dnl
- m4_popdef([b4_dollar_dollar])dnl
++b4_dollar_popdef[]dnl
 +])])
 +
 +
 +# b4_symbol_destructor(SYMBOL-NUM)
 +# b4_symbol_printer(SYMBOL-NUM)
 +# --------------------------------
 +m4_define([b4_symbol_destructor], [b4_symbol_action([$1], [destructor])])
 +m4_define([b4_symbol_printer],    [b4_symbol_action([$1], [printer])])
 +
 +
 +# b4_symbol_case_(SYMBOL-NUM)
 +# ---------------------------
 +# Issue a "case NUM" for SYMBOL-NUM.
 +m4_define([b4_symbol_case_],
 +[      case b4_symbol([$1], [number]): // b4_symbol([$1], [tag])
 +])
 +
 +
 +# b4_symbol_foreach(MACRO)
 +# ------------------------
 +# Invoke MACRO(SYMBOL-NUM) for each SYMBOL-NUM.
 +m4_define([b4_symbol_foreach],
 +          [m4_map([$1], m4_defn([b4_symbol_numbers]))])
 +
 +# b4_symbol_map(MACRO)
 +# --------------------
 +# Return a list (possibly empty elements) of MACRO invoked for each
 +# SYMBOL-NUM.
 +m4_define([b4_symbol_map],
 +[m4_map_args_sep([$1(], [)], [,], b4_symbol_numbers)])
 +
 +
 +# b4_token_visible_if(NUM, IF-TRUE, IF-FALSE)
 +# -------------------------------------------
 +# Whether NUM denotes a token that has an exported definition (i.e.,
 +# shows in enum yytokentype).
 +m4_define([b4_token_visible_if],
 +[b4_symbol_if([$1], [is_token],
 +              [b4_symbol_if([$1], [has_id], [$2], [$3])],
 +              [$3])])
 +
 +# b4_token_has_definition(NUM)
 +# ----------------------------
 +# 1 if NUM is visible, nothing otherwise.
 +m4_define([b4_token_has_definition],
 +[b4_token_visible_if([$1], [1])])
 +
 +# b4_any_token_visible_if([IF-TRUE], [IF-FALSE])
 +# ----------------------------------------------
 +# Whether there is a token that needs to be defined.
 +m4_define([b4_any_token_visible_if],
 +[m4_ifval(b4_symbol_foreach([b4_token_has_definition]),
 +          [$1], [$2])])
 +
 +
 +# b4_token_format(FORMAT, NUM)
 +# ----------------------------
 +m4_define([b4_token_format],
 +[b4_token_visible_if([$2],
 +[m4_quote(m4_format([$1],
 +                     [b4_symbol([$2], [id])],
 +                     [b4_symbol([$2], [user_number])]))])])
 +
 +
 +## ------- ##
 +## Types.  ##
 +## ------- ##
 +
 +# b4_type_action_(NUMS)
 +# ---------------------
 +# Run actions for the symbol NUMS that all have the same type-name.
 +# Skip NUMS that have no type-name.
 +m4_define([b4_type_action_],
 +[b4_symbol_if([$1], [has_type],
 +[m4_map([b4_symbol_case_], [$@])[]dnl
 +        b4_dollar_dollar([b4_symbol([$1], [number])],
 +                         [b4_symbol([$1], [tag])],
 +                         [b4_symbol([$1], [type])]);
 +        break;
 +
 +])])
 +
 +# b4_type_foreach(MACRO)
 +# ----------------------
 +# Invoke MACRO(SYMBOL-NUMS) for each set of SYMBOL-NUMS for each type set.
 +m4_define([b4_type_foreach],
 +          [m4_map([$1], m4_defn([b4_type_names]))])
  
  
  
@@@ -584,6 -349,7 +582,6 @@@ m4_popdef([b4_end])dn
  
  
  
 -
  ## --------------------- ##
  ## b4_percent_define_*.  ##
  ## --------------------- ##
@@@ -613,6 -379,7 +611,6 @@@ m4_ifdef([b4_percent_define(]$1[)]
           [m4_indir([b4_percent_define(]$1[)])],
           [$2])])
  
 -
  # b4_percent_define_get_loc(VARIABLE)
  # -----------------------------------
  # Mimic muscle_percent_define_get_loc in ../src/muscle-tab.h exactly.  That is,
@@@ -661,14 -428,8 +659,14 @@@ m4_define([b4_percent_define_get_syncli
  #   b4_percent_define_ifdef([[foo]], [[it's defined]], [[it's undefined]])
  m4_define([b4_percent_define_ifdef],
  [m4_ifdef([b4_percent_define(]$1[)],
 -        [m4_define([b4_percent_define_bison_variables(]$1[)])$2],
 -        [$3])])
 +          [b4_percent_define_use([$1])$2],
 +          [$3])])
 +
 +
 +## --------- ##
 +## Options.  ##
 +## --------- ##
 +
  
  # b4_percent_define_flag_if(VARIABLE, IF-TRUE, [IF-FALSE])
  # --------------------------------------------------------
@@@ -693,7 -454,6 +691,7 @@@ m4_define([b4_percent_define_flag_if]
                             [[b4_percent_define_flag_if($1)]])])],
    [b4_fatal([[b4_percent_define_flag_if: undefined %%define variable '%s']], [$1])])])
  
 +
  # b4_percent_define_default(VARIABLE, DEFAULT)
  # --------------------------------------------
  # Mimic muscle_percent_define_default in ../src/muscle-tab.h exactly.  That is,
@@@ -712,20 -472,6 +710,20 @@@ m4_define([b4_percent_define_default]
                          [[<skeleton default value>:-1.-1]]]])dnl
              m4_define([b4_percent_define_syncline(]$1[)], [[]])])])
  
 +
 +# b4_percent_define_if_define(VARIABLE)
 +# -------------------------------------
 +# Define b4_VARIABLE_if that executes its $1 or $2 depending whether
 +# VARIABLE was %defined.  The characters `.' and `-' in VARIABLE are mapped
 +# to `_'.
 +m4_define([b4_percent_define_if_define_],
 +[m4_define(m4_bpatsubst([b4_$1_if], [[-.]], [_]),
 +           [b4_percent_define_flag_if([$1], [$2], [$3])])])
 +m4_define([b4_percent_define_if_define],
 +[b4_percent_define_default([[$1]], [[false]])
 +b4_percent_define_if_define_([$1], $[1], $[2])])
 +
 +
  # b4_percent_define_check_values(VALUES)
  # --------------------------------------
  # Mimic muscle_percent_define_check_values in ../src/muscle-tab.h exactly
@@@ -797,45 -543,7 +795,45 @@@ m4_popdef([b4_macro_name])]
  m4_define([b4_percent_code_ifdef],
  [m4_ifdef([b4_percent_code(]$1[)],
            [m4_ifval([$1], [m4_define([b4_percent_code_bison_qualifiers(]$1[)])])$2],
 -        [$3])])
 +          [$3])])
 +
 +
 +## ------------------ ##
 +## Common variables.  ##
 +## ------------------ ##
 +
 +# Default values for %define.
 +# ---------------------------
 +# If the api.tokens.prefix, it is empty.
 +m4_percent_define_default([[api.tokens.prefix]], [[]])
 +
 +# b4_parse_assert_if([IF-ASSERTIONS-ARE-USED], [IF-NOT])
 +# b4_parse_trace_if([IF-DEBUG-TRACES-ARE-ENABLED], [IF-NOT])
 +# b4_lex_symbol_if([IF-YYLEX-RETURNS-A-COMPLETE-SYMBOL], [IF-NOT])
 +# b4_variant_if([IF-VARIANT-ARE-USED], [IF-NOT])
 +# ----------------------------------------------
 +b4_percent_define_if_define([lex_symbol])
 +b4_percent_define_if_define([locations])     # Whether locations are tracked.
 +b4_percent_define_if_define([parse.assert])
 +b4_percent_define_if_define([parse.trace])
 +b4_percent_define_if_define([variant])
 +
 +
 +# b4_error_verbose_if([IF-ERRORS-ARE-VERBOSE], [IF-NOT])
 +# ------------------------------------------------------
 +# Map %define parse.error "(simple|verbose)" to b4_error_verbose_if and
 +# b4_error_verbose_flag.
 +b4_percent_define_default([[parse.error]], [[simple]])
 +b4_percent_define_check_values([[[[parse.error]],
 +                                 [[simple]], [[verbose]]]])
 +m4_define([b4_error_verbose_flag],
 +          [m4_case(b4_percent_define_get([[parse.error]]),
 +                   [simple],  [[0]],
 +                   [verbose], [[1]])])
 +b4_define_flag_if([error_verbose])
 +
 +# yytoken_table is needed to support verbose errors.
 +b4_error_verbose_if([m4_define([b4_token_table_flag], [1])])
  
  
  ## ----------------------------------------------------------- ##
diff --combined data/c-like.m4
index 0000000000000000000000000000000000000000,c2abce7e1df55e63b97579642c3f79cf1bafdbc6..732d18d4c1c82d04a76ac4e3e06382ceffb6bba2
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,44 +1,43 @@@
 -[m4_if([$2], [[]],
 -       [m4_ifval([$3], [($1.$3)],
 -                 [$1])],
 -       [($1.$2)])])
+                                                             -*- Autoconf -*-
+ # Common code for C-like languages (C, C++, Java, etc.)
+ # Copyright (C) 2012 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
+ # the Free Software Foundation, either version 3 of the License, or
+ # (at your option) any later version.
+ #
+ # This program is distributed in the hope that it will be useful,
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ # GNU General Public License for more details.
+ #
+ # You should have received a copy of the GNU General Public License
+ # along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ # b4_dollar_dollar_(VALUE, FIELD, DEFAULT-FIELD)
+ # ----------------------------------------------
+ # If FIELD (or DEFAULT-FIELD) is non-null, return "VALUE.FIELD",
+ # otherwise just VALUE.  Be sure to pass "(VALUE)" is VALUE is a
+ # pointer.
+ m4_define([b4_dollar_dollar_],
++[b4_symbol_value([$1],
++                 m4_if([$2], [[]],
++                       [[$3]], [[$2]]))])
+ # b4_dollar_pushdef(VALUE-POINTER, DEFAULT-FIELD, LOCATION)
+ # b4_dollar_popdef
+ # ---------------------------------------------------------
+ # Define b4_dollar_dollar for VALUE and DEFAULT-FIELD,
+ # and b4_at_dollar for LOCATION.
+ m4_define([b4_dollar_pushdef],
+ [m4_pushdef([b4_dollar_dollar],
+             [b4_dollar_dollar_([$1], m4_dquote($][1), [$2])])dnl
+ m4_pushdef([b4_at_dollar], [$3])dnl
+ ])
+ m4_define([b4_dollar_popdef],
+ [m4_popdef([b4_at_dollar])dnl
+ m4_popdef([b4_dollar_dollar])dnl
+ ])
diff --combined data/c.m4
index b8659eb41421242f6fc18540619db55d453ac82e,45468e3cac1305dbd5f398f8467978745c13e2d8..a07422d1eba14282863218e40024c96bef0f2f9d
+++ b/data/c.m4
@@@ -17,6 -17,7 +17,7 @@@
  # You should have received a copy of the GNU General Public License
  # along with this program.  If not, see <http://www.gnu.org/licenses/>.
  
+ m4_include(b4_pkgdatadir/[c-like.m4])
  
  # b4_tocpp(STRING)
  # ----------------
@@@ -48,34 -49,11 +49,34 @@@ m4_define([b4_cpp_guard_close]
  ## Identification.  ##
  ## ---------------- ##
  
 -# b4_comment(TEXT)
 -# ----------------
 -m4_define([b4_comment], [/* m4_bpatsubst([$1], [
 -], [
 -   ])  */])
 +# b4_comment_(TEXT, OPEN, CONTINUE, END)
 +# -------------------------------------
 +# Put TEXT in comment.  Avoid trailing spaces: don't indent empty lines.
 +# Avoid adding indentation to the first line, as the indentation comes
 +# from OPEN.  That's why we don't patsubst([$1], [^\(.\)], [   \1]).
 +#
 +# Prefix all the output lines with PREFIX.
 +m4_define([b4_comment_], [$2[]m4_bpatsubst([$1], [
 +\(.\)], [
 +$3\1])$4])
 +
 +
 +# b4_c_comment(TEXT, [PREFIX])
 +# ----------------------------
 +# Put TEXT in comment.  Avoid trailing spaces: don't indent empty lines.
 +# Avoid adding indentation to the first line, as the indentation comes
 +# from "/*".  That's why we don't patsubst([$1], [^\(.\)], [   \1]).
 +#
 +# Prefix all the output lines with PREFIX.
 +m4_define([b4_c_comment],
 +[b4_comment_([$1], [$2/* ], [$2   ], [$2  */])])
 +
 +
 +# b4_comment(TEXT, [PREFIX])
 +# --------------------------
 +# By default, C comments.
 +m4_define([b4_comment], [b4_c_comment($@)])
 +
  
  # b4_identification
  # -----------------
@@@ -157,13 -135,11 +158,13 @@@ m4_popdef([$2])dn
  m4_popdef([$1])dnl
  ])])
  
 -# b4_parse_param_use
 -# ------------------
 -# `YYUSE' all the parse-params.
 +# b4_parse_param_use([VAL], [LOC])
 +# --------------------------------
 +# `YYUSE' VAL, LOC if locations are enabled, and all the parse-params.
  m4_define([b4_parse_param_use],
 -[b4_parse_param_for([Decl], [Formal], [  YYUSE (Formal);
 +[m4_ifvaln([$1], [  YYUSE([$1]);])dnl
 +b4_locations_if([m4_ifvaln([$2], [  YYUSE ([$2]);])])dnl
 +b4_parse_param_for([Decl], [Formal], [  YYUSE (Formal);
  ])dnl
  ])
  
@@@ -185,7 -161,7 +186,7 @@@ m4_define([b4_int_type]
  
         m4_eval([0 <= $1]),                [1], [unsigned int],
  
 -                                             [int])])
 +                                               [int])])
  
  
  # b4_int_type_for(NAME)
@@@ -234,85 -210,63 +235,85 @@@ m4_define([b4_null_define]
  # Return a null pointer constant.
  m4_define([b4_null], [YY_NULL])
  
 +# b4_integral_parser_table_define(TABLE-NAME, CONTENT, COMMENT)
 +# -------------------------------------------------------------
 +# Define "yy<TABLE-NAME>" which contents is CONTENT.
 +m4_define([b4_integral_parser_table_define],
 +[m4_ifvaln([$3], [b4_c_comment([$3], [  ])])dnl
 +static const b4_int_type_for([$2]) yy$1[[]] =
 +{
 +  $2
 +};dnl
 +])
  
  
  ## ------------------------- ##
  ## Assigning token numbers.  ##
  ## ------------------------- ##
  
 -# b4_token_define(TOKEN-NAME, TOKEN-NUMBER)
 -# -----------------------------------------
 +# b4_token_define(TOKEN-NUM)
 +# --------------------------
  # Output the definition of this token as #define.
  m4_define([b4_token_define],
 -[#define $1 $2
 -])
 +[b4_token_format([#define %s %s], [$1])])
  
 -
 -# b4_token_defines(LIST-OF-PAIRS-TOKEN-NAME-TOKEN-NUMBER)
 -# -------------------------------------------------------
 -# Output the definition of the tokens (if there are) as #defines.
 +# b4_token_defines
 +# ----------------
 +# Output the definition of the tokens.
  m4_define([b4_token_defines],
 -[m4_if([$#$1], [1], [],
 -[/* Tokens.  */
 -m4_map([b4_token_define], [$@])])
 -])
 +[b4_any_token_visible_if([/* Tokens.  */
 +m4_join([
 +], b4_symbol_map([b4_token_define]))
 +])])
  
  
 -# b4_token_enum(TOKEN-NAME, TOKEN-NUMBER)
 -# ---------------------------------------
 +# b4_token_enum(TOKEN-NUM)
 +# ------------------------
  # Output the definition of this token as an enum.
  m4_define([b4_token_enum],
 -[$1 = $2])
 +[b4_token_format([%s = %s], [$1])])
  
  
 -# b4_token_enums(LIST-OF-PAIRS-TOKEN-NAME-TOKEN-NUMBER)
 -# -----------------------------------------------------
 +# b4_token_enums
 +# --------------
  # Output the definition of the tokens (if there are) as enums.
  m4_define([b4_token_enums],
 -[m4_if([$#$1], [1], [],
 -[[/* Tokens.  */
 +[b4_any_token_visible_if([[/* Tokens.  */
  #ifndef ]b4_api_PREFIX[TOKENTYPE
  # define ]b4_api_PREFIX[TOKENTYPE
 -   /* Put the tokens into the symbol table, so that GDB and other debuggers
 -      know about them.  */
 -   enum ]b4_api_prefix[tokentype {
 -]m4_map_sep([     b4_token_enum], [,
 -],
 -         [$@])[
 -   };
 +  /* Put the tokens into the symbol table, so that GDB and other debuggers
 +     know about them.  */
 +  enum ]b4_api_prefix[tokentype
 +  {
 +    ]m4_join([,
 +    ],
 +             b4_symbol_map([b4_token_enum]))[
 +  };
  #endif
  ]])])
  
  
 -# b4_token_enums_defines(LIST-OF-PAIRS-TOKEN-NAME-TOKEN-NUMBER)
 -# -------------------------------------------------------------
 -# Output the definition of the tokens (if there are any) as enums and, if POSIX
 -# Yacc is enabled, as #defines.
 +# b4_token_enums_defines
 +# ----------------------
 +# Output the definition of the tokens (if there are any) as enums and,
 +# if POSIX Yacc is enabled, as #defines.
  m4_define([b4_token_enums_defines],
 -[b4_token_enums($@)b4_yacc_if([b4_token_defines($@)], [])
 -])
 +[b4_token_enums[]b4_yacc_if([b4_token_defines])])
 +
 +
 +## ----------------- ##
 +## Semantic Values.  ##
 +## ----------------- ##
 +
 +
 +# b4_symbol_value(VAL, [TYPE])
 +# ----------------------------
 +# Given a semantic value VAL ($$, $1 etc.), extract its value of type
 +# TYPE if TYPE is given, otherwise just return VAL.  The result can be
 +# used safetly, it is put in parens to avoid nasty precedence issues.
 +# TYPE is *not* put in braces, provide some if needed.
 +m4_define([b4_symbol_value],
 +[($1[]m4_ifval([$2], [.$2]))])
  
  
  
@@@ -364,7 -318,7 +365,7 @@@ $1 (b4_c_ansi_formals(m4_shift2($@)))[]
  m4_define([b4_c_ansi_formals],
  [m4_if([$#], [0], [void],
         [$#$1], [1], [void],
 -             [m4_map_sep([b4_c_ansi_formal], [, ], [$@])])])
 +               [m4_map_sep([b4_c_ansi_formal], [, ], [$@])])])
  
  m4_define([b4_c_ansi_formal],
  [$1])
@@@ -385,9 -339,9 +386,9 @@@ m4_define([b4_c_knr_formal_name]
  # Output the K&R argument declarations.
  m4_define([b4_c_knr_formal_decls],
  [m4_map_sep([b4_c_knr_formal_decl],
 -          [
 +            [
  ],
 -          [$@])])
 +            [$@])])
  
  m4_define([b4_c_knr_formal_decl],
  [    $1;])
  # -----------------------------------------------------------
  # Declare the function NAME.
  m4_define([b4_c_function_decl],
 -[#if defined __STDC__ || defined __cplusplus
 +[#if b4_c_modern
  b4_c_ansi_function_decl($@)
  #else
  $2 $1 ();
@@@ -462,17 -416,25 +463,17 @@@ m4_define([b4_sync_start], [[#]line $1 
  m4_define([b4_case],
  [  case $1:
  $2
 +b4_syncline([@oline@], [@ofile@])
      break;])
  
 -# b4_symbol_actions(FILENAME, LINENO,
 -#                   SYMBOL-TAG, SYMBOL-NUM,
 -#                   SYMBOL-ACTION, SYMBOL-TYPENAME)
 -# -------------------------------------------------
 -# Issue the code for a symbol action (e.g., %printer).
 -#
 -# Define b4_dollar_dollar([TYPE-NAME]), and b4_at_dollar, which are
 -# invoked where $<TYPE-NAME>$ and @$ were specified by the user.
 -m4_define([b4_symbol_actions],
 -[b4_dollar_pushdef([(*yyvaluep)], [$6], [(*yylocationp)])dnl
 -      case $4: /* $3 */
 -b4_syncline([$2], [$1])
 -      $5;
 +
 +# b4_predicate_case(LABEL, CONDITIONS)
 +# ------------------------------------
 +m4_define([b4_predicate_case],
 +[  case $1:
 +    if (! ($2)) YYERROR;
  b4_syncline([@oline@], [@ofile@])
 -      break;
 -b4_dollar_popdef[]dnl
 -])
 +    break;])
  
  
  # b4_yydestruct_generate(FUNCTION-DECLARATOR)
@@@ -494,16 -456,20 +495,16 @@@ m4_define_default([b4_yydestruct_genera
  b4_locations_if(            [, [[YYLTYPE *yylocationp], [yylocationp]]])[]dnl
  m4_ifset([b4_parse_param], [, b4_parse_param]))[
  {
 -  YYUSE (yyvaluep);
 -]b4_locations_if([  YYUSE (yylocationp);
 -])dnl
 -b4_parse_param_use[]dnl
 -[
 -  if (!yymsg)
 +]b4_parse_param_use([yyvaluep], [yylocationp])dnl
 +[  if (!yymsg)
      yymsg = "Deleting";
    YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
  
    switch (yytype)
      {
 -]m4_map([b4_symbol_actions], m4_defn([b4_symbol_destructors]))[
 -      default:
 -      break;
 +]b4_symbol_foreach([b4_symbol_destructor])dnl
 +[      default:
 +        break;
      }
  }]dnl
  ])
@@@ -523,28 -489,30 +524,28 @@@ m4_define_default([b4_yy_symbol_print_g
  /*ARGSUSED*/
  ]$1([yy_symbol_value_print],
      [static void],
 -             [[FILE *yyoutput],                       [yyoutput]],
 -             [[int yytype],                           [yytype]],
 -             [[YYSTYPE const * const yyvaluep],       [yyvaluep]][]dnl
 +               [[FILE *yyoutput],                       [yyoutput]],
 +               [[int yytype],                           [yytype]],
 +               [[YYSTYPE const * const yyvaluep],       [yyvaluep]][]dnl
  b4_locations_if([, [[YYLTYPE const * const yylocationp], [yylocationp]]])[]dnl
  m4_ifset([b4_parse_param], [, b4_parse_param]))[
  {
    FILE *yyo = yyoutput;
 -  YYUSE (yyo);
 -  if (!yyvaluep)
 -    return;
 -]b4_locations_if([  YYUSE (yylocationp);
 -])dnl
 -b4_parse_param_use[]dnl
 -[# ifdef YYPRINT
 +]b4_parse_param_use([yyo], [yylocationp])dnl
 +[  if (!yyvaluep)
 +    return;]
 +dnl glr.c does not feature yytoknum.
 +m4_if(b4_skeleton, ["yacc.c"],
 +[[# ifdef YYPRINT
    if (yytype < YYNTOKENS)
      YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
 -# else
 -  YYUSE (yyoutput);
  # endif
 -  switch (yytype)
 +]])dnl
 +[  switch (yytype)
      {
 -]m4_map([b4_symbol_actions], m4_defn([b4_symbol_printers]))dnl
 +]b4_symbol_foreach([b4_symbol_printer])dnl
  [      default:
 -      break;
 +        break;
      }
  }
  
  
  ]$1([yy_symbol_print],
      [static void],
 -             [[FILE *yyoutput],                       [yyoutput]],
 -             [[int yytype],                           [yytype]],
 -             [[YYSTYPE const * const yyvaluep],       [yyvaluep]][]dnl
 +               [[FILE *yyoutput],                       [yyoutput]],
 +               [[int yytype],                           [yytype]],
 +               [[YYSTYPE const * const yyvaluep],       [yyvaluep]][]dnl
  b4_locations_if([, [[YYLTYPE const * const yylocationp], [yylocationp]]])[]dnl
  m4_ifset([b4_parse_param], [, b4_parse_param]))[
  {
@@@ -594,6 -562,7 +595,6 @@@ m4_define([b4_declare_yylstype]
  [m4_if(b4_tag_seen_flag, 0,
  [[typedef int ]b4_api_PREFIX[STYPE;
  # define ]b4_api_PREFIX[STYPE_IS_TRIVIAL 1]])])[
 -# define ]b4_api_prefix[stype ]b4_api_PREFIX[STYPE /* obsolescent; will be withdrawn */
  # define ]b4_api_PREFIX[STYPE_IS_DECLARED 1
  #endif]b4_locations_if([[
  
@@@ -605,6 -574,7 +606,6 @@@ typedef struct ]b4_api_PREFIX[LTYP
    int last_line;
    int last_column;
  } ]b4_api_PREFIX[LTYPE;
 -# define ]b4_api_prefix[ltype ]b4_api_PREFIX[LTYPE /* obsolescent; will be withdrawn */
  # define ]b4_api_PREFIX[LTYPE_IS_DECLARED 1
  # define ]b4_api_PREFIX[LTYPE_IS_TRIVIAL 1
  #endif]])
@@@ -619,17 -589,17 +620,17 @@@ m4_define([b4_YYDEBUG_define]
  [[/* Enabling traces.  */
  ]m4_if(b4_api_prefix, [yy],
  [[#ifndef YYDEBUG
 -# define YYDEBUG ]b4_debug_flag[
 +# define YYDEBUG ]b4_parse_trace_if([1], [0])[
  #endif]],
  [[#ifndef ]b4_api_PREFIX[DEBUG
  # if defined YYDEBUG
 -#  if YYDEBUG
 +#if YYDEBUG
  #   define ]b4_api_PREFIX[DEBUG 1
  #  else
  #   define ]b4_api_PREFIX[DEBUG 0
  #  endif
  # else /* ! defined YYDEBUG */
 -#  define ]b4_api_PREFIX[DEBUG ]b4_debug_flag[
 +#  define ]b4_api_PREFIX[DEBUG ]b4_parse_trace_if([1], [0])[
  # endif /* ! defined ]b4_api_PREFIX[DEBUG */
  #endif  /* ! defined ]b4_api_PREFIX[DEBUG */]])[]dnl
  ])
diff --combined data/glr.c
index d392622903a9f1e6197d4aed0a32bb8bc3f47600,08f6cd8d0db55dd4a6a6208566683b58ecd4e51b..935ee96a82fcbb016dc555638adcb25ff4202c86
@@@ -126,15 -126,7 +126,15 @@@ m4_define([b4_locuser_args]
  # --------------------
  # Expansion of $<TYPE>$.
  m4_define([b4_lhs_value],
 -[((*yyvalp)[]m4_ifval([$1], [.$1]))])
 +[b4_symbol_value([(*yyvalp)], [$1])])
 +
 +
 +# b4_rhs_data(RULE-LENGTH, NUM)
 +# -----------------------------
 +# Expand to the semantic stack place that contains value and location
 +# of symbol number NUM in a rule of length RULE-LENGTH.
 +m4_define([b4_rhs_data],
 +[((yyGLRStackItem const *)yyvsp)@{YYFILL (b4_subtract([$2], [$1]))@}.yystate])
  
  
  # b4_rhs_value(RULE-LENGTH, NUM, [TYPE])
  # Expansion of $<TYPE>NUM, where the current rule has RULE-LENGTH
  # symbols on RHS.
  m4_define([b4_rhs_value],
 -[(((yyGLRStackItem const *)yyvsp)@{YYFILL (($2) - ($1))@}.yystate.yysemantics.yysval[]m4_ifval([$3], [.$3]))])
 +[b4_symbol_value([b4_rhs_data([$1], [$2]).yysemantics.yysval], [$3])])
  
  
  
@@@ -162,7 -154,7 +162,7 @@@ m4_define([b4_lhs_location]
  # Expansion of @NUM, where the current rule has RULE-LENGTH symbols
  # on RHS.
  m4_define([b4_rhs_location],
 -[(((yyGLRStackItem const *)yyvsp)@{YYFILL (($2) - ($1))@}.yystate.yyloc)])
 +[(b4_rhs_data([$1], [$2]).yyloc)])
  
  
  ## -------------- ##
  m4_define([b4_shared_declarations],
  [b4_declare_yydebug[
  ]b4_percent_code_get([[requires]])[
 -]b4_token_enums(b4_tokens)[
 +]b4_token_enums[
  ]b4_declare_yylstype[
  ]b4_c_ansi_function_decl(b4_prefix[parse], [int], b4_parse_param)[
  ]b4_percent_code_get([[provides]])[]dnl
@@@ -220,14 -212,14 +220,14 @@@ b4_percent_code_get([[top]])
  ]b4_null_define[
  
  ]b4_defines_if([[#include "@basename(]b4_spec_defines_file[@)"]],
 -               [b4_shared_declarations])[
 +              [b4_shared_declarations])[
  
  /* Enabling verbose error messages.  */
  #ifdef YYERROR_VERBOSE
  # undef YYERROR_VERBOSE
  # define YYERROR_VERBOSE 1
  #else
 -# define YYERROR_VERBOSE ]b4_error_verbose_flag[
 +# define YYERROR_VERBOSE ]b4_error_verbose_if([1], [0])[
  #endif
  
  /* Default (constant) value used for initialization for null
@@@ -357,6 -349,19 +357,6 @@@ static const ]b4_int_type_for([b4_trans
  };
  
  #if ]b4_api_PREFIX[DEBUG
 -/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
 -   YYRHS.  */
 -static const ]b4_int_type_for([b4_prhs])[ yyprhs[] =
 -{
 -  ]b4_prhs[
 -};
 -
 -/* YYRHS -- A `-1'-separated list of the rules' RHS.  */
 -static const ]b4_int_type_for([b4_rhs])[ yyrhs[] =
 -{
 -  ]b4_rhs[
 -};
 -
  /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
  static const ]b4_int_type_for([b4_rline])[ yyrline[] =
  {
@@@ -373,10 -378,17 +373,10 @@@ static const char *const yytname[] 
  };
  #endif
  
 -/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 -static const ]b4_int_type_for([b4_r1])[ yyr1[] =
 -{
 -  ]b4_r1[
 -};
 +#define YYPACT_NINF ]b4_pact_ninf[
 +#define YYTABLE_NINF ]b4_table_ninf[
  
 -/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
 -static const ]b4_int_type_for([b4_r2])[ yyr2[] =
 -{
 -  ]b4_r2[
 -};
 +]b4_parser_tables_define[
  
  /* YYDPREC[RULE-NUM] -- Dynamic precedence of rule #RULE-NUM (0 if none).  */
  static const ]b4_int_type_for([b4_dprec])[ yydprec[] =
@@@ -390,11 -402,41 +390,11 @@@ static const ]b4_int_type_for([b4_merge
    ]b4_merger[
  };
  
 -/* YYDEFACT[S] -- default reduction number in state S.  Performed when
 -   YYTABLE doesn't specify something else to do.  Zero means the default
 -   is an error.  */
 -static const ]b4_int_type_for([b4_defact])[ yydefact[] =
 +/* YYIMMEDIATE[RULE-NUM] -- True iff rule #RULE-NUM is not to be deferred, as
 +   in the case of predicates.  */
 +static const yybool yyimmediate[] =
  {
 -  ]b4_defact[
 -};
 -
 -/* YYPDEFGOTO[NTERM-NUM].  */
 -static const ]b4_int_type_for([b4_defgoto])[ yydefgoto[] =
 -{
 -  ]b4_defgoto[
 -};
 -
 -/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
 -   STATE-NUM.  */
 -#define YYPACT_NINF ]b4_pact_ninf[
 -static const ]b4_int_type_for([b4_pact])[ yypact[] =
 -{
 -  ]b4_pact[
 -};
 -
 -/* YYPGOTO[NTERM-NUM].  */
 -static const ]b4_int_type_for([b4_pgoto])[ yypgoto[] =
 -{
 -  ]b4_pgoto[
 -};
 -
 -/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
 -   positive, shift that token.  If negative, reduce the rule which
 -   number is the opposite.  If YYTABLE_NINF, syntax error.  */
 -#define YYTABLE_NINF ]b4_table_ninf[
 -static const ]b4_int_type_for([b4_table])[ yytable[] =
 -{
 -  ]b4_table[
 +  ]b4_immediate[
  };
  
  /* YYCONFLP[YYPACT[STATE-NUM]] -- Pointer into YYCONFL of start of
@@@ -415,7 -457,19 +415,7 @@@ dnl We probably ought to introduce a ty
  {
    ]b4_conflicting_rules[
  };
 -
 -static const ]b4_int_type_for([b4_check])[ yycheck[] =
 -{
 -  ]b4_check[
 -};
 -
 -/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
 -   symbol of state STATE-NUM.  */
 -static const ]b4_int_type_for([b4_stos])[ yystos[] =
 -{
 -  ]b4_stos[
 -};
 -
 +\f
  /* Error token number */
  #define YYTERROR 1
  
@@@ -472,12 -526,9 +472,12 @@@ static const int YYEMPTY = -2
  
  typedef enum { yyok, yyaccept, yyabort, yyerr } YYRESULTTAG;
  
 -#define YYCHK(YYE)                                                           \
 -   do { YYRESULTTAG yyflag = YYE; if (yyflag != yyok) return yyflag; }       \
 -   while (YYID (0))
 +#define YYCHK(YYE)                              \
 +  do {                                          \
 +    YYRESULTTAG yychk_flag = YYE;               \
 +    if (yychk_flag != yyok)                     \
 +      return yychk_flag;                        \
 +  } while (YYID (0))
  
  #if ]b4_api_PREFIX[DEBUG
  
  # endif
  
  # define YYDPRINTF(Args)                        \
 -do {                                            \
 -  if (yydebug)                                  \
 -    YYFPRINTF Args;                             \
 -} while (YYID (0))
 +  do {                                          \
 +    if (yydebug)                                \
 +      YYFPRINTF Args;                           \
 +  } while (YYID (0))
  
  ]b4_yy_symbol_print_generate([b4_c_ansi_function_def])[
  
 -# define YY_SYMBOL_PRINT(Title, Type, Value, Location)          \
 -do {                                                            \
 -  if (yydebug)                                                  \
 -    {                                                           \
 -      YYFPRINTF (stderr, "%s ", Title);                         \
 -      yy_symbol_print (stderr, Type, Value]b4_locuser_args([Location])[);        \
 -      YYFPRINTF (stderr, "\n");                                 \
 -    }                                                           \
 -} while (YYID (0))
 +# define YY_SYMBOL_PRINT(Title, Type, Value, Location)                  \
 +  do {                                                                  \
 +    if (yydebug)                                                        \
 +      {                                                                 \
 +        YYFPRINTF (stderr, "%s ", Title);                               \
 +        yy_symbol_print (stderr, Type, Value]b4_locuser_args([Location])[);        \
 +        YYFPRINTF (stderr, "\n");                                       \
 +      }                                                                 \
 +  } while (YYID (0))
  
  /* Nonzero means print parse trace.  It is left uninitialized so that
     multiple parsers can coexist.  */
@@@ -538,7 -589,13 +538,7 @@@ int yydebug
  #define YYHEADROOM 2
  
  #ifndef YYSTACKEXPANDABLE
 -# if (! defined __cplusplus \
 -      || (]b4_locations_if([[defined ]b4_api_PREFIX[LTYPE_IS_TRIVIAL && ]b4_api_PREFIX[LTYPE_IS_TRIVIAL \
 -          && ]])[defined ]b4_api_PREFIX[STYPE_IS_TRIVIAL && ]b4_api_PREFIX[STYPE_IS_TRIVIAL))
  #  define YYSTACKEXPANDABLE 1
 -# else
 -#  define YYSTACKEXPANDABLE 0
 -# endif
  #endif
  
  #if YYSTACKEXPANDABLE
@@@ -635,7 -692,7 +635,7 @@@ typedef int yyStateNum
  typedef int yyRuleNum;
  
  /** Grammar symbol */
 -typedef short int yySymbol;
 +typedef int yySymbol;
  
  /** Item references, as in LALR(1) machine */
  typedef short int yyItemNum;
@@@ -656,7 -713,7 +656,7 @@@ struct yyGLRState 
    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
@@@ -768,16 -825,9 +768,16 @@@ yyfillin (yyGLRStackItem *yyvsp, int yy
    yyGLRState *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;]b4_locations_if([[
 +#if ]b4_api_PREFIX[DEBUG
 +      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 = YY_NULL;]b4_locations_if([[
        yyvsp[i].yystate.yyloc = s->yyloc;]])[
        s = yyvsp[i].yystate.yypred = s->yypred;
      }
@@@ -812,7 -862,7 +812,7 @@@ yyuserAction (yyRuleNum yyn, int yyrhsl
    yybool yynormal __attribute__ ((__unused__)) =
      (yystackp->yysplitPoint == YY_NULL);
    int yylow;
 -]b4_parse_param_use[]dnl
 +]b4_parse_param_use([yyvalp], [yylocp])dnl
  [# undef yyerrok
  # define yyerrok (yystackp->yyerrState = 0)
  # undef YYACCEPT
@@@ -915,7 -965,7 +915,7 @@@ yydestroyGLRState (char const *yymsg, y
      }
  }
  
 -/** Left-hand-side symbol for rule #RULE.  */
 +/** Left-hand-side symbol for rule #YYRULE.  */
  static inline yySymbol
  yylhsNonterm (yyRuleNum yyrule)
  {
  #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)
    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)
  {
   *    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 yyStateNum
  yyLRgotoState (yyStateNum yystate, yySymbol yylhs)
  {
 -  int yyr;
 -  yyr = yypgoto[yylhs - YYNTOKENS] + yystate;
 +  int yyr = yypgoto[yylhs - YYNTOKENS] + yystate;
    if (0 <= yyr && yyr <= YYLAST && yycheck[yyr] == yystate)
      return yytable[yyr];
    else
@@@ -998,10 -1049,9 +998,10 @@@ yyisErrorAction (int yyaction
  
                                  /* 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)
  }
  
  /** 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* rhs, yyRuleNum yyrule)
 +                     yyGLRState* yyrhs, yyRuleNum yyrule)
  {
    yySemanticOption* yynewOption =
      &yynewGLRStackItem (yystackp, yyfalse)->yyoption;
 -  yynewOption->yystate = rhs;
 +  yynewOption->yystate = yyrhs;
    yynewOption->yyrule = yyrule;
    if (yystackp->yytops.yylookaheadNeeds[yyk])
      {
  
                                  /* 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)
  {
@@@ -1067,8 -1117,8 +1067,8 @@@ static void yyfreeStateSet (yyGLRStateS
    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)
  {
  # 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
@@@ -1160,9 -1210,9 +1160,9 @@@ yyfreeGLRStack (yyGLRStack* yystackp
    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)
  {
      yystackp->yysplitPoint = yys;
  }
  
 -/** Invalidate stack #K in STACK.  */
 +/** Invalidate stack #YYK in *YYSTACKP.  */
  static inline void
  yymarkStackDeleted (yyGLRStack* yystackp, size_t yyk)
  {
    yystackp->yytops.yystates[yyk] = YY_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)
@@@ -1229,9 -1279,8 +1229,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,
    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
  yyglrShiftDefer (yyGLRStack* yystackp, size_t yyk, yyStateNum yylrState,
 -                 size_t yyposn, yyGLRState* rhs, yyRuleNum yyrule)
 +                 size_t yyposn, yyGLRState* yyrhs, yyRuleNum yyrule)
  {
    yyGLRState* yynewState = &yynewGLRStackItem (yystackp, yytrue)->yystate;
  
    yystackp->yytops.yystates[yyk] = yynewState;
  
    /* Invokes YY_RESERVE_GLRSTACK.  */
 -  yyaddDeferredAction (yystackp, yyk, yynewState, rhs, yyrule);
 +  yyaddDeferredAction (yystackp, yyk, yynewState, yyrhs, yyrule);
 +}
 +
 +#if !]b4_api_PREFIX[DEBUG
 +# 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* yyvsp, size_t yyk,
 +                 yyRuleNum yyrule]b4_user_formals[)
 +{
 +  int yynrhs = yyrhsLength (yyrule);]b4_locations_if([
 +  int yylow = 1;])[
 +  int yyi;
 +  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 (yyvsp, 1, -yynrhs);
 +  /* The symbols being reduced.  */
 +  for (yyi = 0; yyi < yynrhs; yyi++)
 +    {
 +      YYFPRINTF (stderr, "   $%d = ", yyi + 1);
 +      yy_symbol_print (stderr,
 +                       yystos[yyvsp[yyi - yynrhs + 1].yystate.yylrState],
 +                       &yyvsp[yyi - yynrhs + 1].yystate.yysemantics.yysval
 +                       ]b4_locations_if([, &]b4_rhs_location(yynrhs, yyi + 1))[]dnl
 +                       b4_user_args[);
 +      if (!yyvsp[yyi - yynrhs + 1].yystate.yyresolved)
 +        YYFPRINTF (stderr, " (unresolved)");
 +      YYFPRINTF (stderr, "\n");
 +    }
  }
 +#endif
  
 -/** Pop the symbols consumed by reduction #RULE from the top of stack
 - *  #K of STACK, and perform the appropriate semantic action on their
 +/** 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
 - *  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,
    if (yystackp->yysplitPoint == YY_NULL)
      {
        /* Standard special case: single stack.  */
 -      yyGLRStackItem* rhs = (yyGLRStackItem*) yystackp->yytops.yystates[yyk];
 +      yyGLRStackItem* yyrhs = (yyGLRStackItem*) yystackp->yytops.yystates[yyk];
        YYASSERT (yyk == 0);
        yystackp->yynextFree -= yynrhs;
        yystackp->yyspaceLeft += yynrhs;
        yystackp->yytops.yystates[0] = & yystackp->yynextFree[-1].yystate;
 -      return yyuserAction (yyrule, yynrhs, rhs, yystackp,
 +      YY_REDUCE_PRINT ((1, yyrhs, yyk, yyrule]b4_user_args[));
 +      return yyuserAction (yyrule, yynrhs, yyrhs, yystackp,
                             yyvalp]b4_locuser_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];
          }
        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,
                             yystackp, yyvalp]b4_locuser_args[);
      }
  }
  
 -#if !]b4_api_PREFIX[DEBUG
 -# 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,
 -                 YYSTYPE* yyvalp]b4_locuser_formals[)
 -{
 -  int yynrhs = yyrhsLength (yyrule);
 -  yybool yynormal __attribute__ ((__unused__)) =
 -    (yystackp->yysplitPoint == YY_NULL);
 -  yyGLRStackItem* yyvsp = (yyGLRStackItem*) yystackp->yytops.yystates[yyk];
 -  int yylow = 1;
 -  int yyi;
 -  YYUSE (yyvalp);]b4_locations_if([
 -  YYUSE (yylocp);])[
 -]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, yyrhs[yyprhs[yyrule] + yyi],
 -                       &]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
 - *  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,
 - *  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
@@@ -1377,18 -1429,11 +1377,18 @@@ yyglrReduce (yyGLRStack* yystackp, size
  
    if (yyforceEval || yystackp->yysplitPoint == YY_NULL)
      {
 +      YYRESULTTAG yyflag;
        YYSTYPE yysval;]b4_locations_if([
        YYLTYPE yyloc;])[
  
 -      YY_REDUCE_PRINT ((yystackp, yyk, yyrule, &yysval]b4_locuser_args([&yyloc])[));
 -      YYCHK (yydoAction (yystackp, yyk, yyrule, &yysval]b4_locuser_args([&yyloc])[));
 +      yyflag = yydoAction (yystackp, yyk, yyrule, &yysval]b4_locuser_args([&yyloc])[);
 +      if (yyflag == yyerr && yystackp->yysplitPoint != YY_NULL)
 +        {
 +          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,
        yyupdateSplit (yystackp, yys);
        yynewLRState = yyLRgotoState (yys->yylrState, yylhsNonterm (yyrule));
        YYDPRINTF ((stderr,
 -                  "Reduced stack %lu by rule #%d; action deferred.  Now in state %d.\n",
 +                  "Reduced stack %lu by rule #%d; action deferred.  "
 +                  "Now in state %d.\n",
                    (unsigned long int) yyk, yyrule - 1, yynewLRState));
        for (yyi = 0; yyi < yystackp->yytops.yysize; yyi += 1)
          if (yyi != yyk && yystackp->yytops.yystates[yyi] != YY_NULL)
@@@ -1483,7 -1527,7 +1483,7 @@@ yysplitStack (yyGLRStack* yystackp, siz
    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
@@@ -1505,8 -1549,8 +1505,8 @@@ yyidenticalOptions (yySemanticOption* y
      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)
  {
@@@ -1585,11 -1629,11 +1585,11 @@@ static YYRESULTTAG yyresolveValue (yyGL
                                     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[)
    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,
@@@ -1681,11 -1724,11 +1681,11 @@@ yyreportTree (yySemanticOption* yyx, in
          {
            if (yystates[yyi-1]->yyposn+1 > yystates[yyi]->yyposn)
              YYFPRINTF (stderr, "%*s%s <empty>\n", yyindent+2, "",
 -                       yytokenName (yyrhs[yyprhs[yyx->yyrule]+yyi-1]));
 +                       yytokenName (yystos[yystates[yyi]->yylrState]));
            else
              YYFPRINTF (stderr, "%*s%s <tokens %lu .. %lu>\n", yyindent+2, "",
 -                       yytokenName (yyrhs[yyprhs[yyx->yyrule]+yyi-1]),
 -                       (unsigned long int) (yystates[yyi - 1]->yyposn + 1),
 +                       yytokenName (yystos[yystates[yyi]->yylrState]),
 +                       (unsigned long int) (yystates[yyi-1]->yyposn + 1),
                         (unsigned long int) yystates[yyi]->yyposn);
          }
        else
@@@ -1714,9 -1757,9 +1714,9 @@@ yyreportAmbiguity (yySemanticOption* yy
    return yyabort;
  }]b4_locations_if([[
  
 -/** 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[)
      }
  }]])[
  
 -/** 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[)
@@@ -1913,6 -1955,10 +1913,6 @@@ static YYRESULTTA
  yyprocessOneStack (yyGLRStack* yystackp, size_t yyk,
                     size_t yyposn]b4_pure_formals[)
  {
 -  int yyaction;
 -  const short int* yyconflicts;
 -  yyRuleNum yyrule;
 -
    while (yystackp->yytops.yystates[yyk] != YY_NULL)
      {
        yyStateNum yystate = yystackp->yytops.yystates[yyk]->yylrState;
  
        if (yyisDefaultedState (yystate))
          {
 -          yyrule = yydefaultAction (yystate);
 +          YYRESULTTAG yyflag;
 +          yyRuleNum yyrule = yydefaultAction (yystate);
            if (yyrule == 0)
              {
                YYDPRINTF ((stderr, "Stack %lu dies.\n",
                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;
 +          int yyaction;
 +          const short int* yyconflicts;
 +
            yystackp->yytops.yylookaheadNeeds[yyk] = yytrue;
            if (yychar == YYEMPTY)
              {
  
            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));
 -              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;
              }
  
                break;
              }
            else
 -            YYCHK (yyglrReduce (yystackp, yyk, -yyaction,
 -                                yyfalse]b4_user_args[));
 +            {
 +              YYRESULTTAG 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;
@@@ -2272,6 -2279,7 +2272,6 @@@ yyrecoverSyntaxError (yyGLRStack* yysta
      }                                                                        \
    } while (YYID (0))
  
 -
  /*----------.
  | yyparse.  |
  `----------*/
  #endif
  ])
  m4_ifdef([b4_initial_action], [
- m4_pushdef([b4_at_dollar],     [yylloc])dnl
- m4_pushdef([b4_dollar_dollar], [yylval])dnl
+ b4_dollar_pushdef([yylval], [], [yylloc])dnl
 -/* User initialization code.  */
 -b4_user_initial_action
 +  /* User initialization code.  */
 +  b4_user_initial_action
- m4_popdef([b4_dollar_dollar])dnl
- m4_popdef([b4_at_dollar])])dnl
+ b4_dollar_popdef])[]dnl
  [
    if (! yyinitGLRStack (yystackp, YYINITDEPTH))
      goto yyexhaustedlab;
@@@ -2593,7 -2599,9 +2591,7 @@@ yypdumpstack (yyGLRStack* yystackp
    YYFPRINTF (stderr, "\n");
  }
  #endif
 -]
 -
 -b4_epilogue
 +]b4_epilogue[]dnl
  dnl
  dnl glr.cc produces its own header.
  dnl
diff --combined data/glr.cc
index 81e80278234fcaf2e075cc08c113f5d87989c8db,78a7ae519ad0b902a1a3e67e2fc5b51f83067d1a..7b3ea3f4ee9ade2e0a34d431b1bd37c6796c53c0
@@@ -1,3 -1,5 +1,3 @@@
 -                                                                    -*- C -*-
 -
  # C++ GLR skeleton for Bison
  
  # Copyright (C) 2002-2012 Free Software Foundation, Inc.
@@@ -27,7 -29,7 +27,7 @@@
  #
  #   The additional arguments are stored as members of the parser
  #   object, yyparser.  The C routines need to carry yyparser
 -#   throughout the C parser; that easy: just let yyparser become an
 +#   throughout the C parser; that's easy: make yyparser an
  #   additional parse-param.  But because the C++ skeleton needs to
  #   know the "real" original parse-param, we save them
  #   (b4_parse_param_orig).  Note that b4_parse_param is overquoted
  # The locations
  #
  #   We use location.cc just like lalr1.cc, but because glr.c stores
 -#   the locations in a (C++) union, the position and location classes
 +#   the locations in a union, the position and location classes
  #   must not have a constructor.  Therefore, contrary to lalr1.cc, we
  #   must not define "b4_location_constructors".  As a consequence the
  #   user must initialize the first positions (in particular the
  #   filename member).
  
  # We require a pure interface using locations.
 -m4_define([b4_locations_flag], [1])
 +m4_define([b4_percent_define(locations)], [])
  m4_define([b4_pure_flag],      [1])
  
  # The header is mandatory.
@@@ -129,7 -131,8 +129,7 @@@ m4_pushdef([b4_parse_param], m4_defn([b
    ]b4_parser_class_name::b4_parser_class_name[ (]b4_parse_param_decl[)]m4_ifset([b4_parse_param], [
      :])[
  #if ]b4_api_PREFIX[DEBUG
 -    ]m4_ifset([b4_parse_param], [  ], [ :])[
 -      yycdebug_ (&std::cerr)]m4_ifset([b4_parse_param], [,])[
 +    ]m4_ifset([b4_parse_param], [  ], [ :])[yycdebug_ (&std::cerr)]m4_ifset([b4_parse_param], [,])[
  #endif]b4_parse_param_cons[
    {
    }
      YYUSE (yyo);
      switch (yytype)
        {
 -  ]m4_map([b4_symbol_actions], m4_defn([b4_symbol_printers]))dnl
 +]b4_symbol_foreach([b4_symbol_printer])dnl
  [        default:
            break;
        }
    void
    ]b4_parser_class_name[::set_debug_level (debug_level_type l)
    {
+     // Actually, it is yydebug which is really used.
      yydebug = l;
    }
  
  #endif
  ]m4_popdef([b4_parse_param])dnl
  b4_namespace_close[
 -
  ]])
  
  
@@@ -225,7 -230,7 +226,7 @@@ m4_popdef([b4_parse_param]
  m4_divert_push(0)
  @output(b4_spec_defines_file@)@
  b4_copyright([Skeleton interface for Bison GLR parsers in C++],
 -             [2002-2006, 2009-2012])[
 +             [2002-2012])[
  
  /* C++ GLR parser skeleton written by Akim Demaille.  */
  
  
  ]b4_percent_code_get([[requires]])[
  
 -# include <string>
 -# include <iostream>
 +#include <stdexcept>
 +#include <string>
 +#include <iostream>
  ]b4_percent_define_ifdef([[location_type]], [],
 -                         [[# include "location.hh"]])[
 +                         [[#include "location.hh"]])[
  
  ]b4_YYDEBUG_define[
  
    class ]b4_parser_class_name[
    {
    public:
 -    /// Symbol semantic values.
 -# ifndef ]b4_api_PREFIX[STYPE
 -]m4_ifdef([b4_stype],
 -[    union semantic_type
 -    {
 -b4_user_stype
 -    };],
 -[m4_if(b4_tag_seen_flag, 0,
 -[[    typedef int semantic_type;]],
 -[[    typedef ]b4_api_PREFIX[STYPE semantic_type;]])])[
 -# else
 -    typedef ]b4_api_PREFIX[STYPE semantic_type;
 -# endif
 -    /// Symbol locations.
 -    typedef ]b4_percent_define_get([[location_type]],
 -                                   [[location]])[ location_type;
 -    /// Tokens.
 -    struct token
 -    {
 -      ]b4_token_enums(b4_tokens)[
 -    };
 -    /// Token type.
 -    typedef token::yytokentype token_type;
 +]b4_public_types_declare[
  
      /// Build a parser object.
      ]b4_parser_class_name[ (]b4_parse_param_decl[);
      /// Set the current debugging level.
      void set_debug_level (debug_level_type l);
  
 -  private:
 -
    public:
      /// Report a syntax error.
      /// \param loc    where the syntax error is found.
      /// \param msg    a description of the syntax error.
      virtual void error (const location_type& loc, const std::string& msg);
 -  private:
  
  # if ]b4_api_PREFIX[DEBUG
    public:
    private:
      /* Debugging.  */
      std::ostream* yycdebug_;
 -# endif
 +#endif
  
  ]b4_parse_param_vars[
    };
  
  ]dnl Redirections for glr.c.
  b4_percent_define_flag_if([[global_tokens_and_yystype]],
 -[b4_token_defines(b4_tokens)])
 +[b4_token_defines])
  [
  #ifndef ]b4_api_PREFIX[STYPE
  # define ]b4_api_PREFIX[STYPE ]b4_namespace_ref[::]b4_parser_class_name[::semantic_type
diff --combined data/java.m4
index cd70852c148a51151d9fb1fc7dec5cac4ca43fd5,18ea30b5086b379ecc794a746dd4718daaa18528..988ac39ac670e16cf9ca0d15edb4f391d23035c7
@@@ -17,6 -17,7 +17,7 @@@
  # You should have received a copy of the GNU General Public License
  # along with this program.  If not, see <http://www.gnu.org/licenses/>.
  
+ m4_include(b4_pkgdatadir/[c-like.m4])
  
  # b4_comment(TEXT)
  # ----------------
@@@ -29,7 -30,7 +30,7 @@@ m4_define([b4_comment], [/* m4_bpatsubs
  # --------------------------
  # Join two lists with a comma if necessary.
  m4_define([b4_list2],
 -        [$1[]m4_ifval(m4_quote($1), [m4_ifval(m4_quote($2), [[, ]])])[]$2])
 +          [$1[]m4_ifval(m4_quote($1), [m4_ifval(m4_quote($2), [[, ]])])[]$2])
  
  
  # b4_percent_define_get3(DEF, PRE, POST, NOT)
@@@ -37,8 -38,8 +38,8 @@@
  # Expand to the value of DEF surrounded by PRE and POST if it's %define'ed,
  # otherwise NOT.
  m4_define([b4_percent_define_get3],
 -        [m4_ifval(m4_quote(b4_percent_define_get([$1])),
 -              [$2[]b4_percent_define_get([$1])[]$3], [$4])])
 +          [m4_ifval(m4_quote(b4_percent_define_get([$1])),
 +                [$2[]b4_percent_define_get([$1])[]$3], [$4])])
  
  
  
@@@ -103,7 -104,7 +104,7 @@@ m4_define([b4_identification]
  m4_define([b4_int_type],
  [m4_if(b4_ints_in($@,   [-128],   [127]), [1], [byte],
         b4_ints_in($@, [-32768], [32767]), [1], [short],
 -                                             [int])])
 +                                               [int])])
  
  # b4_int_type_for(NAME)
  # ---------------------
@@@ -117,45 -118,27 +118,45 @@@ m4_define([b4_int_type_for]
  m4_define([b4_null], [null])
  
  
 +# b4_typed_parser_table_define(TYPE, NAME, DATA, COMMENT)
 +# -------------------------------------------------------
 +m4_define([b4_typed_parser_table_define],
 +[m4_ifval([$4], [b4_comment([$4])
 +  ])dnl
 +[private static final ]$1[ yy$2_[] = yy$2_init();
 +  private static final ]$1[[] yy$2_init()
 +  {
 +    return new ]$1[[]
 +    {
 +  ]$3[
 +    };
 +  }]])
 +
 +
 +# b4_integral_parser_table_define(NAME, DATA, COMMENT)
 +#-----------------------------------------------------
 +m4_define([b4_integral_parser_table_define],
 +[b4_typed_parser_table_define([b4_int_type_for([$2])], [$1], [$2], [$3])])
 +
 +
  ## ------------------------- ##
  ## Assigning token numbers.  ##
  ## ------------------------- ##
  
 -# b4_token_enum(TOKEN-NAME, TOKEN-NUMBER)
 -# ---------------------------------------
 +# b4_token_enum(TOKEN-NUM)
 +# ------------------------
  # Output the definition of this token as an enum.
  m4_define([b4_token_enum],
 -[  /** Token number, to be returned by the scanner.  */
 -  public static final int $1 = $2;
 -])
 +[b4_token_format([    /** Token number, to be returned by the scanner.  */
 +    static final int %s = %s;
 +], [$1])])
  
 -
 -# b4_token_enums(LIST-OF-PAIRS-TOKEN-NAME-TOKEN-NUMBER)
 -# -----------------------------------------------------
 +# b4_token_enums
 +# --------------
  # Output the definition of the tokens (if there are) as enums.
  m4_define([b4_token_enums],
 -[m4_if([$#$1], [1], [],
 -[/* Tokens.  */
 -m4_map([b4_token_enum], [$@])])
 -])
 +[b4_any_token_visible_if([/* Tokens.  */
 +b4_symbol_foreach([b4_token_enum])])])
  
  # b4-case(ID, CODE)
  # -----------------
@@@ -166,40 -149,30 +167,40 @@@ m4_define([b4_case], [  case $1
    break;
      ])
  
 +# b4_predicate_case(LABEL, CONDITIONS)
 +# ------------------------------------
 +m4_define([b4_predicate_case], [  case $1:
 +     if (! ($2)) YYERROR;
 +    break;
 +    ])
 +
  
  ## ---------------- ##
  ## Default values.  ##
  ## ---------------- ##
  
  m4_define([b4_yystype], [b4_percent_define_get([[stype]])])
 -b4_percent_define_default([[stype]], [[Object]])])
 +b4_percent_define_default([[stype]], [[Object]])
  
  # %name-prefix
  m4_define_default([b4_prefix], [[YY]])
  
 -b4_percent_define_default([[parser_class_name]], [b4_prefix[]Parser])])
 +b4_percent_define_default([[parser_class_name]], [b4_prefix[]Parser])
  m4_define([b4_parser_class_name], [b4_percent_define_get([[parser_class_name]])])
  
 -b4_percent_define_default([[lex_throws]], [[java.io.IOException]])])
 +b4_percent_define_default([[lex_throws]], [[java.io.IOException]])
  m4_define([b4_lex_throws], [b4_percent_define_get([[lex_throws]])])
  
 -b4_percent_define_default([[throws]], [])])
 +b4_percent_define_default([[throws]], [])
  m4_define([b4_throws], [b4_percent_define_get([[throws]])])
  
 -b4_percent_define_default([[location_type]], [Location])])
 +b4_percent_define_default([[init_throws]], [])
 +m4_define([b4_init_throws], [b4_percent_define_get([[init_throws]])])
 +
 +b4_percent_define_default([[location_type]], [Location])
  m4_define([b4_location_type], [b4_percent_define_get([[location_type]])])
  
 -b4_percent_define_default([[position_type]], [Position])])
 +b4_percent_define_default([[position_type]], [Position])
  m4_define([b4_position_type], [b4_percent_define_get([[position_type]])])
  
  
@@@ -246,21 -219,21 +247,21 @@@ m4_define([b4_rhs_location]
  # it to be single quoted.  Same for b4_parse_param.
  
  # TODO: should be in bison.m4
 -m4_define_default([b4_lex_param], [[]]))
 -m4_define([b4_lex_param], b4_lex_param))
 -m4_define([b4_parse_param], b4_parse_param))
 +m4_define_default([b4_lex_param], [[]])
 +m4_define([b4_lex_param], b4_lex_param)
 +m4_define([b4_parse_param], b4_parse_param)
  
  # b4_lex_param_decl
 -# -------------------
 +# -----------------
  # Extra formal arguments of the constructor.
  m4_define([b4_lex_param_decl],
  [m4_ifset([b4_lex_param],
            [b4_remove_comma([$1],
 -                         b4_param_decls(b4_lex_param))],
 -        [$1])])
 +                           b4_param_decls(b4_lex_param))],
 +          [$1])])
  
  m4_define([b4_param_decls],
 -        [m4_map([b4_param_decl], [$@])])
 +          [m4_map([b4_param_decl], [$@])])
  m4_define([b4_param_decl], [, $1])
  
  m4_define([b4_remove_comma], [m4_ifval(m4_quote($1), [$1, ], [])m4_shift2($@)])
  m4_define([b4_parse_param_decl],
  [m4_ifset([b4_parse_param],
            [b4_remove_comma([$1],
 -                         b4_param_decls(b4_parse_param))],
 -        [$1])])
 +                           b4_param_decls(b4_parse_param))],
 +          [$1])])
  
  
  
  # b4_lex_param_call
 -# -------------------
 +# -----------------
  # Delegating the lexer parameters to the lexer constructor.
  m4_define([b4_lex_param_call],
            [m4_ifset([b4_lex_param],
 -                  [b4_remove_comma([$1],
 -                                   b4_param_calls(b4_lex_param))],
 -                  [$1])])
 +                    [b4_remove_comma([$1],
 +                                     b4_param_calls(b4_lex_param))],
 +                    [$1])])
  m4_define([b4_param_calls],
 -        [m4_map([b4_param_call], [$@])])
 +          [m4_map([b4_param_call], [$@])])
  m4_define([b4_param_call], [, $2])
  
  
  # Extra initialisations of the constructor.
  m4_define([b4_parse_param_cons],
            [m4_ifset([b4_parse_param],
 -                  [b4_constructor_calls(b4_parse_param)])])
 +                    [b4_constructor_calls(b4_parse_param)])])
  
  m4_define([b4_constructor_calls],
 -        [m4_map([b4_constructor_call], [$@])])
 +          [m4_map([b4_constructor_call], [$@])])
  m4_define([b4_constructor_call],
 -        [this.$2 = $2;
 -        ])
 +          [this.$2 = $2;
 +          ])
  
  
  
  # Extra instance variables.
  m4_define([b4_parse_param_vars],
            [m4_ifset([b4_parse_param],
 -                  [
 +                    [
      /* User arguments.  */
  b4_var_decls(b4_parse_param)])])
  
  m4_define([b4_var_decls],
 -        [m4_map_sep([b4_var_decl], [
 +          [m4_map_sep([b4_var_decl], [
  ], [$@])])
  m4_define([b4_var_decl],
 -        [    protected final $1;])
 +          [    protected final $1;])
  
  
  
  # -----------------------
  # Expand to either an empty string or "throws THROWS".
  m4_define([b4_maybe_throws],
 -        [m4_ifval($1, [throws $1])])
 +          [m4_ifval($1, [throws $1])])
diff --combined data/lalr1.cc
index 96936bbe67955cf17d11b62887475da705d8fffc,c1639033f3fbd5194f92bd2b44f56144637f5406..313dba271ce55f0623f6de62d5cf0951b636a973
  
  m4_include(b4_pkgdatadir/[c++.m4])
  
- [m4_pushdef([b4_dollar_dollar],
-     [b4_symbol_value_template([yysym.value],
-                               b4_symbol_if([$1], [has_type],
-                                            [b4_symbol([$1], [type])]))])dnl
- m4_pushdef([b4_at_dollar], [yysym.location])dnl
 +
 +# b4_integral_parser_table_declare(TABLE-NAME, CONTENT, COMMENT)
 +# --------------------------------------------------------------
 +# Declare "parser::yy<TABLE-NAME>_" which contents is CONTENT.
 +m4_define([b4_integral_parser_table_declare],
 +[m4_ifval([$3], [b4_c_comment([$3], [  ])
 +])dnl
 +  static const b4_int_type_for([$2]) yy$1_[[]];dnl
 +])
 +
 +# b4_integral_parser_table_define(TABLE-NAME, CONTENT, COMMENT)
 +# -------------------------------------------------------------
 +# Define "parser::yy<TABLE-NAME>_" which contents is CONTENT.
 +m4_define([b4_integral_parser_table_define],
 +[  const b4_int_type_for([$2])
 +  b4_parser_class_name::yy$1_[[]] =
 +  {
 +  $2
 +  };dnl
 +])
 +
 +
 +# b4_symbol_value_template(VAL, [TYPE])
 +# -------------------------------------
 +# Same as b4_symbol_value, but used in a template method.  It makes
 +# a difference when using variants.
 +m4_copy([b4_symbol_value], [b4_symbol_value_template])
 +
 +
 +# b4_lhs_value([TYPE])
 +# --------------------
 +# Expansion of $<TYPE>$.
 +m4_define([b4_lhs_value],
 +          [b4_symbol_value([yylhs.value], [$1])])
 +
 +
 +# b4_lhs_location()
 +# -----------------
 +# Expansion of @$.
 +m4_define([b4_lhs_location],
 +          [yylhs.location])
 +
 +
 +# b4_rhs_data(RULE-LENGTH, NUM)
 +# -----------------------------
 +# Return the data corresponding to the symbol #NUM, where the current
 +# rule has RULE-LENGTH symbols on RHS.
 +m4_define([b4_rhs_data],
 +          [yystack_@{b4_subtract($@)@}])
 +
 +
 +# b4_rhs_state(RULE-LENGTH, NUM)
 +# ------------------------------
 +# The state corresponding to the symbol #NUM, where the current
 +# rule has RULE-LENGTH symbols on RHS.
 +m4_define([b4_rhs_state],
 +          [b4_rhs_data([$1], [$2]).state])
 +
 +
 +# b4_rhs_value(RULE-LENGTH, NUM, [TYPE])
 +# --------------------------------------
 +# Expansion of $<TYPE>NUM, where the current rule has RULE-LENGTH
 +# symbols on RHS.
 +m4_define([b4_rhs_value],
 +          [b4_symbol_value([b4_rhs_data([$1], [$2]).value], [$3])])
 +
 +
 +# b4_rhs_location(RULE-LENGTH, NUM)
 +# ---------------------------------
 +# Expansion of @NUM, where the current rule has RULE-LENGTH symbols
 +# on RHS.
 +m4_define([b4_rhs_location],
 +          [b4_rhs_data([$1], [$2]).location])
 +
 +
 +# b4_symbol_action(SYMBOL-NUM, KIND)
 +# ----------------------------------
 +# Run the action KIND (destructor or printer) for SYMBOL-NUM.
 +# Same as in C, but using references instead of pointers.
 +m4_define([b4_symbol_action],
 +[b4_symbol_if([$1], [has_$2],
- m4_popdef([b4_at_dollar])dnl
- m4_popdef([b4_dollar_dollar])dnl
++[m4_pushdef([b4_symbol_value], m4_defn([b4_symbol_value_template]))[]dnl
++b4_dollar_pushdef([yysym.value],
++                   b4_symbol_if([$1], [has_type],
++                                [m4_dquote(b4_symbol([$1], [type]))]),
++                   [yysym.location])dnl
 +      b4_symbol_case_([$1])
 +b4_syncline([b4_symbol([$1], [$2_line])], ["b4_symbol([$1], [$2_file])"])
 +        b4_symbol([$1], [$2])
 +b4_syncline([@oline@], [@ofile@])
 +        break;
 +
++m4_popdef([b4_symbol_value])[]dnl
++b4_dollar_popdef[]dnl
 +])])
 +
 +
 +m4_pushdef([b4_copyright_years],
 +           [2002-2012])
 +
  m4_define([b4_parser_class_name],
            [b4_percent_define_get([[parser_class_name]])])
  
  b4_defines_if([],
                [b4_fatal([b4_skeleton[: using %%defines is mandatory]])])
  
 -b4_percent_define_ifdef([[location_type]], [],
 +b4_locations_if([b4_percent_define_ifdef([[location_type]], [],
    [# Backward compatibility.
 -  m4_define([b4_location_constructors])
 -  m4_include(b4_pkgdatadir/[location.cc])])
 +   m4_define([b4_location_constructors])
 +   m4_include(b4_pkgdatadir/[location.cc])])])
  m4_include(b4_pkgdatadir/[stack.hh])
 +b4_variant_if([m4_include(b4_pkgdatadir/[variant.hh])])
  
  # We do want M4 expansion after # for CPP macros.
  m4_changecom()
  m4_divert_push(0)dnl
 -b4_defines_if(
 -[@output(b4_spec_defines_file@)@
 -b4_copyright([Skeleton interface for Bison LALR(1) parsers in C++],
 -             [2002-2012])
 +@output(b4_spec_defines_file@)@
 +b4_copyright([Skeleton interface for Bison LALR(1) parsers in C++])
  [
  /**
   ** \file ]b4_spec_defines_file[
  /* C++ LALR(1) parser skeleton written by Akim Demaille.  */
  
  ]b4_cpp_guard_open([b4_spec_defines_file])[
 -
  ]b4_percent_code_get([[requires]])[
 -
 -#include <string>
 -#include <iostream>
 -#include "stack.hh"
 -]b4_percent_define_ifdef([[location_type]], [],
 -                         [[#include "location.hh"]])[
 +]b4_parse_assert_if([# include <cassert>])[
 +# include <stdexcept>
 +# include <string>
 +# include <iostream>
 +# include "stack.hh"
 +]b4_locations_if([b4_percent_define_ifdef([[location_type]], [],
 +                                          [[# include "location.hh"]])])[
 +
 +]b4_variant_if([b4_namespace_open
 +b4_variant_define
 +b4_namespace_close])[
  
  ]b4_YYDEBUG_define[
  
    class ]b4_parser_class_name[
    {
    public:
 -    /// Symbol semantic values.
 -#ifndef ]b4_api_PREFIX[STYPE
 -]m4_ifdef([b4_stype],
 -[    union semantic_type
 -    {
 -b4_user_stype
 -    };],
 -[m4_if(b4_tag_seen_flag, 0,
 -[[    typedef int semantic_type;]],
 -[[    typedef ]b4_api_PREFIX[STYPE semantic_type;]])])[
 -#else
 -    typedef ]b4_api_PREFIX[STYPE semantic_type;
 -#endif
 -    /// Symbol locations.
 -    typedef ]b4_percent_define_get([[location_type]],
 -                                   [[location]])[ location_type;
 -    /// Tokens.
 -    struct token
 -    {
 -      ]b4_token_enums(b4_tokens)[
 -    };
 -    /// Token type.
 -    typedef token::yytokentype token_type;
 -
 +]b4_public_types_declare[
      /// Build a parser object.
      ]b4_parser_class_name[ (]b4_parse_param_decl[);
      virtual ~]b4_parser_class_name[ ();
      void set_debug_level (debug_level_type l);
  #endif
  
 -  private:
 -    /// Report a syntax error.
 -    /// \param loc    where the syntax error is found.
 +    /// Report a syntax error.]b4_locations_if([
 +    /// \param loc    where the syntax error is found.])[
      /// \param msg    a description of the syntax error.
 -    virtual void error (const location_type& loc, const std::string& msg);
 -
 -    /// Generate an error message.
 -    /// \param state   the state where the error occurred.
 -    /// \param tok     the lookahead token.
 -    virtual std::string yysyntax_error_ (int yystate, int tok);
 -
 -#if ]b4_api_PREFIX[DEBUG
 -    /// \brief Report a symbol value on the debug stream.
 -    /// \param yytype       The token type.
 -    /// \param yyvaluep     Its semantic value.
 -    /// \param yylocationp  Its location.
 -    virtual void yy_symbol_value_print_ (int yytype,
 -                                       const semantic_type* yyvaluep,
 -                                       const location_type* yylocationp);
 -    /// \brief Report a symbol on the debug stream.
 -    /// \param yytype       The token type.
 -    /// \param yyvaluep     Its semantic value.
 -    /// \param yylocationp  Its location.
 -    virtual void yy_symbol_print_ (int yytype,
 -                                 const semantic_type* yyvaluep,
 -                                 const location_type* yylocationp);
 -#endif
 +    virtual void error (]b4_locations_if([const location_type& loc, ])[const std::string& msg);
  
 +    /// Report a syntax error.
 +    void error (const syntax_error& err);
  
 +  private:
      /// State numbers.
      typedef int state_type;
 -    /// State stack type.
 -    typedef stack<state_type>    state_stack_type;
 -    /// Semantic value stack type.
 -    typedef stack<semantic_type> semantic_stack_type;
 -    /// location stack type.
 -    typedef stack<location_type> location_stack_type;
 -
 -    /// The state stack.
 -    state_stack_type yystate_stack_;
 -    /// The semantic value stack.
 -    semantic_stack_type yysemantic_stack_;
 -    /// The location stack.
 -    location_stack_type yylocation_stack_;
 +
 +    /// Generate an error message.
 +    /// \param yystate   the state where the error occurred.
 +    /// \param yytoken   the lookahead token.
 +    virtual std::string yysyntax_error_ (state_type yystate, int yytoken);
 +
 +    /// Compute post-reduction state.
 +    /// \param yystate   the current state
 +    /// \param yylhs     the nonterminal to push on the stack
 +    state_type yy_lr_goto_state_ (state_type yystate, int yylhs);
  
      /// Whether the given \c yypact_ value indicates a defaulted state.
      /// \param yyvalue   the value to check
  
      /// Internal symbol numbers.
      typedef ]b4_int_type_for([b4_translate])[ token_number_type;
 -    /* Tables.  */
 -    /// For a state, the index in \a yytable_ of its portion.
 -    static const ]b4_int_type_for([b4_pact])[ yypact_[];
      static const ]b4_int_type(b4_pact_ninf, b4_pact_ninf)[ yypact_ninf_;
 -
 -    /// For a state, default reduction number.
 -    /// Unless\a  yytable_ specifies something else to do.
 -    /// Zero means the default is an error.
 -    static const ]b4_int_type_for([b4_defact])[ yydefact_[];
 -
 -    static const ]b4_int_type_for([b4_pgoto])[ yypgoto_[];
 -    static const ]b4_int_type_for([b4_defgoto])[ yydefgoto_[];
 -
 -    /// What to do in a state.
 -    /// \a yytable_[yypact_[s]]: what to do in state \a s.
 -    /// - if positive, shift that token.
 -    /// - if negative, reduce the rule which number is the opposite.
 -    /// - if zero, do what YYDEFACT says.
 -    static const ]b4_int_type_for([b4_table])[ yytable_[];
      static const ]b4_int_type(b4_table_ninf, b4_table_ninf)[ yytable_ninf_;
  
 -    static const ]b4_int_type_for([b4_check])[ yycheck_[];
 -
 -    /// For a state, its accessing symbol.
 -    static const ]b4_int_type_for([b4_stos])[ yystos_[];
 -
 -    /// For a rule, its LHS.
 -    static const ]b4_int_type_for([b4_r1])[ yyr1_[];
 -    /// For a rule, its RHS length.
 -    static const ]b4_int_type_for([b4_r2])[ yyr2_[]; ]b4_error_verbose_if([
 +    // Tables.
 +]b4_parser_tables_declare[]b4_error_verbose_if([
  
      /// Convert the symbol name \a n to a form suitable for a diagnostic.
      static std::string yytnamerr_ (const char *n);])[
      /// For a symbol, its name in clear.
      static const char* const yytname_[];
  ]b4_token_table_if([[#if ]b4_api_PREFIX[DEBUG]])[
 -    /// A type to store symbol numbers and -1.
 -    typedef ]b4_int_type_for([b4_rhs])[ rhs_number_type;
 -    /// A `-1'-separated list of the rules' RHS.
 -    static const rhs_number_type yyrhs_[];
 -    /// For each rule, the index of the first RHS symbol in \a yyrhs_.
 -    static const ]b4_int_type_for([b4_prhs])[ yyprhs_[];
 -    /// For each rule, its source line number.
 -    static const ]b4_int_type_for([b4_rline])[ yyrline_[];
 -    /// For each scanner token number, its symbol number.
 -    static const ]b4_int_type_for([b4_toknum])[ yytoken_number_[];
 +]b4_integral_parser_table_declare([rline], [b4_rline],
 +     [YYRLINE[YYN] -- Source line where rule number YYN was defined.])[
      /// Report on the debug stream that the rule \a r is going to be reduced.
      virtual void yy_reduce_print_ (int r);
      /// Print the state stack on the debug stream.
      virtual void yystack_print_ ();
  
 -    /* Debugging.  */
 +    // Debugging.
      int yydebug_;
      std::ostream* yycdebug_;
 -#endif
 +#endif // ]b4_api_PREFIX[DEBUG
  
      /// Convert a scanner token number \a t to a symbol number.
 -    token_number_type yytranslate_ (int t);
 +    static inline token_number_type yytranslate_ (]b4_lex_symbol_if([token_type], [int])[ t);
 +
 +#if ]b4_api_PREFIX[DEBUG
 +    /// \brief Display a symbol type, value and location.
 +    /// \param yyo    The output stream.
 +    /// \param yysym  The symbol.
 +    template <typename Exact>
 +    void yy_print_ (std::ostream& yyo,
 +                    const symbol_base_type<Exact>& yysym) const;
 +#endif
  
      /// \brief Reclaim the memory associated to a symbol.
 -    /// \param yymsg        Why this token is reclaimed.
 -    /// \param yytype       The symbol type.
 -    /// \param yyvaluep     Its semantic value.
 -    /// \param yylocationp  Its location.
 -    inline void yydestruct_ (const char* yymsg,
 -                           int yytype,
 -                           semantic_type* yyvaluep,
 -                           location_type* yylocationp);
 +    /// \param yymsg     Why this token is reclaimed.
 +    ///                  If null, print nothing.
 +    /// \param s         The symbol.
 +    template <typename Exact>
 +    inline void yy_destroy_ (const char* yymsg,
 +                             symbol_base_type<Exact>& yysym) const;
 +
 +  private:
 +    /// Element of the stack: a state and its attributes.
 +    struct stack_symbol_type : symbol_base_type<stack_symbol_type>
 +    {
 +      /// The parent class.
 +      typedef symbol_base_type<stack_symbol_type> super_type;
 +
 +      /// Default constructor.
 +      inline stack_symbol_type ();
 +
 +      /// Constructor.
 +      inline stack_symbol_type (]b4_args([state_type s],
 +                                         [const semantic_type& v],
 +                                         b4_locations_if([const location_type& l]))[);
 +
 +      /// The state.
 +      state_type state;
 +
 +      /// The type (corresponding to \a state).
 +      inline int type_get_ () const;
 +    };
 +
 +    /// Stack type.
 +    typedef stack<stack_symbol_type> stack_type;
 +
 +    /// The stack.
 +    stack_type yystack_;
 +
 +    /// Push a new state on the stack.
 +    /// \param m    a debug message to display
 +    ///             if null, no trace is output.
 +    /// \param s    the symbol
 +    /// \warning the contents of \a s.value is stolen.
 +    inline void yypush_ (const char* m, stack_symbol_type& s);
 +
 +    /// Push a new look ahead token on the state on the stack.
 +    /// \param m    a debug message to display
 +    ///             if null, no trace is output.
 +    /// \param s    the state
 +    /// \param sym  the symbol (for its value and location).
 +    /// \warning the contents of \a s.value is stolen.
 +    inline void yypush_ (const char* m, state_type s, symbol_type& sym);
  
      /// Pop \a n symbols the three stacks.
      inline void yypop_ (unsigned int n = 1);
  
      /* Constants.  */
 -    static const int yyeof_;
 -    /* LAST_ -- Last index in TABLE_.  */
 -    static const int yylast_;
 -    static const int yynnts_;
 -    static const int yyempty_;
 -    static const int yyfinal_;
 -    static const int yyterror_;
 -    static const int yyerrcode_;
 -    static const int yyntokens_;
 -    static const unsigned int yyuser_token_number_max_;
 -    static const token_number_type yyundef_token_;
 +    enum
 +    {
 +      yyeof_ = 0,
 +      yylast_ = ]b4_last[,           //< Last index in yytable_.
 +      yynnts_ = ]b4_nterms_number[,  //< Number of nonterminal symbols.
 +      yyempty_ = -2,
 +      yyfinal_ = ]b4_final_state_number[, //< Termination state number.
 +      yyterror_ = 1,
 +      yyerrcode_ = 256,
 +      yyntokens_ = ]b4_tokens_number[    //< Number of tokens.
 +    };
 +
  ]b4_parse_param_vars[
    };
 +
 +]b4_lex_symbol_if([b4_yytranslate_define
 +b4_public_types_define])[
  ]b4_namespace_close[
  
  ]b4_percent_define_flag_if([[global_tokens_and_yystype]],
 -[b4_token_defines(b4_tokens)
 +[b4_token_defines
  
  #ifndef ]b4_api_PREFIX[STYPE
   /* Redirection for backward compatibility.  */
  ])[
  ]b4_percent_code_get([[provides]])[
  ]b4_cpp_guard_close([b4_spec_defines_file])
 -])dnl
  @output(b4_parser_file_name@)@
 -b4_copyright([Skeleton implementation for Bison LALR(1) parsers in C++],
 -             [2002-2012])
 +b4_copyright([Skeleton implementation for Bison LALR(1) parsers in C++])
  b4_percent_code_get([[top]])[]dnl
  m4_if(b4_prefix, [yy], [],
  [
  /* First part of user declarations.  */
  ]b4_user_pre_prologue[
  
 -]b4_defines_if([[
 -#include "@basename(]b4_spec_defines_file[@)"]])[
 +#include "@basename(]b4_spec_defines_file[@)"
  
  /* User implementation prologue.  */
  ]b4_user_post_prologue[
  # endif
  #endif
  
 -#define YYRHSLOC(Rhs, K) ((Rhs)[K])
 -]b4_yylloc_default_define[
 +]b4_locations_if([dnl
 +[#define YYRHSLOC(Rhs, K) ((Rhs)[K].location)
 +]b4_yylloc_default_define])[
  
  /* Suppress unused-variable warnings by "using" E.  */
  #define YYUSE(e) ((void) (e))
  /* A pseudo ostream that takes yydebug_ into account.  */
  # define YYCDEBUG if (yydebug_) (*yycdebug_)
  
 -# define YY_SYMBOL_PRINT(Title, Type, Value, Location)        \
 -do {                                                  \
 -  if (yydebug_)                                               \
 -    {                                                 \
 -      *yycdebug_ << Title << ' ';                     \
 -      yy_symbol_print_ ((Type), (Value), (Location)); \
 -      *yycdebug_ << std::endl;                                \
 -    }                                                 \
 -} while (false)
 -
 -# define YY_REDUCE_PRINT(Rule)                \
 -do {                                  \
 -  if (yydebug_)                               \
 -    yy_reduce_print_ (Rule);          \
 -} while (false)
 -
 -# define YY_STACK_PRINT()             \
 -do {                                  \
 -  if (yydebug_)                               \
 -    yystack_print_ ();                        \
 -} while (false)
 +# define YY_SYMBOL_PRINT(Title, Symbol)         \
 +  do {                                          \
 +    if (yydebug_)                               \
 +    {                                           \
 +      *yycdebug_ << Title << ' ';               \
 +      yy_print_ (*yycdebug_, Symbol);           \
 +      *yycdebug_ << std::endl;                  \
 +    }                                           \
 +  } while (false)
 +
 +# define YY_REDUCE_PRINT(Rule)          \
 +  do {                                  \
 +    if (yydebug_)                       \
 +      yy_reduce_print_ (Rule);          \
 +  } while (false)
 +
 +# define YY_STACK_PRINT()               \
 +  do {                                  \
 +    if (yydebug_)                       \
 +      yystack_print_ ();                \
 +  } while (false)
  
  #else /* !]b4_api_PREFIX[DEBUG */
  
  # define YYCDEBUG if (false) std::cerr
 -# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
 -# define YY_REDUCE_PRINT(Rule)
 -# define YY_STACK_PRINT()
 +# define YY_SYMBOL_PRINT(Title, Symbol)  YYUSE(Symbol)
 +# define YY_REDUCE_PRINT(Rule)           static_cast<void>(0)
 +# define YY_STACK_PRINT()                static_cast<void>(0)
  
  #endif /* !]b4_api_PREFIX[DEBUG */
  
 -#define yyerrok               (yyerrstatus_ = 0)
 -#define yyclearin     (yychar = yyempty_)
 +#define yyerrok         (yyerrstatus_ = 0)
 +#define yyclearin       (yyempty = true)
  
 -#define YYACCEPT      goto yyacceptlab
 -#define YYABORT               goto yyabortlab
 -#define YYERROR               goto yyerrorlab
 +#define YYACCEPT        goto yyacceptlab
 +#define YYABORT         goto yyabortlab
 +#define YYERROR         goto yyerrorlab
  #define YYRECOVERING()  (!!yyerrstatus_)
  
  ]b4_namespace_open[]b4_error_verbose_if([[
    {
    }
  
 -#if ]b4_api_PREFIX[DEBUG
 -  /*--------------------------------.
 -  | Print this symbol on YYOUTPUT.  |
 -  `--------------------------------*/
  
 -  inline void
 -  ]b4_parser_class_name[::yy_symbol_value_print_ (int yytype,
 -                         const semantic_type* yyvaluep, const location_type* yylocationp)
 +  /*---------------.
 +  | Symbol types.  |
 +  `---------------*/
 +
 +]b4_lex_symbol_if([], [b4_public_types_define])[
 +
 +  // stack_symbol_type.
 +  ]b4_parser_class_name[::stack_symbol_type::stack_symbol_type ()
 +    : super_type ()
 +    , state ()
 +  {
 +  }
 +
 +  ]b4_parser_class_name[::stack_symbol_type::stack_symbol_type (]b4_args(
 +                 [state_type s],
 +                 [const semantic_type& v],
 +                 b4_locations_if([const location_type& l]))[)
 +    : super_type (v]b4_locations_if([, l])[)
 +    , state (s)
 +  {
 +  }
 +
 +  int
 +  ]b4_parser_class_name[::stack_symbol_type::type_get_ () const
 +  {
 +    return yystos_[state];
 +  }
 +
 +
 +  template <typename Exact>
 +  void
 +  ]b4_parser_class_name[::yy_destroy_ (const char* yymsg,
 +                                       symbol_base_type<Exact>& yysym) const
 +  {
 +    if (yymsg)
 +      YY_SYMBOL_PRINT (yymsg, yysym);
 +
 +    // User destructor.
 +    int yytype = yysym.type_get ();
 +    switch (yytype)
 +      {
 +]b4_symbol_foreach([b4_symbol_destructor])dnl
 +[       default:
 +          break;
 +      }]b4_variant_if([
 +
 +    // Type destructor.
 +  b4_symbol_variant([[yytype]], [[yysym.value]], [[template destroy]])])[
 +  }
 +
 +#if ]b4_api_PREFIX[DEBUG
 +  template <typename Exact>
 +  void
 +  ]b4_parser_class_name[::yy_print_ (std::ostream& yyo,
 +                                     const symbol_base_type<Exact>& yysym) const
    {
 -    YYUSE (yylocationp);
 -    YYUSE (yyvaluep);
 -    std::ostream& yyo = debug_stream ();
      std::ostream& yyoutput = yyo;
      YYUSE (yyoutput);
 +    int yytype = yysym.type_get ();
 +    yyo << (yytype < yyntokens_ ? "token" : "nterm")
 +        << ' ' << yytname_[yytype] << " ("]b4_locations_if([
 +        << yysym.location << ": "])[;
      switch (yytype)
        {
 -  ]m4_map([b4_symbol_actions], m4_defn([b4_symbol_printers]))dnl
 +]b4_symbol_foreach([b4_symbol_printer])dnl
  [       default:
 -        break;
 +          break;
        }
 +    yyo << ')';
    }
 -
 +#endif
  
    void
 -  ]b4_parser_class_name[::yy_symbol_print_ (int yytype,
 -                         const semantic_type* yyvaluep, const location_type* yylocationp)
 +  ]b4_parser_class_name[::yypush_ (const char* m, state_type s,
 +                                   symbol_type& sym)
    {
 -    *yycdebug_ << (yytype < yyntokens_ ? "token" : "nterm")
 -             << ' ' << yytname_[yytype] << " ("
 -             << *yylocationp << ": ";
 -    yy_symbol_value_print_ (yytype, yyvaluep, yylocationp);
 -    *yycdebug_ << ')';
 +    if (m)
 +      YY_SYMBOL_PRINT (m, sym);
 +]b4_variant_if(
 +[[    yystack_.push (stack_symbol_type (]b4_args(
 +                    [s],
 +                    [semantic_type()],
 +                    b4_locations_if([sym.location]))[));
 +    ]b4_symbol_variant([[yystos_[s]]], [[yystack_[0].value]],
 +                       [build], [sym.value])],
 +[[    yystack_.push (stack_symbol_type (]b4_args(
 +                      [s],
 +                      [sym.value],
 +                      b4_locations_if([sym.location]))[));]])[
    }
 -#endif
  
    void
 -  ]b4_parser_class_name[::yydestruct_ (const char* yymsg,
 -                         int yytype, semantic_type* yyvaluep, location_type* yylocationp)
 +  ]b4_parser_class_name[::yypush_ (const char* m, stack_symbol_type& s)
    {
 -    YYUSE (yylocationp);
 -    YYUSE (yymsg);
 -    YYUSE (yyvaluep);
 -
 -    YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
 -
 -    switch (yytype)
 -      {
 -  ]m4_map([b4_symbol_actions], m4_defn([b4_symbol_destructors]))[
 -      default:
 -        break;
 -      }
 +    if (m)
 +      YY_SYMBOL_PRINT (m, s);
 +]b4_variant_if(
 +[[    yystack_.push (stack_symbol_type (]b4_args(
 +                       [s.state],
 +                       [semantic_type()],
 +                       b4_locations_if([s.location]))[));
 +    ]b4_symbol_variant([[yystos_[s.state]]], [[yystack_[0].value]],
 +                       [build], [s.value])],
 +[    yystack_.push (s);])[
    }
  
    void
    ]b4_parser_class_name[::yypop_ (unsigned int n)
    {
 -    yystate_stack_.pop (n);
 -    yysemantic_stack_.pop (n);
 -    yylocation_stack_.pop (n);
 +    yystack_.pop (n);
    }
  
  #if ]b4_api_PREFIX[DEBUG
    {
      yydebug_ = l;
    }
 -#endif
 +#endif // ]b4_api_PREFIX[DEBUG
 +
 +  inline ]b4_parser_class_name[::state_type
 +  ]b4_parser_class_name[::yy_lr_goto_state_ (state_type yystate, int yylhs)
 +  {
 +    int yyr = yypgoto_[yylhs - yyntokens_] + yystate;
 +    if (0 <= yyr && yyr <= yylast_ && yycheck_[yyr] == yystate)
 +      return yytable_[yyr];
 +    else
 +      return yydefgoto_[yylhs - yyntokens_];
 +  }
  
    inline bool
    ]b4_parser_class_name[::yy_pact_value_is_default_ (int yyvalue)
    int
    ]b4_parser_class_name[::parse ()
    {
 -    /// Lookahead and lookahead in internal form.
 -    int yychar = yyempty_;
 -    int yytoken = 0;
 +    /// Whether yyla contains a lookahead.
 +    bool yyempty = true;
  
      /* State.  */
      int yyn;
      int yylen = 0;
 -    int yystate = 0;
  
      /* Error handling.  */
      int yynerrs_ = 0;
      int yyerrstatus_ = 0;
  
 -    /// Semantic value of the lookahead.
 -    semantic_type yylval;
 -    /// Location of the lookahead.
 -    location_type yylloc;
 +    /// The lookahead symbol.
 +    symbol_type yyla;]b4_locations_if([[
 +
      /// The locations where the error started and ended.
 -    location_type yyerror_range[3];
 +    stack_symbol_type yyerror_range[3];]])[
  
 -    /// $$.
 -    semantic_type yyval;
 -    /// @@$.
 -    location_type yyloc;
 +    /// $$ and @@$.
 +    stack_symbol_type yylhs;
  
 +    /// The return value of parse ().
      int yyresult;
  
      YYCDEBUG << "Starting parse" << std::endl;
  
  ]m4_ifdef([b4_initial_action], [
- m4_pushdef([b4_at_dollar],     [yyla.location])dnl
- m4_pushdef([b4_dollar_dollar], [yyla.value])dnl
 -b4_dollar_pushdef([yylval], [], [yylloc])dnl
 -/* User initialization code.  */
 -b4_user_initial_action
++b4_dollar_pushdef([yyla.value], [], [yyla.location])dnl
 +    /* User initialization code.  */
 +    b4_user_initial_action
- m4_popdef([b4_dollar_dollar])dnl
- m4_popdef([b4_at_dollar])])dnl
+ b4_dollar_popdef])[]dnl
  
 -  [  /* Initialize the stacks.  The initial state will be pushed in
 +  [  /* Initialize the stack.  The initial state will be set in
         yynewstate, since the latter expects the semantical and the
         location values to have been already stored, initialize these
         stacks with a primary value.  */
 -    yystate_stack_ = state_stack_type (0);
 -    yysemantic_stack_ = semantic_stack_type (0);
 -    yylocation_stack_ = location_stack_type (0);
 -    yysemantic_stack_.push (yylval);
 -    yylocation_stack_.push (yylloc);
 +    yystack_ = stack_type (0);
 +    yypush_ (YY_NULL, 0, yyla);
  
 -    /* New state.  */
 +    // A new symbol was pushed on the stack.
    yynewstate:
 -    yystate_stack_.push (yystate);
 -    YYCDEBUG << "Entering state " << yystate << std::endl;
 +    YYCDEBUG << "Entering state " << yystack_[0].state << std::endl;
  
      /* Accept?  */
 -    if (yystate == yyfinal_)
 +    if (yystack_[0].state == yyfinal_)
        goto yyacceptlab;
  
      goto yybackup;
    yybackup:
  
      /* Try to take a decision without lookahead.  */
 -    yyn = yypact_[yystate];
 +    yyn = yypact_[yystack_[0].state];
      if (yy_pact_value_is_default_ (yyn))
        goto yydefault;
  
      /* Read a lookahead token.  */
 -    if (yychar == yyempty_)
 -      {
 -      YYCDEBUG << "Reading a token: ";
 -      yychar = ]b4_c_function_call([yylex], [int],
 -                                   [b4_api_PREFIX[STYPE*], [&yylval]][]dnl
 -b4_locations_if([, [[location*], [&yylloc]]])dnl
 -m4_ifdef([b4_lex_param], [, ]b4_lex_param))[;
 -      }
 -
 -
 -    /* Convert token to internal form.  */
 -    if (yychar <= yyeof_)
 +    if (yyempty)
        {
 -      yychar = yytoken = yyeof_;
 -      YYCDEBUG << "Now at end of input." << std::endl;
 -      }
 -    else
 -      {
 -      yytoken = yytranslate_ (yychar);
 -      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
 +        YYCDEBUG << "Reading a token: ";
 +        try
 +        {
 +]b4_lex_symbol_if(
 +[          yyla = b4_c_function_call([yylex], [symbol_type],
 +                                     m4_ifdef([b4_lex_param], b4_lex_param));],
 +[          yyla.type = yytranslate_ (b4_c_function_call([yylex], [int],
 +                                     [b4_api_PREFIX[STYPE*], [&yyla.value]][]dnl
 +b4_locations_if([, [[location*], [&yyla.location]]])dnl
 +m4_ifdef([b4_lex_param], [, ]b4_lex_param)));])[
 +        }
 +        catch (const syntax_error& yyexc)
 +        {
 +          error (yyexc);
 +          goto yyerrlab1;
 +        }
 +        yyempty = false;
        }
 +    YY_SYMBOL_PRINT ("Next token is", yyla);
  
 -    /* If the proper action on seeing token YYTOKEN is to reduce or to
 -       detect an error, take that action.  */
 -    yyn += yytoken;
 -    if (yyn < 0 || yylast_ < yyn || yycheck_[yyn] != yytoken)
 +    /* If the proper action on seeing token YYLA.TYPE is to reduce or
 +       to detect an error, take that action.  */
 +    yyn += yyla.type;
 +    if (yyn < 0 || yylast_ < yyn || yycheck_[yyn] != yyla.type)
        goto yydefault;
  
      /* Reduce or error.  */
      yyn = yytable_[yyn];
      if (yyn <= 0)
        {
 -      if (yy_table_value_is_error_ (yyn))
 -        goto yyerrlab;
 -      yyn = -yyn;
 -      goto yyreduce;
 +        if (yy_table_value_is_error_ (yyn))
 +          goto yyerrlab;
 +        yyn = -yyn;
 +        goto yyreduce;
        }
  
 -    /* Shift the lookahead token.  */
 -    YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
 -
      /* Discard the token being shifted.  */
 -    yychar = yyempty_;
 -
 -    yysemantic_stack_.push (yylval);
 -    yylocation_stack_.push (yylloc);
 +    yyempty = true;
  
      /* Count tokens shifted since error; after three, turn off error
         status.  */
      if (yyerrstatus_)
        --yyerrstatus_;
  
 -    yystate = yyn;
 +    /* Shift the lookahead token.  */
 +    yypush_ ("Shifting", yyn, yyla);
      goto yynewstate;
  
    /*-----------------------------------------------------------.
    | yydefault -- do the default action for the current state.  |
    `-----------------------------------------------------------*/
    yydefault:
 -    yyn = yydefact_[yystate];
 +    yyn = yydefact_[yystack_[0].state];
      if (yyn == 0)
        goto yyerrlab;
      goto yyreduce;
    `-----------------------------*/
    yyreduce:
      yylen = yyr2_[yyn];
 +    yylhs.state = yy_lr_goto_state_(yystack_[yylen].state, yyr1_[yyn]);]b4_variant_if([
 +    /* Variants are always initialized to an empty instance of the
 +       correct type. The default $$=$1 action is NOT applied when using
 +       variants.  */
 +    b4_symbol_variant([[yyr1_@{yyn@}]], [yylhs.value], [build])],[
      /* If YYLEN is nonzero, implement the default value of the action:
         `$$ = $1'.  Otherwise, use the top of the stack.
  
 -       Otherwise, the following line sets YYVAL to garbage.
 +       Otherwise, the following line sets YYLHS.VALUE to garbage.
         This behavior is undocumented and Bison
         users should not rely upon it.  */
      if (yylen)
 -      yyval = yysemantic_stack_[yylen - 1];
 +      yylhs.value = yystack_@{yylen - 1@}.value;
      else
 -      yyval = yysemantic_stack_[0];
 -
 +      yylhs.value = yystack_@{0@}.value;])[
 +]b4_locations_if([dnl
 +[
 +    // Compute the default @@$.
      {
 -      slice<location_type, location_stack_type> slice (yylocation_stack_, yylen);
 -      YYLLOC_DEFAULT (yyloc, slice, yylen);
 -    }
 +      slice<stack_symbol_type, stack_type> slice (yystack_, yylen);
 +      YYLLOC_DEFAULT (yylhs.location, slice, yylen);
 +    }]])[
 +
 +    // Perform the reduction.
      YY_REDUCE_PRINT (yyn);
 -    switch (yyn)
 +    try
 +    {
 +      switch (yyn)
        {
 -      ]b4_user_actions[
 -      default:
 +]b4_user_actions[
 +        default:
            break;
        }
 -    /* User semantic actions sometimes alter yychar, and that requires
 -       that yytoken be updated with the new translation.  We take the
 -       approach of translating immediately before every use of yytoken.
 -       One alternative is translating here after every semantic action,
 -       but that translation would be missed if the semantic action
 -       invokes YYABORT, YYACCEPT, or YYERROR immediately after altering
 -       yychar.  In the case of YYABORT or YYACCEPT, an incorrect
 -       destructor might then be invoked immediately.  In the case of
 -       YYERROR, subsequent parser actions might lead to an incorrect
 -       destructor call or verbose syntax error message before the
 -       lookahead is translated.  */
 -    YY_SYMBOL_PRINT ("-> $$ =", yyr1_[yyn], &yyval, &yyloc);
 +    }
 +    catch (const syntax_error& yyexc)
 +    {
 +      error (yyexc);
 +      YYERROR;
 +    }
 +    YY_SYMBOL_PRINT ("-> $$ =", yylhs);
 +]b4_variant_if([[
 +    // Destroy the rhs symbols.
 +    for (int i = 0; i < yylen; ++i)
 +      // Destroy a variant which value may have been swapped with
 +      // yylhs.value (for instance if the action was "std::swap($$,
 +      // $1)").  The value of yylhs.value (hence possibly one of these
 +      // rhs symbols) depends on the default construction for this
 +      // type.  In the case of pointers for instance, no
 +      // initialization is done, so the value is junk.  Therefore do
 +      // not try to report the value of symbols about to be destroyed
 +      // in the debug trace, it's possibly junk.  Hence yymsg = 0.
 +      // Besides, that keeps exactly the same traces as with the other
 +      // Bison skeletons.
 +      yy_destroy_ (YY_NULL, yystack_[i]);]])[
  
      yypop_ (yylen);
      yylen = 0;
      YY_STACK_PRINT ();
  
 -    yysemantic_stack_.push (yyval);
 -    yylocation_stack_.push (yyloc);
 -
      /* Shift the result of the reduction.  */
 -    yyn = yyr1_[yyn];
 -    yystate = yypgoto_[yyn - yyntokens_] + yystate_stack_[0];
 -    if (0 <= yystate && yystate <= yylast_
 -      && yycheck_[yystate] == yystate_stack_[0])
 -      yystate = yytable_[yystate];
 -    else
 -      yystate = yydefgoto_[yyn - yyntokens_];
 +    yypush_ (YY_NULL, yylhs);
      goto yynewstate;
  
 -  /*------------------------------------.
 -  | yyerrlab -- here on detecting error |
 -  `------------------------------------*/
 +  /*--------------------------------------.
 +  | yyerrlab -- here on detecting error |
 +  `--------------------------------------*/
    yyerrlab:
 -    /* Make sure we have latest lookahead translation.  See comments at
 -       user semantic actions for why this is necessary.  */
 -    yytoken = yytranslate_ (yychar);
 -
      /* If not already recovering from an error, report this error.  */
      if (!yyerrstatus_)
        {
 -      ++yynerrs_;
 -      if (yychar == yyempty_)
 -        yytoken = yyempty_;
 -      error (yylloc, yysyntax_error_ (yystate, yytoken));
 +        ++yynerrs_;
 +        error (]b4_args(b4_locations_if([yyla.location]),
 +                        [[yysyntax_error_ (yystack_[0].state,
 +                                           yyempty ? yyempty_ : yyla.type)]])[);
        }
  
 -    yyerror_range[1] = yylloc;
 +]b4_locations_if([[
 +    yyerror_range[1].location = yyla.location;]])[
      if (yyerrstatus_ == 3)
        {
 -      /* If just tried and failed to reuse lookahead token after an
 -       error, discard it.  */
 -
 -      if (yychar <= yyeof_)
 -        {
 -        /* Return failure if at end of input.  */
 -        if (yychar == yyeof_)
 -          YYABORT;
 -        }
 -      else
 -        {
 -          yydestruct_ ("Error: discarding", yytoken, &yylval, &yylloc);
 -          yychar = yyempty_;
 -        }
 +        /* If just tried and failed to reuse lookahead token after an
 +           error, discard it.  */
 +
 +        /* Return failure if at end of input.  */
 +        if (yyla.type == yyeof_)
 +          YYABORT;
 +        else if (!yyempty)
 +          {
 +            yy_destroy_ ("Error: discarding", yyla);
 +            yyempty = true;
 +          }
        }
  
      /* Else will try to reuse lookahead token after shifting the error
         YYERROR and the label yyerrorlab therefore never appears in user
         code.  */
      if (false)
 -      goto yyerrorlab;
 -
 -    yyerror_range[1] = yylocation_stack_[yylen - 1];
 +      goto yyerrorlab;]b4_locations_if([[
 +    yyerror_range[1].location = yystack_[yylen - 1].location;]])b4_variant_if([[
 +    /* $$ was initialized before running the user action.  */
 +    yy_destroy_ ("Error: discarding", yylhs);]])[
      /* Do not reclaim the symbols of the rule which action triggered
         this YYERROR.  */
      yypop_ (yylen);
      yylen = 0;
 -    yystate = yystate_stack_[0];
      goto yyerrlab1;
  
    /*-------------------------------------------------------------.
    | yyerrlab1 -- common code for both syntax error and YYERROR.  |
    `-------------------------------------------------------------*/
    yyerrlab1:
 -    yyerrstatus_ = 3; /* Each real token shifted decrements this.  */
 -
 -    for (;;)
 -      {
 -      yyn = yypact_[yystate];
 -      if (!yy_pact_value_is_default_ (yyn))
 -      {
 -        yyn += yyterror_;
 -        if (0 <= yyn && yyn <= yylast_ && yycheck_[yyn] == yyterror_)
 -          {
 -            yyn = yytable_[yyn];
 -            if (0 < yyn)
 -              break;
 -          }
 -      }
 -
 -      /* Pop the current state because it cannot handle the error token.  */
 -      if (yystate_stack_.height () == 1)
 -      YYABORT;
 -
 -      yyerror_range[1] = yylocation_stack_[0];
 -      yydestruct_ ("Error: popping",
 -                   yystos_[yystate],
 -                   &yysemantic_stack_[0], &yylocation_stack_[0]);
 -      yypop_ ();
 -      yystate = yystate_stack_[0];
 -      YY_STACK_PRINT ();
 -      }
 -
 -    yyerror_range[2] = yylloc;
 -    // Using YYLLOC is tempting, but would change the location of
 -    // the lookahead.  YYLOC is available though.
 -    YYLLOC_DEFAULT (yyloc, yyerror_range, 2);
 -    yysemantic_stack_.push (yylval);
 -    yylocation_stack_.push (yyloc);
 +    yyerrstatus_ = 3;   /* Each real token shifted decrements this.  */
 +    {
 +      stack_symbol_type error_token;
 +      for (;;)
 +        {
 +          yyn = yypact_[yystack_[0].state];
 +          if (!yy_pact_value_is_default_ (yyn))
 +            {
 +              yyn += yyterror_;
 +              if (0 <= yyn && yyn <= yylast_ && yycheck_[yyn] == yyterror_)
 +                {
 +                  yyn = yytable_[yyn];
 +                  if (0 < yyn)
 +                    break;
 +                }
 +            }
  
 -    /* Shift the error token.  */
 -    YY_SYMBOL_PRINT ("Shifting", yystos_[yyn],
 -                   &yysemantic_stack_[0], &yylocation_stack_[0]);
 +          // Pop the current state because it cannot handle the error token.
 +          if (yystack_.size () == 1)
 +            YYABORT;
 +]b4_locations_if([[
 +          yyerror_range[1].location = yystack_[0].location;]])[
 +          yy_destroy_ ("Error: popping", yystack_[0]);
 +          yypop_ ();
 +          YY_STACK_PRINT ();
 +        }
 +]b4_locations_if([[
 +      yyerror_range[2].location = yyla.location;
 +      YYLLOC_DEFAULT (error_token.location, yyerror_range, 2);]])[
  
 -    yystate = yyn;
 +      /* Shift the error token.  */
 +      error_token.state = yyn;
 +      yypush_ ("Shifting", error_token);
 +    }
      goto yynewstate;
  
      /* Accept.  */
      goto yyreturn;
  
    yyreturn:
 -    if (yychar != yyempty_)
 -      {
 -        /* Make sure we have latest lookahead translation.  See comments
 -           at user semantic actions for why this is necessary.  */
 -        yytoken = yytranslate_ (yychar);
 -        yydestruct_ ("Cleanup: discarding lookahead", yytoken, &yylval,
 -                     &yylloc);
 -      }
 +    if (!yyempty)
 +      yy_destroy_ ("Cleanup: discarding lookahead", yyla);
  
      /* Do not reclaim the symbols of the rule which action triggered
         this YYABORT or YYACCEPT.  */
      yypop_ (yylen);
 -    while (yystate_stack_.height () != 1)
 +    while (yystack_.size () != 1)
        {
 -      yydestruct_ ("Cleanup: popping",
 -                 yystos_[yystate_stack_[0]],
 -                 &yysemantic_stack_[0],
 -                 &yylocation_stack_[0]);
 -      yypop_ ();
 +        yy_destroy_ ("Cleanup: popping", yystack_[0]);
 +        yypop_ ();
        }
  
      return yyresult;
    }
  
 +  void
 +  ]b4_parser_class_name[::error (const syntax_error& yyexc)
 +  {
 +    error (]b4_args(b4_locations_if([yyexc.location]),
 +                    [[yyexc.what()]])[);
 +  }
 +
    // Generate an error message.
    std::string
    ]b4_parser_class_name[::yysyntax_error_ (]dnl
 -b4_error_verbose_if([int yystate, int yytoken],
 +b4_error_verbose_if([state_type yystate, int yytoken],
                      [int, int])[)
    {]b4_error_verbose_if([[
      std::string yyres;
           a consistent state with a default action.  There might have
           been a previous inconsistent state, consistent state with a
           non-default action, or user semantic action that manipulated
 -         yychar.
 +         yyla.  (However, yyla is currently not documented for users.)
         - Of course, the expected token list depends on states to have
           correct lookahead information, and it depends on the parser not
           to perform extra reductions after fetching a lookahead from the
    }
  
  
 -  /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
 -     STATE-NUM.  */
    const ]b4_int_type(b4_pact_ninf, b4_pact_ninf) b4_parser_class_name::yypact_ninf_ = b4_pact_ninf[;
 -  const ]b4_int_type_for([b4_pact])[
 -  ]b4_parser_class_name[::yypact_[] =
 -  {
 -    ]b4_pact[
 -  };
 -
 -  /* YYDEFACT[S] -- default reduction number in state S.  Performed when
 -     YYTABLE doesn't specify something else to do.  Zero means the
 -     default is an error.  */
 -  const ]b4_int_type_for([b4_defact])[
 -  ]b4_parser_class_name[::yydefact_[] =
 -  {
 -    ]b4_defact[
 -  };
 -
 -  /* YYPGOTO[NTERM-NUM].  */
 -  const ]b4_int_type_for([b4_pgoto])[
 -  ]b4_parser_class_name[::yypgoto_[] =
 -  {
 -    ]b4_pgoto[
 -  };
 -
 -  /* YYDEFGOTO[NTERM-NUM].  */
 -  const ]b4_int_type_for([b4_defgoto])[
 -  ]b4_parser_class_name[::yydefgoto_[] =
 -  {
 -    ]b4_defgoto[
 -  };
  
 -  /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
 -     positive, shift that token.  If negative, reduce the rule which
 -     number is the opposite.  If YYTABLE_NINF_, syntax error.  */
    const ]b4_int_type(b4_table_ninf, b4_table_ninf) b4_parser_class_name::yytable_ninf_ = b4_table_ninf[;
 -  const ]b4_int_type_for([b4_table])[
 -  ]b4_parser_class_name[::yytable_[] =
 -  {
 -    ]b4_table[
 -  };
  
 -  /* YYCHECK.  */
 -  const ]b4_int_type_for([b4_check])[
 -  ]b4_parser_class_name[::yycheck_[] =
 -  {
 -    ]b4_check[
 -  };
 -
 -  /* STOS_[STATE-NUM] -- The (internal number of the) accessing
 -     symbol of state STATE-NUM.  */
 -  const ]b4_int_type_for([b4_stos])[
 -  ]b4_parser_class_name[::yystos_[] =
 -  {
 -    ]b4_stos[
 -  };
 -
 -#if ]b4_api_PREFIX[DEBUG
 -  /* TOKEN_NUMBER_[YYLEX-NUM] -- Internal symbol number corresponding
 -     to YYLEX-NUM.  */
 -  const ]b4_int_type_for([b4_toknum])[
 -  ]b4_parser_class_name[::yytoken_number_[] =
 -  {
 -    ]b4_toknum[
 -  };
 -#endif
 -
 -  /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 -  const ]b4_int_type_for([b4_r1])[
 -  ]b4_parser_class_name[::yyr1_[] =
 -  {
 -    ]b4_r1[
 -  };
 -
 -  /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
 -  const ]b4_int_type_for([b4_r2])[
 -  ]b4_parser_class_name[::yyr2_[] =
 -  {
 -    ]b4_r2[
 -  };
 +]b4_parser_tables_define[
  
  ]b4_token_table_if([], [[#if ]b4_api_PREFIX[DEBUG]])[
    /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
    const char*
    const ]b4_parser_class_name[::yytname_[] =
    {
 -    ]b4_tname[
 +  ]b4_tname[
    };
  
  ]b4_token_table_if([[#if ]b4_api_PREFIX[DEBUG]])[
 -  /* YYRHS -- A `-1'-separated list of the rules' RHS.  */
 -  const ]b4_parser_class_name[::rhs_number_type
 -  ]b4_parser_class_name[::yyrhs_[] =
 -  {
 -    ]b4_rhs[
 -  };
 -
 -  /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
 -     YYRHS.  */
 -  const ]b4_int_type_for([b4_prhs])[
 -  ]b4_parser_class_name[::yyprhs_[] =
 -  {
 -    ]b4_prhs[
 -  };
 -
 -  /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
 -  const ]b4_int_type_for([b4_rline])[
 -  ]b4_parser_class_name[::yyrline_[] =
 -  {
 -    ]b4_rline[
 -  };
 +]b4_integral_parser_table_define([rline], [b4_rline])[
  
    // Print the state stack on the debug stream.
    void
    ]b4_parser_class_name[::yystack_print_ ()
    {
      *yycdebug_ << "Stack now";
 -    for (state_stack_type::const_iterator i = yystate_stack_.begin ();
 -       i != yystate_stack_.end (); ++i)
 -      *yycdebug_ << ' ' << *i;
 +    for (stack_type::const_iterator
 +           i = yystack_.begin (),
 +           i_end = yystack_.end ();
 +         i != i_end; ++i)
 +      *yycdebug_ << ' ' << i->state;
      *yycdebug_ << std::endl;
    }
  
      int yynrhs = yyr2_[yyrule];
      /* Print the symbols being reduced, and their result.  */
      *yycdebug_ << "Reducing stack by rule " << yyrule - 1
 -             << " (line " << yylno << "):" << std::endl;
 +               << " (line " << yylno << "):" << std::endl;
      /* The symbols being reduced.  */
      for (int yyi = 0; yyi < yynrhs; yyi++)
        YY_SYMBOL_PRINT ("   $" << yyi + 1 << " =",
 -                     yyrhs_[yyprhs_[yyrule] + yyi],
 -                     &]b4_rhs_value(yynrhs, yyi + 1)[,
 -                     &]b4_rhs_location(yynrhs, yyi + 1)[);
 +                       ]b4_rhs_data(yynrhs, yyi + 1)[);
    }
  #endif // ]b4_api_PREFIX[DEBUG
  
 -  /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
 -  ]b4_parser_class_name[::token_number_type
 -  ]b4_parser_class_name[::yytranslate_ (int t)
 -  {
 -    static
 -    const token_number_type
 -    translate_table[] =
 -    {
 -      ]b4_translate[
 -    };
 -    if ((unsigned int) t <= yyuser_token_number_max_)
 -      return translate_table[t];
 -    else
 -      return yyundef_token_;
 -  }
 -
 -  const int ]b4_parser_class_name[::yyeof_ = 0;
 -  const int ]b4_parser_class_name[::yylast_ = ]b4_last[;
 -  const int ]b4_parser_class_name[::yynnts_ = ]b4_nterms_number[;
 -  const int ]b4_parser_class_name[::yyempty_ = -2;
 -  const int ]b4_parser_class_name[::yyfinal_ = ]b4_final_state_number[;
 -  const int ]b4_parser_class_name[::yyterror_ = 1;
 -  const int ]b4_parser_class_name[::yyerrcode_ = 256;
 -  const int ]b4_parser_class_name[::yyntokens_ = ]b4_tokens_number[;
 -
 -  const unsigned int ]b4_parser_class_name[::yyuser_token_number_max_ = ]b4_user_token_number_max[;
 -  const ]b4_parser_class_name[::token_number_type ]b4_parser_class_name[::yyundef_token_ = ]b4_undef_token_number[;
 -
 +]b4_lex_symbol_if([], [b4_yytranslate_define])[
  ]b4_namespace_close[
 -]b4_epilogue
 +]b4_epilogue[]dnl
  m4_divert_pop(0)
 +m4_popdef([b4_copyright_years])dnl
diff --combined data/lalr1.java
index d3729c6ef4fe7cb2823f9187371a589bf52052ce,d1410a10cf806b6598d71e90c44bc1d38a1e22a5..1cfaef38caf15686beb2d9731ae46215d5af92b5
  
  m4_include(b4_pkgdatadir/[java.m4])
  
 -b4_defines_if([b4_fatal([%s: %%defines does not make sense in Java], [b4_skeleton])])
 -m4_ifval(m4_defn([b4_symbol_destructors]),
 -        [b4_fatal([%s: %%destructor does not make sense in Java], [b4_skeleton])],
 -        [])
 +b4_defines_if([b4_fatal([%s: %%defines does not make sense in Java],
 +              [b4_skeleton])])
 +
 +# We don't depend on %debug in Java, but pacify warnings about non-used flags.
 +b4_parse_trace_if([0], [0])
 +
 +m4_define([b4_symbol_no_destructor_assert],
 +[b4_symbol_if([$1], [has_destructor],
 +              [b4_fatal([%s: %s: %%destructor does not make sense in Java],
 +                        [b4_skeleton],
 +                        [b4_symbol_action_location([$1], [destructor])])])])
 +b4_symbol_foreach([b4_symbol_no_destructor_assert])
  
  m4_divert_push(0)dnl
  @output(b4_parser_file_name@)@
@@@ -37,16 -29,14 +37,16 @@@ b4_copyright([Skeleton implementation f
  
  b4_percent_define_ifdef([package], [package b4_percent_define_get([package]);
  ])[/* First part of user declarations.  */
 -]b4_pre_prologue
 +]b4_user_pre_prologue
 +b4_user_post_prologue
  b4_percent_code_get([[imports]])
  [/**
   * A Bison parser, automatically generated from <tt>]m4_bpatsubst(b4_file_name, [^"\(.*\)"$], [\1])[</tt>.
   *
   * @@author LALR (1) parser skeleton written by Paolo Bonzini.
   */
 -]b4_public_if([public ])dnl
 +]b4_percent_define_get3([annotations], [], [ ])dnl
 +b4_public_if([public ])dnl
  b4_abstract_if([abstract ])dnl
  b4_final_if([final ])dnl
  b4_strictfp_if([strictfp ])dnl
@@@ -55,22 -45,9 +55,22 @@@ b4_percent_define_get3([extends], [ ext
  b4_percent_define_get3([implements], [ implements ])[
  {
    ]b4_identification[
 -
 +]b4_error_verbose_if([[
    /** True if verbose error messages are enabled.  */
 -  public boolean errorVerbose = ]b4_flag_value([error_verbose]);
 +  private boolean yyErrorVerbose = true;
 +
 +  /**
 +   * Return whether verbose error messages are enabled.
 +   */
 +  public final boolean getErrorVerbose() { return yyErrorVerbose; }
 +
 +  /**
 +   * Set the verbosity of error messages.
 +   * @@param verbose True to request verbose error messages.
 +   */
 +  public final void setErrorVerbose(boolean verbose)
 +  { yyErrorVerbose = verbose; }
 +]])
  
  b4_locations_if([[
    /**
  
  ]])
  
 -[  /** Token returned by the scanner to signal the end of its input.  */
 -  public static final int EOF = 0;]
 -
 -b4_token_enums(b4_tokens)
 -
    b4_locations_if([[
    private ]b4_location_type[ yylloc (YYStack rhs, int n)
    {
     * parser <tt>]b4_parser_class_name[</tt>.
     */
    public interface Lexer {
 +    /** Token returned by the scanner to signal the end of its input.  */
 +    public static final int EOF = 0;
 +
 +]b4_token_enums[
 +
      ]b4_locations_if([[/**
       * Method to retrieve the beginning position of the last scanned token.
       * @@return the position at which the last scanned token starts.  */
       *
       * ]b4_locations_if([[@@param loc The location of the element to which the
       *                error message is related]])[
 -     * @@param s The string for the error message.  */
 -     void yyerror (]b4_locations_if([b4_location_type[ loc, ]])[String s);]
 +     * @@param msg The string for the error message.  */
 +     void yyerror (]b4_locations_if([b4_location_type[ loc, ]])[String msg);]
    }
  
    b4_lexer_if([[private class YYLexer implements Lexer {
@@@ -180,9 -157,7 +180,9 @@@ b4_lexer_if([
    /**
     * Instantiates the Bison-generated parser.
     */
 -  public ]b4_parser_class_name (b4_parse_param_decl([b4_lex_param_decl])[) {
 +  public ]b4_parser_class_name (b4_parse_param_decl([b4_lex_param_decl])[) ]b4_maybe_throws([b4_init_throws])[
 +  {
 +    ]b4_percent_code_get([[init]])[
      this.yylexer = new YYLexer(]b4_lex_param_call[);
      ]b4_parse_param_cons[
    }
     * Instantiates the Bison-generated parser.
     * @@param yylexer The scanner that will supply tokens to the parser.
     */
 -  b4_lexer_if([[protected]], [[public]]) b4_parser_class_name[ (]b4_parse_param_decl([[Lexer yylexer]])[) {
 +  b4_lexer_if([[protected]], [[public]]) b4_parser_class_name[ (]b4_parse_param_decl([[Lexer yylexer]])[) ]b4_maybe_throws([b4_init_throws])[
 +  {
 +    ]b4_percent_code_get([[init]])[
      this.yylexer = yylexer;
      ]b4_parse_param_cons[
    }
     */
    public final void setDebugLevel(int level) { yydebug = level; }
  
 -  private final int yylex () ]b4_maybe_throws([b4_lex_throws]) [{
 -    return yylexer.yylex ();
 +  /**
 +   * Print an error message via the lexer.
 +   *]b4_locations_if([[ Use a <code>null</code> location.]])[
 +   * @@param msg The error message.
 +   */
 +  public final void yyerror (String msg)
 +  {
 +    yylexer.yyerror (]b4_locations_if([[(]b4_location_type[)null, ]])[msg);
    }
 -  protected final void yyerror (]b4_locations_if([b4_location_type[ loc, ]])[String s) {
 -    yylexer.yyerror (]b4_locations_if([loc, ])[s);
 +]b4_locations_if([[
 +  /**
 +   * Print an error message via the lexer.
 +   * @@param loc The location associated with the message.
 +   * @@param msg The error message.
 +   */
 +  public final void yyerror (]b4_location_type[ loc, String msg)
 +  {
 +    yylexer.yyerror (loc, msg);
    }
  
 -  ]b4_locations_if([
 -  protected final void yyerror (String s) {
 -    yylexer.yyerror ((]b4_location_type[)null, s);
 -  }
 -  protected final void yyerror (]b4_position_type[ loc, String s) {
 -    yylexer.yyerror (new ]b4_location_type[ (loc), s);
 -  }])
 +  /**
 +   * Print an error message via the lexer.
 +   * @@param pos The position associated with the message.
 +   * @@param msg The error message.
 +   */
 +  public final void yyerror (]b4_position_type[ pos, String msg)
 +  {
 +    yylexer.yyerror (new ]b4_location_type[ (pos), msg);
 +  }]])
  
    [protected final void yycdebug (String s) {
      if (yydebug > 0)
      public int height = -1;
  
      public final void push (int state, ]b4_yystype[ value]dnl
 -                          b4_locations_if([, ]b4_location_type[ loc])[) {
 +                            b4_locations_if([, ]b4_location_type[ loc])[) {
        height++;
        if (size == height)
          {
 -        int[] newStateStack = new int[size * 2];
 -        System.arraycopy (stateStack, 0, newStateStack, 0, height);
 -        stateStack = newStateStack;
 -        ]b4_locations_if([[
 -        ]b4_location_type[[] newLocStack = new ]b4_location_type[[size * 2];
 -        System.arraycopy (locStack, 0, newLocStack, 0, height);
 -        locStack = newLocStack;]])
 -
 -        b4_yystype[[] newValueStack = new ]b4_yystype[[size * 2];
 -        System.arraycopy (valueStack, 0, newValueStack, 0, height);
 -        valueStack = newValueStack;
 -
 -        size *= 2;
 -      }
 +          int[] newStateStack = new int[size * 2];
 +          System.arraycopy (stateStack, 0, newStateStack, 0, height);
 +          stateStack = newStateStack;
 +          ]b4_locations_if([[
 +          ]b4_location_type[[] newLocStack = new ]b4_location_type[[size * 2];
 +          System.arraycopy (locStack, 0, newLocStack, 0, height);
 +          locStack = newLocStack;]])
 +
 +          b4_yystype[[] newValueStack = new ]b4_yystype[[size * 2];
 +          System.arraycopy (valueStack, 0, newValueStack, 0, height);
 +          valueStack = newValueStack;
 +
 +          size *= 2;
 +        }
  
        stateStack[height] = state;
        ]b4_locations_if([[locStack[height] = loc;]])[
      public final void pop (int num) {
        // Avoid memory leaks... garbage collection is a white lie!
        if (num > 0) {
 -      java.util.Arrays.fill (valueStack, height - num + 1, height + 1, null);
 +        java.util.Arrays.fill (valueStack, height - num + 1, height + 1, null);
          ]b4_locations_if([[java.util.Arrays.fill (locStack, height - num + 1, height + 1, null);]])[
        }
        height -= num;
  
        for (int i = 0; i <= height; i++)
          {
 -        out.print (' ');
 -        out.print (stateStack[i]);
 +          out.print (' ');
 +          out.print (stateStack[i]);
          }
        out.println ();
      }
  
      switch (yyn)
        {
 -      ]b4_user_actions[
 -      default: break;
 +        ]b4_user_actions[
 +        default: break;
        }
  
      yy_symbol_print ("-> $$ =", yyr1_[yyn], yyval]b4_locations_if([, yyloc])[);
      yyn = yyr1_[yyn];
      int yystate = yypgoto_[yyn - yyntokens_] + yystack.stateAt (0);
      if (0 <= yystate && yystate <= yylast_
 -      && yycheck_[yystate] == yystack.stateAt (0))
 +        && yycheck_[yystate] == yystack.stateAt (0))
        yystate = yytable_[yystate];
      else
        yystate = yydefgoto_[yyn - yyntokens_];
      return YYNEWSTATE;
    }
  
 +]b4_error_verbose_if([[
    /* Return YYSTR after stripping away unnecessary quotes and
       backslashes, so that it's suitable for yyerror.  The heuristic is
       that double-quoting is unnecessary unless the string contains an
                break strip_quotes;
  
              case '\\':
 -            if (yystr.charAt(++i) != '\\')
 +              if (yystr.charAt(++i) != '\\')
                  break strip_quotes;
                /* Fall through.  */
              default:
  
      return yystr;
    }
 +]])[
  
    /*--------------------------------.
    | Print this symbol on YYOUTPUT.  |
    `--------------------------------*/
  
    private void yy_symbol_print (String s, int yytype,
 -                               ]b4_yystype[ yyvaluep]dnl
 -                               b4_locations_if([, Object yylocationp])[)
 +                                 ]b4_yystype[ yyvaluep]dnl
 +                                 b4_locations_if([, Object yylocationp])[)
    {
      if (yydebug > 0)
      yycdebug (s + (yytype < yyntokens_ ? " token " : " nterm ")
 -            + yytname_[yytype] + " ("]b4_locations_if([
 -            + yylocationp + ": "])[
 -            + (yyvaluep == null ? "(null)" : yyvaluep.toString ()) + ")");
 +              + yytname_[yytype] + " ("]b4_locations_if([
 +              + yylocationp + ": "])[
 +              + (yyvaluep == null ? "(null)" : yyvaluep.toString ()) + ")");
    }
  
    /**
      yyerrstatus_ = 0;
  
  ]m4_ifdef([b4_initial_action], [
- m4_pushdef([b4_at_dollar],     [yylloc])dnl
- m4_pushdef([b4_dollar_dollar], [yylval])dnl
+ b4_dollar_pushdef([yylval], [], [yylloc])dnl
 -/* User initialization code.  */
 -b4_user_initial_action
 +    /* User initialization code.  */
 +    b4_user_initial_action
- m4_popdef([b4_dollar_dollar])dnl
- m4_popdef([b4_at_dollar])])dnl
+ b4_dollar_popdef])[]dnl
  
    [  /* Initialize the stack.  */
      yystack.push (yystate, yylval]b4_locations_if([, yylloc])[);
        switch (label)
        {
          /* New state.  Unlike in the C/C++ skeletons, the state is already
 -         pushed when we come here.  */
 +           pushed when we come here.  */
        case YYNEWSTATE:
          yycdebug ("Entering state " + yystate + "\n");
          if (yydebug > 0)
          if (yy_pact_value_is_default_ (yyn))
            {
              label = YYDEFAULT;
 -          break;
 +            break;
            }
  
          /* Read a lookahead token.  */
          if (yychar == yyempty_)
            {
 -          yycdebug ("Reading a token: ");
 -          yychar = yylex ();]
 +            yycdebug ("Reading a token: ");
 +            yychar = yylexer.yylex ();]
              b4_locations_if([[
 -          yylloc = new ]b4_location_type[(yylexer.getStartPos (),
 -                                          yylexer.getEndPos ());]])
 +            yylloc = new ]b4_location_type[(yylexer.getStartPos (),
 +                            yylexer.getEndPos ());]])
              yylval = yylexer.getLVal ();[
            }
  
          /* Convert token to internal form.  */
 -        if (yychar <= EOF)
 +        if (yychar <= Lexer.EOF)
            {
 -          yychar = yytoken = EOF;
 -          yycdebug ("Now at end of input.\n");
 +            yychar = yytoken = Lexer.EOF;
 +            yycdebug ("Now at end of input.\n");
            }
          else
            {
 -          yytoken = yytranslate_ (yychar);
 -          yy_symbol_print ("Next token is", yytoken,
 -                           yylval]b4_locations_if([, yylloc])[);
 +            yytoken = yytranslate_ (yychar);
 +            yy_symbol_print ("Next token is", yytoken,
 +                             yylval]b4_locations_if([, yylloc])[);
            }
  
          /* If the proper action on seeing token YYTOKEN is to reduce or to
          /* <= 0 means reduce or error.  */
          else if ((yyn = yytable_[yyn]) <= 0)
            {
 -          if (yy_table_value_is_error_ (yyn))
 -            label = YYERRLAB;
 -          else
 -            {
 -              yyn = -yyn;
 -              label = YYREDUCE;
 -            }
 +            if (yy_table_value_is_error_ (yyn))
 +              label = YYERRLAB;
 +            else
 +              {
 +                yyn = -yyn;
 +                label = YYREDUCE;
 +              }
            }
  
          else
            {
              /* Shift the lookahead token.  */
 -          yy_symbol_print ("Shifting", yytoken,
 -                           yylval]b4_locations_if([, yylloc])[);
 +            yy_symbol_print ("Shifting", yytoken,
 +                             yylval]b4_locations_if([, yylloc])[);
  
              /* Discard the token being shifted.  */
              yychar = yyempty_;
        case YYREDUCE:
          yylen = yyr2_[yyn];
          label = yyaction (yyn, yystack, yylen);
 -      yystate = yystack.stateAt (0);
 +        yystate = yystack.stateAt (0);
          break;
  
        /*------------------------------------.
          ]b4_locations_if([yyerrloc = yylloc;])[
          if (yyerrstatus_ == 3)
            {
 -          /* If just tried and failed to reuse lookahead token after an
 -           error, discard it.  */
 -
 -          if (yychar <= EOF)
 -            {
 -            /* Return failure if at end of input.  */
 -            if (yychar == EOF)
 -              return false;
 -            }
 -          else
 -            yychar = yyempty_;
 +        /* If just tried and failed to reuse lookahead token after an
 +         error, discard it.  */
 +
 +        if (yychar <= Lexer.EOF)
 +          {
 +          /* Return failure if at end of input.  */
 +          if (yychar == Lexer.EOF)
 +            return false;
 +          }
 +        else
 +              yychar = yyempty_;
            }
  
          /* Else will try to reuse lookahead token after shifting the error
        | yyerrlab1 -- common code for both syntax error and YYERROR.  |
        `-------------------------------------------------------------*/
        case YYERRLAB1:
 -        yyerrstatus_ = 3;     /* Each real token shifted decrements this.  */
 +        yyerrstatus_ = 3;       /* Each real token shifted decrements this.  */
  
          for (;;)
            {
 -          yyn = yypact_[yystate];
 -          if (!yy_pact_value_is_default_ (yyn))
 -            {
 -              yyn += yyterror_;
 -              if (0 <= yyn && yyn <= yylast_ && yycheck_[yyn] == yyterror_)
 -                {
 -                  yyn = yytable_[yyn];
 -                  if (0 < yyn)
 -                    break;
 -                }
 -            }
 -
 -          /* Pop the current state because it cannot handle the error token.  */
 -          if (yystack.height == 0)
 -            return false;
 -
 -          ]b4_locations_if([yyerrloc = yystack.locationAt (0);])[
 -          yystack.pop ();
 -          yystate = yystack.stateAt (0);
 -          if (yydebug > 0)
 -            yystack.print (yyDebugStream);
 +            yyn = yypact_[yystate];
 +            if (!yy_pact_value_is_default_ (yyn))
 +              {
 +                yyn += yyterror_;
 +                if (0 <= yyn && yyn <= yylast_ && yycheck_[yyn] == yyterror_)
 +                  {
 +                    yyn = yytable_[yyn];
 +                    if (0 < yyn)
 +                      break;
 +                  }
 +              }
 +
 +            /* Pop the current state because it cannot handle the error token.  */
 +            if (yystack.height == 0)
 +              return false;
 +
 +            ]b4_locations_if([yyerrloc = yystack.locationAt (0);])[
 +            yystack.pop ();
 +            yystate = yystack.stateAt (0);
 +            if (yydebug > 0)
 +              yystack.print (yyDebugStream);
            }
  
 -      ]b4_locations_if([
 -      /* Muck with the stack to setup for yylloc.  */
 -      yystack.push (0, null, yylloc);
 -      yystack.push (0, null, yyerrloc);
 +        ]b4_locations_if([
 +        /* Muck with the stack to setup for yylloc.  */
 +        yystack.push (0, null, yylloc);
 +        yystack.push (0, null, yyerrloc);
          yyloc = yylloc (yystack, 2);
 -      yystack.pop (2);])[
 +        yystack.pop (2);])[
  
          /* Shift the error token.  */
          yy_symbol_print ("Shifting", yystos_[yyn],
 -                       yylval]b4_locations_if([, yyloc])[);
 +                         yylval]b4_locations_if([, yyloc])[);
  
          yystate = yyn;
 -      yystack.push (yyn, yylval]b4_locations_if([, yyloc])[);
 +        yystack.push (yyn, yylval]b4_locations_if([, yyloc])[);
          label = YYNEWSTATE;
          break;
  
  
    // Generate an error message.
    private String yysyntax_error (int yystate, int tok)
 -  {
 -    if (errorVerbose)
 +  {]b4_error_verbose_if([[
 +    if (yyErrorVerbose)
        {
          /* There are many possibilities here to consider:
 -           - Assume YYFAIL is not used.  It's too flawed to consider.
 -             See
 -             <http://lists.gnu.org/archive/html/bison-patches/2009-12/msg00024.html>
 -             for details.  YYERROR is fine as it does not invoke this
 -             function.
             - If this state is a consistent state with a default action,
               then the only way this function was invoked is if the
               default action is an error action.  In that case, don't
              return res.toString ();
            }
        }
 -
 +]])[
      return "syntax error";
    }
  
      return yyvalue == yytable_ninf_;
    }
  
 -  /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
 -     STATE-NUM.  */
    private static final ]b4_int_type_for([b4_pact])[ yypact_ninf_ = ]b4_pact_ninf[;
 -  private static final ]b4_int_type_for([b4_pact])[ yypact_[] =
 -  {
 -    ]b4_pact[
 -  };
 -
 -  /* YYDEFACT[S] -- default reduction number in state S.  Performed when
 -     YYTABLE doesn't specify something else to do.  Zero means the
 -     default is an error.  */
 -  private static final ]b4_int_type_for([b4_defact])[ yydefact_[] =
 -  {
 -    ]b4_defact[
 -  };
 -
 -  /* YYPGOTO[NTERM-NUM].  */
 -  private static final ]b4_int_type_for([b4_pgoto])[ yypgoto_[] =
 -  {
 -    ]b4_pgoto[
 -  };
 -
 -  /* YYDEFGOTO[NTERM-NUM].  */
 -  private static final ]b4_int_type_for([b4_defgoto])[
 -  yydefgoto_[] =
 -  {
 -    ]b4_defgoto[
 -  };
 -
 -  /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
 -     positive, shift that token.  If negative, reduce the rule which
 -     number is the opposite.  If YYTABLE_NINF_, syntax error.  */
    private static final ]b4_int_type_for([b4_table])[ yytable_ninf_ = ]b4_table_ninf[;
 -  private static final ]b4_int_type_for([b4_table])[
 -  yytable_[] =
 -  {
 -    ]b4_table[
 -  };
  
 -  /* YYCHECK.  */
 -  private static final ]b4_int_type_for([b4_check])[
 -  yycheck_[] =
 -  {
 -    ]b4_check[
 -  };
 -
 -  /* STOS_[STATE-NUM] -- The (internal number of the) accessing
 -     symbol of state STATE-NUM.  */
 -  private static final ]b4_int_type_for([b4_stos])[
 -  yystos_[] =
 -  {
 -    ]b4_stos[
 -  };
 -
 -  /* TOKEN_NUMBER_[YYLEX-NUM] -- Internal symbol number corresponding
 -     to YYLEX-NUM.  */
 -  private static final ]b4_int_type_for([b4_toknum])[
 -  yytoken_number_[] =
 -  {
 -    ]b4_toknum[
 -  };
 -
 -  /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 -  private static final ]b4_int_type_for([b4_r1])[
 -  yyr1_[] =
 -  {
 -    ]b4_r1[
 -  };
 -
 -  /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
 -  private static final ]b4_int_type_for([b4_r2])[
 -  yyr2_[] =
 -  {
 -    ]b4_r2[
 -  };
 +  ]b4_parser_tables_define[
 +  ]b4_integral_parser_table_define([token_number], [b4_toknum],
 +     [TOKEN_NUMBER_[YYLEX-NUM] -- Internal symbol number corresponding
 +     to YYLEX-NUM.])[
  
    /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
       First, the terminals, then, starting at \a yyntokens_, nonterminals.  */
 -  private static final String yytname_[] =
 -  {
 -    ]b4_tname[
 -  };
 -
 -  /* YYRHS -- A `-1'-separated list of the rules' RHS.  */
 -  private static final ]b4_int_type_for([b4_rhs])[ yyrhs_[] =
 -  {
 -    ]b4_rhs[
 -  };
 +  ]b4_typed_parser_table_define([String], [tname], [b4_tname])[
  
 -  /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
 -     YYRHS.  */
 -  private static final ]b4_int_type_for([b4_prhs])[ yyprhs_[] =
 -  {
 -    ]b4_prhs[
 -  };
 -
 -  /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
 -  private static final ]b4_int_type_for([b4_rline])[ yyrline_[] =
 -  {
 -    ]b4_rline[
 -  };
 +  ]b4_integral_parser_table_define([rline], [b4_rline],
 +  [YYRLINE[YYN] -- Source line where rule number YYN was defined.])[
  
    // Report on the debug stream that the rule yyrule is going to be reduced.
    private void yy_reduce_print (int yyrule, YYStack yystack)
      int yynrhs = yyr2_[yyrule];
      /* Print the symbols being reduced, and their result.  */
      yycdebug ("Reducing stack by rule " + (yyrule - 1)
 -            + " (line " + yylno + "), ");
 +              + " (line " + yylno + "), ");
  
      /* The symbols being reduced.  */
      for (int yyi = 0; yyi < yynrhs; yyi++)
        yy_symbol_print ("   $" + (yyi + 1) + " =",
 -                     yyrhs_[yyprhs_[yyrule] + yyi],
 -                     ]b4_rhs_value(yynrhs, yyi + 1)b4_locations_if([,
 -                     b4_rhs_location(yynrhs, yyi + 1)])[);
 +                       yystos_[yystack.stateAt(yynrhs - (yyi + 1))],
 +                       ]b4_rhs_value(yynrhs, yyi + 1)b4_locations_if([,
 +                       b4_rhs_location(yynrhs, yyi + 1)])[);
    }
  
    /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
 -  private static final ]b4_int_type_for([b4_translate])[ yytranslate_table_[] =
 -  {
 -    ]b4_translate[
 -  };
 +  ]b4_integral_parser_table_define([translate_table], [b4_translate])[
  
    private static final ]b4_int_type_for([b4_translate])[ yytranslate_ (int t)
    {
@@@ -875,5 -924,5 +873,5 @@@ b4_percent_code_get[]dn
  
  }
  
 -b4_epilogue
 +b4_epilogue[]dnl
  m4_divert_pop(0)dnl
diff --combined data/local.mk
index 6337f769195f2b7c6a1389297bad21a4b55035c5,0000000000000000000000000000000000000000..b8db2d64af05571b20879b47b199053946f4d26a
mode 100644,000000..100644
--- /dev/null
@@@ -1,44 -1,0 +1,45 @@@
 +## Copyright (C) 2002, 2005-2012 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
 +## the Free Software Foundation, either version 3 of the License, or
 +## (at your option) any later version.
 +##
 +## This program is distributed in the hope that it will be useful,
 +## but WITHOUT ANY WARRANTY; without even the implied warranty of
 +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +## GNU General Public License for more details.
 +##
 +## You should have received a copy of the GNU General Public License
 +## along with this program.  If not, see <http://www.gnu.org/licenses/>.
 +
 +dist_pkgdata_DATA =                             \
 +  data/README                                   \
 +  data/bison.m4                                 \
 +  data/c++-skel.m4                              \
 +  data/c++.m4                                   \
++  data/c-like.m4                                \
 +  data/c-skel.m4                                \
 +  data/c.m4                                     \
 +  data/glr.c                                    \
 +  data/glr.cc                                   \
 +  data/java-skel.m4                             \
 +  data/java.m4                                  \
 +  data/lalr1.cc                                 \
 +  data/lalr1.java                               \
 +  data/location.cc                              \
 +  data/stack.hh                                 \
 +  data/variant.hh                               \
 +  data/yacc.c
 +
 +m4sugardir = $(pkgdatadir)/m4sugar
 +dist_m4sugar_DATA =                             \
 +  data/m4sugar/foreach.m4                       \
 +  data/m4sugar/m4sugar.m4
 +
 +xsltdir = $(pkgdatadir)/xslt
 +dist_xslt_DATA =                                \
 +  data/xslt/bison.xsl                           \
 +  data/xslt/xml2dot.xsl                         \
 +  data/xslt/xml2text.xsl                        \
 +  data/xslt/xml2xhtml.xsl
diff --combined data/yacc.c
index b3864e9044566afb3a84ae2212013d46624a6381,1cd9ffbb288493297bb57a88b93f4d21c22569f4..7376f9007a2d466d854c30bba087155fda172659
@@@ -1,12 -1,10 +1,12 @@@
                                                               -*- C -*-
 -
  # Yacc compatible skeleton for Bison
  
  # Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation,
  # Inc.
  
 +m4_pushdef([b4_copyright_years],
 +           [1984, 1989-1990, 2000-2012])
 +
  # 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
  # the Free Software Foundation, either version 3 of the License, or
@@@ -76,8 -74,8 +76,8 @@@ m4_define([b4_pure_flag]
  # Expand IF-TRUE, if %pure-parser and %parse-param, IF-FALSE otherwise.
  m4_define([b4_yacc_pure_if],
  [b4_pure_if([m4_ifset([b4_parse_param],
 -                    [$1], [$2])],
 -          [$2])])
 +                      [$1], [$2])],
 +            [$2])])
  
  
  # b4_yyerror_args
@@@ -117,7 -115,7 +117,7 @@@ m4_define([b4_int_type]
  
         m4_eval([0 <= $1]),                [1], [unsigned int],
  
 -                                             [int])])
 +                                               [int])])
  
  
  ## ----------------- ##
  # --------------------
  # Expansion of $<TYPE>$.
  m4_define([b4_lhs_value],
 -[(yyval[]m4_ifval([$1], [.$1]))])
 +[b4_symbol_value(yyval, [$1])])
  
  
  # b4_rhs_value(RULE-LENGTH, NUM, [TYPE])
  # Expansion of $<TYPE>NUM, where the current rule has RULE-LENGTH
  # symbols on RHS.
  m4_define([b4_rhs_value],
 -[(yyvsp@{($2) - ($1)@}m4_ifval([$3], [.$3]))])
 +          [b4_symbol_value([yyvsp@{b4_subtract([$2], [$1])@}], [$3])])
  
  
  
@@@ -157,7 -155,7 +157,7 @@@ m4_define([b4_lhs_location]
  # Expansion of @NUM, where the current rule has RULE-LENGTH symbols
  # on RHS.
  m4_define([b4_rhs_location],
 -[(yylsp@{($2) - ($1)@})])
 +          [(yylsp@{b4_subtract([$2], [$1])@})])
  
  
  ## -------------- ##
@@@ -284,7 -282,7 +284,7 @@@ m4_define([b4_shared_declarations]
  [b4_cpp_guard_open([b4_spec_defines_file])[
  ]b4_declare_yydebug[
  ]b4_percent_code_get([[requires]])[
 -]b4_token_enums_defines(b4_tokens)[
 +]b4_token_enums_defines[
  ]b4_declare_yylstype[
  ]b4_declare_yyparse[
  ]b4_percent_code_get([[provides]])[
  m4_changecom()
  m4_divert_push(0)dnl
  @output(b4_parser_file_name@)@
 -b4_copyright([Bison implementation for Yacc-like parsers in C],
 -             [1984, 1989-1990, 2000-2012])[
 +b4_copyright([Bison implementation for Yacc-like parsers in C])[
  
  /* C LALR(1) parser skeleton written by Richard Stallman, by
     simplifying the original so-called "semantic" parser.  */
@@@ -343,7 -342,7 +343,7 @@@ m4_if(b4_api_prefix, [yy], []
  # undef YYERROR_VERBOSE
  # define YYERROR_VERBOSE 1
  #else
 -# define YYERROR_VERBOSE ]b4_error_verbose_flag[
 +# define YYERROR_VERBOSE ]b4_error_verbose_if([1], [0])[
  #endif
  
  /* In a future release of Bison, this section will be replaced
@@@ -475,7 -474,7 +475,7 @@@ b4_push_if([], [b4_lac_if([], [
  #  endif
  #  if (defined __cplusplus && ! defined EXIT_SUCCESS \
         && ! ((defined YYMALLOC || defined malloc) \
 -           && (defined YYFREE || defined free)))
 +             && (defined YYFREE || defined free)))
  #   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
  #   ifndef EXIT_SUCCESS
  #    define EXIT_SUCCESS 0
@@@ -500,8 -499,8 +500,8 @@@ void free (void *); /* INFRINGES ON USE
  
  #if (! defined yyoverflow \
       && (! defined __cplusplus \
 -       || (]b4_locations_if([[defined ]b4_api_PREFIX[LTYPE_IS_TRIVIAL && ]b4_api_PREFIX[LTYPE_IS_TRIVIAL \
 -           && ]])[defined ]b4_api_PREFIX[STYPE_IS_TRIVIAL && ]b4_api_PREFIX[STYPE_IS_TRIVIAL)))
 +         || (]b4_locations_if([[defined ]b4_api_PREFIX[LTYPE_IS_TRIVIAL && ]b4_api_PREFIX[LTYPE_IS_TRIVIAL \
 +             && ]])[defined ]b4_api_PREFIX[STYPE_IS_TRIVIAL && ]b4_api_PREFIX[STYPE_IS_TRIVIAL)))
  
  /* A type that is properly aligned for any stack member.  */
  union yyalloc
     elements in the stack, and YYPTR gives the new location of the
     stack.  Advance YYPTR to a properly aligned location for the next
     stack.  */
 -# define YYSTACK_RELOCATE(Stack_alloc, Stack)                         \
 -    do                                                                        \
 -      {                                                                       \
 -      YYSIZE_T yynewbytes;                                            \
 -      YYCOPY (&yyptr->Stack_alloc, Stack, yysize);                    \
 -      Stack = &yyptr->Stack_alloc;                                    \
 -      yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
 -      yyptr += yynewbytes / sizeof (*yyptr);                          \
 -      }                                                                       \
 +# define YYSTACK_RELOCATE(Stack_alloc, Stack)                           \
 +    do                                                                  \
 +      {                                                                 \
 +        YYSIZE_T yynewbytes;                                            \
 +        YYCOPY (&yyptr->Stack_alloc, Stack, yysize);                    \
 +        Stack = &yyptr->Stack_alloc;                                    \
 +        yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
 +        yyptr += yynewbytes / sizeof (*yyptr);                          \
 +      }                                                                 \
      while (YYID (0))
  
  #endif
  #define YYNNTS  ]b4_nterms_number[
  /* YYNRULES -- Number of rules.  */
  #define YYNRULES  ]b4_rules_number[
 -/* YYNRULES -- Number of states.  */
 +/* YYNSTATES -- Number of states.  */
  #define YYNSTATES  ]b4_states_number[
  
 -/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
 +/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
 +   by yylex, with out-of-bounds checking.  */
  #define YYUNDEFTOK  ]b4_undef_token_number[
  #define YYMAXUTOK   ]b4_user_token_number_max[
  
 -#define YYTRANSLATE(YYX)                                              \
 +#define YYTRANSLATE(YYX)                                                \
    ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
  
 -/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
 +/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
 +   as returned by yylex, without out-of-bounds checking.  */
  static const ]b4_int_type_for([b4_translate])[ yytranslate[] =
  {
    ]b4_translate[
  };
  
  #if ]b4_api_PREFIX[DEBUG
 -/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
 -   YYRHS.  */
 -static const ]b4_int_type_for([b4_prhs])[ yyprhs[] =
 -{
 -  ]b4_prhs[
 -};
 -
 -/* YYRHS -- A `-1'-separated list of the rules' RHS.  */
 -static const ]b4_int_type_for([b4_rhs])[ yyrhs[] =
 -{
 -  ]b4_rhs[
 -};
 -
 -/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
 -static const ]b4_int_type_for([b4_rline])[ yyrline[] =
 -{
 -  ]b4_rline[
 -};
 +]b4_integral_parser_table_define([rline], [b4_rline],
 +     [YYRLINE[YYN] -- Source line where rule number YYN was defined.])[
  #endif
  
  #if ]b4_api_PREFIX[DEBUG || YYERROR_VERBOSE || ]b4_token_table_flag[
@@@ -608,35 -621,105 +608,35 @@@ static const char *const yytname[] 
  #endif
  
  # ifdef YYPRINT
 -/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
 -   token YYLEX-NUM.  */
 +/* YYTOKNUM[NUM] -- (External) token number corresponding to the
 +   (internal) symbol number NUM (which must be that of a token).  */
  static const ]b4_int_type_for([b4_toknum])[ yytoknum[] =
  {
    ]b4_toknum[
  };
  # endif
  
 -/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 -static const ]b4_int_type_for([b4_r1])[ yyr1[] =
 -{
 -  ]b4_r1[
 -};
 -
 -/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
 -static const ]b4_int_type_for([b4_r2])[ yyr2[] =
 -{
 -  ]b4_r2[
 -};
 -
 -/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM.
 -   Performed when YYTABLE doesn't specify something else to do.  Zero
 -   means the default is an error.  */
 -static const ]b4_int_type_for([b4_defact])[ yydefact[] =
 -{
 -  ]b4_defact[
 -};
 -
 -/* YYDEFGOTO[NTERM-NUM].  */
 -static const ]b4_int_type_for([b4_defgoto])[ yydefgoto[] =
 -{
 -  ]b4_defgoto[
 -};
 -
 -/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
 -   STATE-NUM.  */
  #define YYPACT_NINF ]b4_pact_ninf[
 -static const ]b4_int_type_for([b4_pact])[ yypact[] =
 -{
 -  ]b4_pact[
 -};
 -
 -/* YYPGOTO[NTERM-NUM].  */
 -static const ]b4_int_type_for([b4_pgoto])[ yypgoto[] =
 -{
 -  ]b4_pgoto[
 -};
 -
 -/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
 -   positive, shift that token.  If negative, reduce the rule which
 -   number is the opposite.  If YYTABLE_NINF, syntax error.  */
 -#define YYTABLE_NINF ]b4_table_ninf[
 -static const ]b4_int_type_for([b4_table])[ yytable[] =
 -{
 -  ]b4_table[
 -};
  
  #define yypact_value_is_default(yystate) \
    ]b4_table_value_equals([[pact]], [[yystate]], [b4_pact_ninf])[
  
 +#define YYTABLE_NINF ]b4_table_ninf[
 +
  #define yytable_value_is_error(yytable_value) \
    ]b4_table_value_equals([[table]], [[yytable_value]], [b4_table_ninf])[
  
 -static const ]b4_int_type_for([b4_check])[ yycheck[] =
 -{
 -  ]b4_check[
 -};
 +]b4_parser_tables_define[
  
 -/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
 -   symbol of state STATE-NUM.  */
 -static const ]b4_int_type_for([b4_stos])[ yystos[] =
 -{
 -  ]b4_stos[
 -};
 +#define yyerrok         (yyerrstatus = 0)
 +#define yyclearin       (yychar = YYEMPTY)
 +#define YYEMPTY         (-2)
 +#define YYEOF           0
 +
 +#define YYACCEPT        goto yyacceptlab
 +#define YYABORT         goto yyabortlab
 +#define YYERROR         goto yyerrorlab
  
 -#define yyerrok               (yyerrstatus = 0)
 -#define yyclearin     (yychar = YYEMPTY)
 -#define YYEMPTY               (-2)
 -#define YYEOF         0
 -
 -#define YYACCEPT      goto yyacceptlab
 -#define YYABORT               goto yyabortlab
 -#define YYERROR               goto yyerrorlab
 -
 -
 -/* Like YYERROR except do call yyerror.  This remains here temporarily
 -   to ease the transition to the new meaning of YYERROR, for GCC.
 -   Once GCC version 2 has supplanted version 1, this can go.  However,
 -   YYFAIL appears to be in use.  Nevertheless, it is formally deprecated
 -   in Bison 2.4.2's NEWS entry, where a plan to phase it out is
 -   discussed.  */
 -
 -#define YYFAIL                goto yyerrlab
 -#if defined YYFAIL
 -  /* This is here to suppress warnings from the GCC cpp's
 -     -Wunused-macros.  Normally we don't worry about that warning, but
 -     some users do, and we want to make it easy for users to remove
 -     YYFAIL uses, which will produce warnings from Bison 2.5.  */
 -#endif
  
  #define YYRECOVERING()  (!!yyerrstatus)
  
    else                                                          \
      {                                                           \
        yyerror (]b4_yyerror_args[YY_("syntax error: cannot back up")); \
 -      YYERROR;                                                        \
 -    }                                                         \
 +      YYERROR;                                                  \
 +    }                                                           \
  while (YYID (0))
  
  
 -#define YYTERROR      1
 -#define YYERRCODE     256
 +#define YYTERROR        1
 +#define YYERRCODE       256
  
 +]b4_locations_if([[
  ]b4_yylloc_default_define[
  #define YYRHSLOC(Rhs, K) ((Rhs)[K])
 -]b4_locations_if([[
 -
  
  /* YY_LOCATION_PRINT -- Print the location on the stream.
     This macro was not mandated originally: define only if we know
  
  #ifndef YY_LOCATION_PRINT
  # if defined ]b4_api_PREFIX[LTYPE_IS_TRIVIAL && ]b4_api_PREFIX[LTYPE_IS_TRIVIAL
 -#  define YY_LOCATION_PRINT(File, Loc)                        \
 -     fprintf (File, "%d.%d-%d.%d",                    \
 -            (Loc).first_line, (Loc).first_column,     \
 -            (Loc).last_line,  (Loc).last_column)
 +#  define YY_LOCATION_PRINT(File, Loc)                  \
 +     fprintf (File, "%d.%d-%d.%d",                      \
 +              (Loc).first_line, (Loc).first_column,     \
 +              (Loc).last_line,  (Loc).last_column)
  # else
  #  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
  # endif
  #  define YYFPRINTF fprintf
  # endif
  
 -# define YYDPRINTF(Args)                      \
 -do {                                          \
 -  if (yydebug)                                        \
 -    YYFPRINTF Args;                           \
 +# define YYDPRINTF(Args)                        \
 +do {                                            \
 +  if (yydebug)                                  \
 +    YYFPRINTF Args;                             \
  } while (YYID (0))
  
 -# define YY_SYMBOL_PRINT(Title, Type, Value, Location)                          \
 -do {                                                                    \
 -  if (yydebug)                                                                  \
 -    {                                                                   \
 -      YYFPRINTF (stderr, "%s ", Title);                                         \
 -      yy_symbol_print (stderr,                                                  \
 -                Type, Value]b4_locations_if([, Location])[]b4_user_args[); \
 -      YYFPRINTF (stderr, "\n");                                                 \
 -    }                                                                   \
 +# define YY_SYMBOL_PRINT(Title, Type, Value, Location)                    \
 +do {                                                                      \
 +  if (yydebug)                                                            \
 +    {                                                                     \
 +      YYFPRINTF (stderr, "%s ", Title);                                   \
 +      yy_symbol_print (stderr,                                            \
 +                  Type, Value]b4_locations_if([, Location])[]b4_user_args[); \
 +      YYFPRINTF (stderr, "\n");                                           \
 +    }                                                                     \
  } while (YYID (0))
  
  ]b4_yy_symbol_print_generate([b4_c_function_def])[
  `------------------------------------------------------------------*/
  
  ]b4_c_function_def([yy_stack_print], [static void],
 -                 [[yytype_int16 *yybottom], [yybottom]],
 -                 [[yytype_int16 *yytop],    [yytop]])[
 +                   [[yytype_int16 *yybottom], [yybottom]],
 +                   [[yytype_int16 *yytop],    [yytop]])[
  {
    YYFPRINTF (stderr, "Stack now");
    for (; yybottom <= yytop; yybottom++)
    YYFPRINTF (stderr, "\n");
  }
  
 -# define YY_STACK_PRINT(Bottom, Top)                          \
 -do {                                                          \
 -  if (yydebug)                                                        \
 -    yy_stack_print ((Bottom), (Top));                         \
 +# define YY_STACK_PRINT(Bottom, Top)                            \
 +do {                                                            \
 +  if (yydebug)                                                  \
 +    yy_stack_print ((Bottom), (Top));                           \
  } while (YYID (0))
  
  
  `------------------------------------------------*/
  
  ]b4_c_function_def([yy_reduce_print], [static void],
 -                 [[YYSTYPE *yyvsp], [yyvsp]],
 +                   [[yytype_int16 *yyssp], [yyssp]],
 +                   [[YYSTYPE *yyvsp], [yyvsp]],
      b4_locations_if([[[YYLTYPE *yylsp], [yylsp]],
 -                 ])[[int yyrule], [yyrule]]m4_ifset([b4_parse_param], [,
 -                 b4_parse_param]))[
 +                   ])[[int yyrule], [yyrule]]m4_ifset([b4_parse_param], [,
 +                   b4_parse_param]))[
  {
 +  unsigned long int yylno = yyrline[yyrule];
    int yynrhs = yyr2[yyrule];
    int yyi;
 -  unsigned long int yylno = yyrline[yyrule];
    YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
 -           yyrule - 1, yylno);
 +             yyrule - 1, yylno);
    /* The symbols being reduced.  */
    for (yyi = 0; yyi < yynrhs; yyi++)
      {
        YYFPRINTF (stderr, "   $%d = ", yyi + 1);
 -      yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
 -                     &]b4_rhs_value(yynrhs, yyi + 1)[
 -                     ]b4_locations_if([, &]b4_rhs_location(yynrhs, yyi + 1))[]dnl
 -                     b4_user_args[);
 +      yy_symbol_print (stderr,
 +                       yystos[yyssp[yyi + 1 - yynrhs]],
 +                       &]b4_rhs_value(yynrhs, yyi + 1)[
 +                       ]b4_locations_if([, &]b4_rhs_location(yynrhs, yyi + 1))[]dnl
 +                       b4_user_args[);
        YYFPRINTF (stderr, "\n");
      }
  }
  
 -# define YY_REDUCE_PRINT(Rule)                \
 -do {                                  \
 -  if (yydebug)                                \
 -    yy_reduce_print (yyvsp, ]b4_locations_if([yylsp, ])[Rule]b4_user_args[); \
 +# define YY_REDUCE_PRINT(Rule)          \
 +do {                                    \
 +  if (yydebug)                          \
 +    yy_reduce_print (yyssp, yyvsp, ]b4_locations_if([yylsp, ])[Rule]b4_user_args[); \
  } while (YYID (0))
  
  /* Nonzero means print parse trace.  It is left uninitialized so that
@@@ -796,7 -878,7 +796,7 @@@ int yydebug
  
  
  /* YYINITDEPTH -- initial size of the parser's stacks.  */
 -#ifndef       YYINITDEPTH
 +#ifndef YYINITDEPTH
  # define YYINITDEPTH ]b4_stack_depth_init[
  #endif
  
@@@ -1103,27 -1185,27 +1103,27 @@@ yytnamerr (char *yyres, const char *yys
        char const *yyp = yystr;
  
        for (;;)
 -      switch (*++yyp)
 -        {
 -        case '\'':
 -        case ',':
 -          goto do_not_strip_quotes;
 -
 -        case '\\':
 -          if (*++yyp != '\\')
 -            goto do_not_strip_quotes;
 -          /* Fall through.  */
 -        default:
 -          if (yyres)
 -            yyres[yyn] = *yyp;
 -          yyn++;
 -          break;
 -
 -        case '"':
 -          if (yyres)
 -            yyres[yyn] = '\0';
 -          return yyn;
 -        }
 +        switch (*++yyp)
 +          {
 +          case '\'':
 +          case ',':
 +            goto do_not_strip_quotes;
 +
 +          case '\\':
 +            if (*++yyp != '\\')
 +              goto do_not_strip_quotes;
 +            /* Fall through.  */
 +          default:
 +            if (yyres)
 +              yyres[yyn] = *yyp;
 +            yyn++;
 +            break;
 +
 +          case '"':
 +            if (yyres)
 +              yyres[yyn] = '\0';
 +            return yyn;
 +          }
      do_not_strip_quotes: ;
      }
  
@@@ -1162,6 -1244,10 +1162,6 @@@ yysyntax_error (YYSIZE_T *yymsg_alloc, 
    int yycount = 0;
  
    /* There are many possibilities here to consider:
 -     - Assume YYFAIL is not used.  It's too flawed to consider.  See
 -       <http://lists.gnu.org/archive/html/bison-patches/2009-12/msg00024.html>
 -       for details.  YYERROR is fine as it does not invoke this
 -       function.
       - If this state is a consistent state with a default action, then
         the only way this function was invoked is if the default action
         is an error action.  In that case, don't check for expected
@@@ -1484,17 -1570,16 +1484,16 @@@ b4_c_function_def([[yyparse]], [[int]]
    yylloc.first_column = yylloc.last_column = ]b4_location_initial_column[;
  #endif]])
  m4_ifdef([b4_initial_action],[
- m4_pushdef([b4_at_dollar],     [m4_define([b4_at_dollar_used])yylloc])dnl
m4_pushdef([b4_dollar_dollar], [m4_define([b4_dollar_dollar_used])yylval])dnl
+ b4_dollar_pushdef([m4_define([b4_dollar_dollar_used])yylval], [],
                  [m4_define([b4_at_dollar_used])yylloc])dnl
  /* User initialization code.  */
  b4_user_initial_action
- m4_popdef([b4_dollar_dollar])dnl
- m4_popdef([b4_at_dollar])])dnl
+ b4_dollar_popdef[]dnl
  m4_ifdef([b4_dollar_dollar_used],[[  yyvsp[0] = yylval;
  ]])dnl
  m4_ifdef([b4_at_dollar_used], [[  yylsp[0] = yylloc;
- ]])[
-   goto yysetstate;
+ ]])])dnl
[  goto yysetstate;
  
  /*------------------------------------------------------------.
  | yynewstate -- Push a new state, which is found in yystate.  |
  
  #ifdef yyoverflow
        {
 -      /* Give user a chance to reallocate the stack.  Use copies of
 -         these so that the &'s don't force the real ones into
 -         memory.  */
 -      YYSTYPE *yyvs1 = yyvs;
 -      yytype_int16 *yyss1 = yyss;]b4_locations_if([
 -      YYLTYPE *yyls1 = yyls;])[
 -
 -      /* Each stack pointer address is followed by the size of the
 -         data in use in that stack, in bytes.  This used to be a
 -         conditional around just the two extra args, but that might
 -         be undefined if yyoverflow is a macro.  */
 -      yyoverflow (YY_("memory exhausted"),
 -                  &yyss1, yysize * sizeof (*yyssp),
 -                  &yyvs1, yysize * sizeof (*yyvsp),]b4_locations_if([
 -                  &yyls1, yysize * sizeof (*yylsp),])[
 -                  &yystacksize);
 +        /* Give user a chance to reallocate the stack.  Use copies of
 +           these so that the &'s don't force the real ones into
 +           memory.  */
 +        YYSTYPE *yyvs1 = yyvs;
 +        yytype_int16 *yyss1 = yyss;]b4_locations_if([
 +        YYLTYPE *yyls1 = yyls;])[
 +
 +        /* Each stack pointer address is followed by the size of the
 +           data in use in that stack, in bytes.  This used to be a
 +           conditional around just the two extra args, but that might
 +           be undefined if yyoverflow is a macro.  */
 +        yyoverflow (YY_("memory exhausted"),
 +                    &yyss1, yysize * sizeof (*yyssp),
 +                    &yyvs1, yysize * sizeof (*yyvsp),]b4_locations_if([
 +                    &yyls1, yysize * sizeof (*yylsp),])[
 +                    &yystacksize);
  ]b4_locations_if([
 -      yyls = yyls1;])[
 -      yyss = yyss1;
 -      yyvs = yyvs1;
 +        yyls = yyls1;])[
 +        yyss = yyss1;
 +        yyvs = yyvs1;
        }
  #else /* no yyoverflow */
  # ifndef YYSTACK_RELOCATE
  # else
        /* Extend the stack our own way.  */
        if (YYMAXDEPTH <= yystacksize)
 -      goto yyexhaustedlab;
 +        goto yyexhaustedlab;
        yystacksize *= 2;
        if (YYMAXDEPTH < yystacksize)
 -      yystacksize = YYMAXDEPTH;
 +        yystacksize = YYMAXDEPTH;
  
        {
 -      yytype_int16 *yyss1 = yyss;
 -      union yyalloc *yyptr =
 -        (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
 -      if (! yyptr)
 -        goto yyexhaustedlab;
 -      YYSTACK_RELOCATE (yyss_alloc, yyss);
 -      YYSTACK_RELOCATE (yyvs_alloc, yyvs);]b4_locations_if([
 -      YYSTACK_RELOCATE (yyls_alloc, yyls);])[
 +        yytype_int16 *yyss1 = yyss;
 +        union yyalloc *yyptr =
 +          (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
 +        if (! yyptr)
 +          goto yyexhaustedlab;
 +        YYSTACK_RELOCATE (yyss_alloc, yyss);
 +        YYSTACK_RELOCATE (yyvs_alloc, yyvs);]b4_locations_if([
 +        YYSTACK_RELOCATE (yyls_alloc, yyls);])[
  #  undef YYSTACK_RELOCATE
 -      if (yyss1 != yyssa)
 -        YYSTACK_FREE (yyss1);
 +        if (yyss1 != yyssa)
 +          YYSTACK_FREE (yyss1);
        }
  # endif
  #endif /* no yyoverflow */
        yylsp = yyls + yysize - 1;])[
  
        YYDPRINTF ((stderr, "Stack size increased to %lu\n",
 -                (unsigned long int) yystacksize));
 +                  (unsigned long int) yystacksize));
  
        if (yyss + yystacksize - 1 <= yyssp)
 -      YYABORT;
 +        YYABORT;
      }
  
    YYDPRINTF ((stderr, "Entering state %d\n", yystate));
@@@ -1750,9 -1835,9 +1749,9 @@@ yyreduce
    goto yynewstate;
  
  
 -/*------------------------------------.
 -| yyerrlab -- here on detecting error |
 -`------------------------------------*/
 +/*--------------------------------------.
 +| yyerrlab -- here on detecting error |
 +`--------------------------------------*/
  yyerrlab:
    /* Make sure we have latest lookahead translation.  See comments at
       user semantic actions for why this is necessary.  */
    if (yyerrstatus == 3)
      {
        /* If just tried and failed to reuse lookahead token after an
 -       error, discard it.  */
 +         error, discard it.  */
  
        if (yychar <= YYEOF)
 -      {
 -        /* Return failure if at end of input.  */
 -        if (yychar == YYEOF)
 -          YYABORT;
 -      }
 +        {
 +          /* Return failure if at end of input.  */
 +          if (yychar == YYEOF)
 +            YYABORT;
 +        }
        else
 -      {
 -        yydestruct ("Error: discarding",
 -                    yytoken, &yylval]b4_locations_if([, &yylloc])[]b4_user_args[);
 -        yychar = YYEMPTY;
 -      }
 +        {
 +          yydestruct ("Error: discarding",
 +                      yytoken, &yylval]b4_locations_if([, &yylloc])[]b4_user_args[);
 +          yychar = YYEMPTY;
 +        }
      }
  
    /* Else will try to reuse lookahead token after shifting the error
@@@ -1852,29 -1937,29 +1851,29 @@@ yyerrorlab
  | yyerrlab1 -- common code for both syntax error and YYERROR.  |
  `-------------------------------------------------------------*/
  yyerrlab1:
 -  yyerrstatus = 3;    /* Each real token shifted decrements this.  */
 +  yyerrstatus = 3;      /* Each real token shifted decrements this.  */
  
    for (;;)
      {
        yyn = yypact[yystate];
        if (!yypact_value_is_default (yyn))
 -      {
 -        yyn += YYTERROR;
 -        if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
 -          {
 -            yyn = yytable[yyn];
 -            if (0 < yyn)
 -              break;
 -          }
 -      }
 +        {
 +          yyn += YYTERROR;
 +          if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
 +            {
 +              yyn = yytable[yyn];
 +              if (0 < yyn)
 +                break;
 +            }
 +        }
  
        /* Pop the current state because it cannot handle the error token.  */
        if (yyssp == yyss)
 -      YYABORT;
 +        YYABORT;
  
  ]b4_locations_if([[      yyerror_range[1] = *yylsp;]])[
        yydestruct ("Error: popping",
 -                yystos[yystate], yyvsp]b4_locations_if([, yylsp])[]b4_user_args[);
 +                  yystos[yystate], yyvsp]b4_locations_if([, yylsp])[]b4_user_args[);
        YYPOPSTACK (1);
        yystate = *yyssp;
        YY_STACK_PRINT (yyss, yyssp);
@@@ -1939,7 -2024,7 +1938,7 @@@ yyreturn
    while (yyssp != yyss)
      {
        yydestruct ("Cleanup: popping",
 -                yystos[*yyssp], yyvsp]b4_locations_if([, yylsp])[]b4_user_args[);
 +                  yystos[*yyssp], yyvsp]b4_locations_if([, yylsp])[]b4_user_args[);
        YYPOPSTACK (1);
      }
  #ifndef yyoverflow
@@@ -1959,12 -2044,13 +1958,12 @@@ yypushreturn:]])
    return YYID (yyresult);
  }
  
 -
 -]b4_epilogue
 +]b4_epilogue[]dnl
  b4_defines_if(
  [@output(b4_spec_defines_file@)@
 -b4_copyright([Bison interface for Yacc-like parsers in C],
 -             [1984, 1989-1990, 2000-2012])[
 +b4_copyright([Bison interface for Yacc-like parsers in C])[
  
  ]b4_shared_declarations[
  ]])dnl b4_defines_if
  m4_divert_pop(0)
 +m4_popdef([b4_copyright_years])
diff --combined doc/bison.texi
index 2d06fec95a378c52dceeee152f76b29ab7b661a8,ad60505446e35fda04d8ba31ed0f47dfaad214c3..62ff045965fad53a3f8151593af9f2fb1a4ca59c
@@@ -110,7 -110,7 +110,7 @@@ Reference sections
  * Glossary::            Basic concepts are explained.
  * Copying This Manual:: License for copying this manual.
  * Bibliography::        Publications cited in this manual.
- * Index::               Cross-references to the text.
+ * Index of Terms::      Cross-references to the text.
  
  @detailmenu
   --- The Detailed Node Listing ---
@@@ -135,8 -135,7 +135,8 @@@ Writing GLR Parser
  
  * Simple GLR Parsers::     Using GLR parsers on unambiguous grammars.
  * Merging GLR Parses::     Using GLR parsers to resolve ambiguities.
 -* GLR Semantic Actions::   Deferred semantic actions have special concerns.
 +* GLR Semantic Actions::   Considerations for semantic values and deferred actions.
 +* Semantic Predicates::    Controlling a parse with arbitrary computations.
  * Compiler Requirements::  GLR parsers require a modern C compiler.
  
  Examples
@@@ -163,9 -162,9 +163,9 @@@ Reverse Polish Notation Calculato
  
  Grammar Rules for @code{rpcalc}
  
 -* Rpcalc Input::
 -* Rpcalc Line::
 -* Rpcalc Expr::
 +* Rpcalc Input::            Explanation of the @code{input} nonterminal
 +* Rpcalc Line::             Explanation of the @code{line} nonterminal
 +* Rpcalc Expr::             Explanation of the @code{expr} nonterminal
  
  Location Tracking Calculator: @code{ltcalc}
  
@@@ -178,8 -177,6 +178,8 @@@ Multi-Function Calculator: @code{mfcalc
  * Mfcalc Declarations::    Bison declarations for multi-function calculator.
  * Mfcalc Rules::           Grammar rules for the calculator.
  * Mfcalc Symbol Table::    Symbol table management subroutines.
 +* Mfcalc Lexer::           The lexical analyzer.
 +* Mfcalc Main::            The controlling function.
  
  Bison Grammar Files
  
@@@ -276,8 -273,7 +276,8 @@@ The Bison Parser Algorith
  Operator Precedence
  
  * Why Precedence::    An example showing why precedence is needed.
 -* Using Precedence::  How to specify precedence in Bison grammars.
 +* Using Precedence::  How to specify precedence and associativity.
 +* Precedence Only::   How to specify precedence only.
  * Precedence Examples::  How these features are used in the previous example.
  * How Precedence::    How they work.
  
@@@ -773,8 -769,7 +773,8 @@@ merged result
  @menu
  * Simple GLR Parsers::     Using GLR parsers on unambiguous grammars.
  * Merging GLR Parses::     Using GLR parsers to resolve ambiguities.
 -* GLR Semantic Actions::   Deferred semantic actions have special concerns.
 +* GLR Semantic Actions::   Considerations for semantic values and deferred actions.
 +* Semantic Predicates::    Controlling a parse with arbitrary computations.
  * Compiler Requirements::  GLR parsers require a modern C compiler.
  @end menu
  
@@@ -1142,10 -1137,6 +1142,10 @@@ the offending merge
  @node GLR Semantic Actions
  @subsection GLR Semantic Actions
  
 +The nature of GLR parsing and the structure of the generated
 +parsers give rise to certain restrictions on semantic values and actions.
 +
 +@subsubsection Deferred semantic actions
  @cindex deferred semantic actions
  By definition, a deferred semantic action is not performed at the same time as
  the associated reduction.
@@@ -1179,7 -1170,6 +1179,7 @@@ For example, if a semantic action migh
  to invoke @code{yyclearin} (@pxref{Action Features}) or to attempt to free
  memory referenced by @code{yylval}.
  
 +@subsubsection YYERROR
  @findex YYERROR
  @cindex GLR parsers and @code{YYERROR}
  Another Bison feature requiring special consideration is @code{YYERROR}
  initiate error recovery.
  During deterministic GLR operation, the effect of @code{YYERROR} is
  the same as its effect in a deterministic parser.
 -In a deferred semantic action, its effect is undefined.
 -@c The effect is probably a syntax error at the split point.
 +The effect in a deferred action is similar, but the precise point of the
 +error is undefined;  instead, the parser reverts to deterministic operation,
 +selecting an unspecified stack on which to continue with a syntax error.
 +In a semantic predicate (see @ref{Semantic Predicates}) during nondeterministic
 +parsing, @code{YYERROR} silently prunes
 +the parse that invoked the test.
 +
 +@subsubsection Restrictions on semantic values and locations
 +GLR parsers require that you use POD (Plain Old Data) types for
 +semantic values and location types when using the generated parsers as
 +C++ code.
 +
 +@node Semantic Predicates
 +@subsection Controlling a Parse with Arbitrary Predicates
 +@findex %?
 +@cindex Semantic predicates in GLR parsers
 +
 +In addition to the @code{%dprec} and @code{%merge} directives,
 +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,
 +
 +@example
 +widget:
 +  %?@{  new_syntax @} "widget" id new_args  @{ $$ = f($3, $4); @}
 +| %?@{ !new_syntax @} "widget" id old_args  @{ $$ = f($3, $4); @}
 +;
 +@end example
 +
 +@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.
  
 -Also, see @ref{Location Default Action, ,Default Action for Locations}, which
 -describes a special usage of @code{YYLLOC_DEFAULT} in GLR parsers.
 +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
 +
 +@example
 +widget:
 +  @{ if (!new_syntax) YYERROR; @}
 +    "widget" id new_args  @{ $$ = f($3, $4); @}
 +|  @{ if (new_syntax) YYERROR; @}
 +    "widget" id old_args   @{ $$ = f($3, $4); @}
 +;
 +@end example
 +
 +@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 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 GLR Parsers
@@@ -1527,13 -1450,11 +1527,13 @@@ The source code for this calculator is 
  Here are the C and Bison declarations for the reverse polish notation
  calculator.  As in C, comments are placed between @samp{/*@dots{}*/}.
  
 +@comment file: rpcalc.y
  @example
  /* Reverse polish notation calculator.  */
  
  %@{
    #define YYSTYPE double
 +  #include <stdio.h>
    #include <math.h>
    int yylex (void);
    void yyerror (char const *);
@@@ -1578,7 -1499,6 +1578,7 @@@ type for numeric constants
  
  Here are the grammar rules for the reverse polish notation calculator.
  
 +@comment file: rpcalc.y
  @example
  @group
  input:
@@@ -1627,9 -1547,9 +1627,9 @@@ main job of most actions.  The semanti
  rule are referred to as @code{$1}, @code{$2}, and so on.
  
  @menu
 -* Rpcalc Input::
 -* Rpcalc Line::
 -* Rpcalc Expr::
 +* Rpcalc Input::            Explanation of the @code{input} nonterminal
 +* Rpcalc Line::             Explanation of the @code{line} nonterminal
 +* Rpcalc Expr::             Explanation of the @code{expr} nonterminal
  @end menu
  
  @node Rpcalc Input
@@@ -1793,7 -1713,6 +1793,7 @@@ A token type code of zero is returned i
  
  Here is the code for the lexical analyzer:
  
 +@comment file: rpcalc.y
  @example
  @group
  /* The lexical analyzer returns a double floating point
@@@ -1842,7 -1761,6 +1842,7 @@@ In keeping with the spirit of this exam
  kept to the bare minimum.  The only requirement is that it call
  @code{yyparse} to start the process of parsing.
  
 +@comment file: rpcalc.y
  @example
  @group
  int
@@@ -1863,7 -1781,6 +1863,7 @@@ always @code{"syntax error"}).  It is u
  @code{yyerror} (@pxref{Interface, ,Parser C-Language Interface}), so
  here is the definition we will use:
  
 +@comment file: rpcalc.y
  @example
  @group
  #include <stdio.h>
@@@ -1948,15 -1865,15 +1948,15 @@@ example session using @code{rpcalc}
  @example
  $ @kbd{rpcalc}
  @kbd{4 9 +}
 -13
 +@result{} 13
  @kbd{3 7 + 3 4 5 *+-}
 --13
 +@result{} -13
  @kbd{3 7 + 3 4 5 * + - n}              @r{Note the unary minus, @samp{n}}
 -13
 +@result{} 13
  @kbd{5 6 / 4 n +}
 --3.166666667
 +@result{} -3.166666667
  @kbd{3 4 ^}                            @r{Exponentiation}
 -81
 +@result{} 81
  @kbd{^D}                               @r{End-of-file indicator}
  $
  @end example
@@@ -1990,8 -1907,8 +1990,8 @@@ parentheses nested to arbitrary depth
  %token NUM
  %left '-' '+'
  %left '*' '/'
 -%left NEG     /* negation--unary minus */
 -%right '^'    /* exponentiation */
 +%precedence NEG   /* negation--unary minus */
 +%right '^'        /* exponentiation */
  @end group
  
  %% /* The grammar follows.  */
@@@ -2034,16 -1951,15 +2034,16 @@@ In the second section (Bison declaratio
  types and says they are left-associative operators.  The declarations
  @code{%left} and @code{%right} (right associativity) take the place of
  @code{%token} which is used to declare a token type name without
 -associativity.  (These tokens are single-character literals, which
 +associativity/precedence.  (These tokens are single-character literals, which
  ordinarily don't need to be declared.  We declare them here to specify
 -the associativity.)
 +the associativity/precedence.)
  
  Operator precedence is determined by the line ordering of the
  declarations; the higher the line number of the declaration (lower on
  the page or screen), the higher the precedence.  Hence, exponentiation
  has the highest precedence, unary minus (@code{NEG}) is next, followed
 -by @samp{*} and @samp{/}, and so on.  @xref{Precedence, ,Operator
 +by @samp{*} and @samp{/}, and so on.  Unary minus is not associative,
 +only precedence matters (@code{%precedence}. @xref{Precedence, ,Operator
  Precedence}.
  
  The other important new feature is the @code{%prec} in the grammar
@@@ -2147,7 -2063,7 +2147,7 @@@ the same as the declarations for the in
  
  %left '-' '+'
  %left '*' '/'
 -%left NEG
 +%precedence NEG
  %right '^'
  
  %% /* The grammar follows.  */
@@@ -2348,23 -2264,19 +2348,23 @@@ to create named variables, store value
  Here is a sample session with the multi-function calculator:
  
  @example
 +@group
  $ @kbd{mfcalc}
  @kbd{pi = 3.141592653589}
 -3.1415926536
 +@result{} 3.1415926536
 +@end group
 +@group
  @kbd{sin(pi)}
 -0.0000000000
 +@result{} 0.0000000000
 +@end group
  @kbd{alpha = beta1 = 2.3}
 -2.3000000000
 +@result{} 2.3000000000
  @kbd{alpha}
 -2.3000000000
 +@result{} 2.3000000000
  @kbd{ln(alpha)}
 -0.8329091229
 +@result{} 0.8329091229
  @kbd{exp(ln(beta1))}
 -2.3000000000
 +@result{} 2.3000000000
  $
  @end example
  
@@@ -2374,8 -2286,6 +2374,8 @@@ Note that multiple assignment and neste
  * Mfcalc Declarations::    Bison declarations for multi-function calculator.
  * Mfcalc Rules::           Grammar rules for the calculator.
  * Mfcalc Symbol Table::    Symbol table management subroutines.
 +* Mfcalc Lexer::           The lexical analyzer.
 +* Mfcalc Main::            The controlling function.
  @end menu
  
  @node Mfcalc Declarations
@@@ -2387,9 -2297,8 +2387,9 @@@ Here are the C and Bison declarations f
  @example
  @group
  %@{
 -  #include <math.h>  /* For math functions, cos(), sin(), etc.  */
 -  #include "calc.h"  /* Contains definition of `symrec'.  */
 +  #include <stdio.h>  /* For printf, etc. */
 +  #include <math.h>   /* For pow, used in the grammar.  */
 +  #include "calc.h"   /* Contains definition of `symrec'.  */
    int yylex (void);
    void yyerror (char const *);
  %@}
  %right '='
  %left '-' '+'
  %left '*' '/'
 -%left NEG     /* negation--unary minus */
 -%right '^'    /* exponentiation */
 +%precedence NEG /* negation--unary minus */
 +%right '^'      /* exponentiation */
  @end group
  @end example
  
@@@ -2526,11 -2435,23 +2526,11 @@@ symrec *getsym (char const *)
  @end group
  @end example
  
 -The new version of @code{main} includes a call to @code{init_table}, a
 -function that initializes the symbol table.  Here it is, and
 -@code{init_table} as well:
 +The new version of @code{main} will call @code{init_table} to initialize
 +the symbol table:
  
  @comment file: mfcalc.y: 3
  @example
 -#include <stdio.h>
 -
 -@group
 -/* Called by yyparse on error.  */
 -void
 -yyerror (char const *s)
 -@{
 -  printf ("%s\n", s);
 -@}
 -@end group
 -
  @group
  struct init
  @{
  @group
  struct init const arith_fncts[] =
  @{
 -  "sin",  sin,
 -  "cos",  cos,
 -  "atan", atan,
 -  "ln",   log,
 -  "exp",  exp,
 -  "sqrt", sqrt,
 -  0, 0
 +  @{ "atan", atan @},
 +  @{ "cos",  cos  @},
 +  @{ "exp",  exp  @},
 +  @{ "ln",   log  @},
 +  @{ "sin",  sin  @},
 +  @{ "sqrt", sqrt @},
 +  @{ 0, 0 @},
  @};
  @end group
  
@@@ -2559,7 -2480,6 +2559,7 @@@ symrec *sym_table
  
  @group
  /* Put arithmetic functions in table.  */
 +static
  void
  init_table (void)
  @{
      @}
  @}
  @end group
 -
 -@group
 -int
 -main (void)
 -@{
 -  init_table ();
 -  return yyparse ();
 -@}
 -@end group
  @end example
  
  By simply editing the initialization list and adding the necessary include
@@@ -2610,16 -2539,13 +2610,16 @@@ getsym (char const *sym_name
    symrec *ptr;
    for (ptr = sym_table; ptr != (symrec *) 0;
         ptr = (symrec *)ptr->next)
 -    if (strcmp (ptr->name,sym_name) == 0)
 +    if (strcmp (ptr->name, sym_name) == 0)
        return ptr;
    return 0;
  @}
  @end group
  @end example
  
 +@node Mfcalc Lexer
 +@subsection The @code{mfcalc} Lexer
 +
  The function @code{yylex} must now recognize variables, numeric values, and
  the single-character arithmetic operators.  Strings of alphanumeric
  characters with a leading letter are recognized as either variables or
@@@ -2676,6 -2602,7 +2676,6 @@@ yylex (void
        symrec *s;
        int i;
  @end group
 -
        if (!symbuf)
          symbuf = (char *) malloc (length + 1);
  
  @end group
  @end example
  
 +@node Mfcalc Main
 +@subsection The @code{mfcalc} Main
 +
  The error reporting function is unchanged, and the new version of
  @code{main} includes a call to @code{init_table} and sets the @code{yydebug}
  on user demand (@xref{Tracing, , Tracing Your Parser}, for details):
@@@ -4376,8 -4300,7 +4376,8 @@@ Bison will convert this into a @code{#d
  the parser, so that the function @code{yylex} (if it is in this file)
  can use the name @var{name} to stand for this token type's code.
  
 -Alternatively, you can use @code{%left}, @code{%right}, or
 +Alternatively, you can use @code{%left}, @code{%right},
 +@code{%precedence}, or
  @code{%nonassoc} instead of @code{%token}, if you wish to specify
  associativity and precedence.  @xref{Precedence Decl, ,Operator
  Precedence}.
@@@ -4453,8 -4376,7 +4453,8 @@@ of ``$end''
  @cindex declaring operator precedence
  @cindex operator precedence, declaring
  
 -Use the @code{%left}, @code{%right} or @code{%nonassoc} declaration to
 +Use the @code{%left}, @code{%right}, @code{%nonassoc}, or
 +@code{%precedence} declaration to
  declare a token and specify its precedence and associativity, all at
  once.  These are called @dfn{precedence declarations}.
  @xref{Precedence, ,Operator Precedence}, for general information on
@@@ -4490,10 -4412,6 +4490,10 @@@ left-associativity (grouping @var{x} wi
  means that @samp{@var{x} @var{op} @var{y} @var{op} @var{z}} is
  considered a syntax error.
  
 +@code{%precedence} gives only precedence to the @var{symbols}, and
 +defines no associativity at all.  Use this to define precedence only,
 +and leave any potential conflict due to associativity enabled.
 +
  @item
  The precedence of an operator determines how it nests with other operators.
  All the tokens declared in a single precedence declaration have equal
@@@ -4634,9 -4552,9 +4634,9 @@@ code
  @deffn {Directive} %initial-action @{ @var{code} @}
  @findex %initial-action
  Declare that the braced @var{code} must be invoked before parsing each time
- @code{yyparse} is called.  The @var{code} may use @code{$$} and
- @code{@@$} --- initial value and location of the lookahead --- and the
- @code{%parse-param}.
+ @code{yyparse} is called.  The @var{code} may use @code{$$} (or
+ @code{$<@var{tag}>$}) and @code{@@$} --- initial value and location of the
lookahead --- and the @code{%parse-param}.
  @end deffn
  
  For instance, if your locations use a file name, you may use
@@@ -4674,11 -4592,11 +4674,11 @@@ symbol is automatically discarded
  @deffn {Directive} %destructor @{ @var{code} @} @var{symbols}
  @findex %destructor
  Invoke the braced @var{code} whenever the parser discards one of the
- @var{symbols}.
Within @var{code}, @code{$$} designates the semantic value associated
- with the discarded symbol, and @code{@@$} designates its location.
- The additional parser parameters are also available (@pxref{Parser Function, ,
The Parser Function @code{yyparse}}).
+ @var{symbols}.  Within @var{code}, @code{$$} (or @code{$<@var{tag}>$})
designates the semantic value associated with the discarded symbol, and
+ @code{@@$} designates its location.  The additional parser parameters are
+ also available (@pxref{Parser Function, , The Parser Function
+ @code{yyparse}}).
  
  When a symbol is listed among @var{symbols}, its @code{%destructor} is called a
  per-symbol @code{%destructor}.
@@@ -4816,10 -4734,11 +4816,11 @@@ Decl, , Freeing Discarded Symbols})
  @c This is the same text as for %destructor.
  Invoke the braced @var{code} whenever the parser displays one of the
  @var{symbols}.  Within @var{code}, @code{yyoutput} denotes the output stream
- (a @code{FILE*} in C, and an @code{std::ostream&} in C++),
- @code{$$} designates the semantic value associated with the symbol, and
- @code{@@$} its location.  The additional parser parameters are also
- available (@pxref{Parser Function, , The Parser Function @code{yyparse}}).
+ (a @code{FILE*} in C, and an @code{std::ostream&} in C++), @code{$$} (or
+ @code{$<@var{tag}>$}) designates the semantic value associated with the
+ symbol, and @code{@@$} its location.  The additional parser parameters are
+ also available (@pxref{Parser Function, , The Parser Function
+ @code{yyparse}}).
  
  The @var{symbols} are defined as for @code{%destructor} (@pxref{Destructor
  Decl, , Freeing Discarded Symbols}.): they can be per-type (e.g.,
@@@ -4954,7 -4873,7 +4955,7 @@@ statically allocated variables for comm
  including @code{yylval} and @code{yylloc}.)
  
  Alternatively, you can generate a pure, reentrant parser.  The Bison
 -declaration @code{%define api.pure} says that you want the parser to be
 +declaration @samp{%define api.pure} says that you want the parser to be
  reentrant.  It looks like this:
  
  @example
@@@ -5058,14 -4977,14 +5059,14 @@@ for use by the next invocation of the @
  
  Bison also supports both the push parser interface along with the pull parser
  interface in the same generated parser.  In order to get this functionality,
 -you should replace the @code{%define api.push-pull push} declaration with the
 -@code{%define api.push-pull both} declaration.  Doing this will create all of
 +you should replace the @samp{%define api.push-pull push} declaration with the
 +@samp{%define api.push-pull both} declaration.  Doing this will create all of
  the symbols mentioned earlier along with the two extra symbols, @code{yyparse}
  and @code{yypull_parse}.  @code{yyparse} can be used exactly as it normally
  would be used.  However, the user should note that it is implemented in the
  generated parser by calling @code{yypull_parse}.
  This makes the @code{yyparse} function that is generated with the
 -@code{%define api.push-pull both} declaration slower than the normal
 +@samp{%define api.push-pull both} declaration slower than the normal
  @code{yyparse} function.  If the user
  calls the @code{yypull_parse} function it will parse the rest of the input
  stream.  It is possible to @code{yypush_parse} tokens to select a subgrammar
@@@ -5081,9 -5000,9 +5082,9 @@@ yypull_parse (ps); /* Will call the lex
  yypstate_delete (ps);
  @end example
  
 -Adding the @code{%define api.pure} declaration does exactly the same thing to
 -the generated parser with @code{%define api.push-pull both} as it did for
 -@code{%define api.push-pull push}.
 +Adding the @samp{%define api.pure} declaration does exactly the same thing to
 +the generated parser with @samp{%define api.push-pull both} as it did for
 +@samp{%define api.push-pull push}.
  
  @node Decl Summary
  @subsection Bison Declaration Summary
@@@ -5156,8 -5075,10 +5157,8 @@@ default location or at the location spe
  @end deffn
  
  @deffn {Directive} %debug
 -In the parser implementation file, define the macro @code{YYDEBUG} (or
 -@code{@var{prefix}DEBUG} with @samp{%define api.prefix @var{prefix}}), see
 -@ref{Multiple Parsers, ,Multiple Parsers in the Same Program}) to 1 if it is
 -not already defined, so that the debugging facilities are compiled.
 +Instrument the parser for traces.  Obsoleted by @samp{%define
 +parse.trace}.
  @xref{Tracing, ,Tracing Your Parser}.
  @end deffn
  
@@@ -5236,22 -5157,6 +5237,22 @@@ grammar does not use it, using @samp{%l
  accurate syntax error messages.
  @end deffn
  
 +@deffn {Directive} %name-prefix "@var{prefix}"
 +Rename the external symbols used in the parser so that they start with
 +@var{prefix} instead of @samp{yy}.  The precise list of symbols renamed
 +in C parsers
 +is @code{yyparse}, @code{yylex}, @code{yyerror}, @code{yynerrs},
 +@code{yylval}, @code{yychar}, @code{yydebug}, and
 +(if locations are used) @code{yylloc}.  If you use a push parser,
 +@code{yypush_parse}, @code{yypull_parse}, @code{yypstate},
 +@code{yypstate_new} and @code{yypstate_delete} will
 +also be renamed.  For example, if you use @samp{%name-prefix "c_"}, the
 +names become @code{c_parse}, @code{c_lex}, and so on.
 +For C++ parsers, see the @samp{%define api.namespace} documentation in this
 +section.
 +@xref{Multiple Parsers, ,Multiple Parsers in the Same Program}.
 +@end deffn
 +
  @ifset defaultprec
  @deffn {Directive} %no-default-prec
  Do not assign a precedence to rules lacking an explicit @code{%prec}
@@@ -5275,7 -5180,7 +5276,7 @@@ Specify @var{file} for the parser imple
  @end deffn
  
  @deffn {Directive} %pure-parser
 -Deprecated version of @code{%define api.pure} (@pxref{%define
 +Deprecated version of @samp{%define api.pure} (@pxref{%define
  Summary,,api.pure}), for which Bison is more careful to warn about
  unreasonable usage.
  @end deffn
@@@ -5398,62 -5303,9 +5399,62 @@@ Summary,,%skeleton})
  Unaccepted @var{variable}s produce an error.
  Some of the accepted @var{variable}s are:
  
 -@itemize @bullet
 +@table @code
 +@c ================================================== api.namespace
 +@item api.namespace
 +@findex %define api.namespace
 +@itemize
 +@item Languages(s): C++
 +
 +@item Purpose: Specify the namespace for the parser class.
 +For example, if you specify:
 +
 +@example
 +%define api.namespace "foo::bar"
 +@end example
 +
 +Bison uses @code{foo::bar} verbatim in references such as:
 +
 +@example
 +foo::bar::parser::semantic_type
 +@end example
 +
 +However, to open a namespace, Bison removes any leading @code{::} and then
 +splits on any remaining occurrences:
 +
 +@example
 +namespace foo @{ namespace bar @{
 +  class position;
 +  class location;
 +@} @}
 +@end example
 +
 +@item Accepted Values:
 +Any absolute or relative C++ namespace reference without a trailing
 +@code{"::"}.  For example, @code{"foo"} or @code{"::foo::bar"}.
 +
 +@item Default Value:
 +The value specified by @code{%name-prefix}, which defaults to @code{yy}.
 +This usage of @code{%name-prefix} is for backward compatibility and can
 +be confusing since @code{%name-prefix} also specifies the textual prefix
 +for the lexical analyzer function.  Thus, if you specify
 +@code{%name-prefix}, it is best to also specify @samp{%define
 +api.namespace} so that @code{%name-prefix} @emph{only} affects the
 +lexical analyzer function.  For example, if you specify:
 +
 +@example
 +%define api.namespace "foo"
 +%name-prefix "bar::"
 +@end example
 +
 +The parser namespace is @code{foo} and @code{yylex} is referenced as
 +@code{bar::lex}.
 +@end itemize
 +@c namespace
 +
 +
  @c ================================================== api.prefix
 -@item @code{api.prefix}
 +@item api.prefix
  @findex %define api.prefix
  
  @itemize @bullet
  @end itemize
  
  @c ================================================== api.pure
 -@item @code{api.pure}
 +@item api.pure
  @findex %define api.pure
  
  @itemize @bullet
  
  @item Default Value: @code{false}
  @end itemize
 +@c api.pure
 +
  
 -@c ================================================== api.push-pull
  
 -@item @code{api.push-pull}
 +@c ================================================== api.push-pull
 +@item api.push-pull
  @findex %define api.push-pull
  
  @itemize @bullet
@@@ -5503,73 -5353,10 +5504,73 @@@ More user feedback will help to stabili
  
  @item Default Value: @code{pull}
  @end itemize
 +@c api.push-pull
 +
 +
 +
 +@c ================================================== api.tokens.prefix
 +@item api.tokens.prefix
 +@findex %define api.tokens.prefix
 +
 +@itemize
 +@item Languages(s): all
 +
 +@item Purpose:
 +Add a prefix to the token names when generating their definition in the
 +target language.  For instance
 +
 +@example
 +%token FILE for ERROR
 +%define api.tokens.prefix "TOK_"
 +%%
 +start: FILE for ERROR;
 +@end example
 +
 +@noindent
 +generates the definition of the symbols @code{TOK_FILE}, @code{TOK_for},
 +and @code{TOK_ERROR} in the generated source files.  In particular, the
 +scanner must use these prefixed token names, while the grammar itself
 +may still use the short names (as in the sample rule given above).  The
 +generated informational files (@file{*.output}, @file{*.xml},
 +@file{*.dot}) are not modified by this prefix.  See @ref{Calc++ Parser}
 +and @ref{Calc++ Scanner}, for a complete example.
 +
 +@item Accepted Values:
 +Any string.  Should be a valid identifier prefix in the target language,
 +in other words, it should typically be an identifier itself (sequence of
 +letters, underscores, and ---not at the beginning--- digits).
 +
 +@item Default Value:
 +empty
 +@end itemize
 +@c api.tokens.prefix
 +
 +
 +@c ================================================== lex_symbol
 +@item lex_symbol
 +@findex %define lex_symbol
 +
 +@itemize @bullet
 +@item Language(s):
 +C++
 +
 +@item Purpose:
 +When variant-based semantic values are enabled (@pxref{C++ Variants}),
 +request that symbols be handled as a whole (type, value, and possibly
 +location) in the scanner.  @xref{Complete Symbols}, for details.
 +
 +@item Accepted Values:
 +Boolean.
 +
 +@item Default Value:
 +@code{false}
 +@end itemize
 +@c lex_symbol
 +
  
  @c ================================================== lr.default-reductions
  
 -@item @code{lr.default-reductions}
 +@item lr.default-reductions
  @findex %define lr.default-reductions
  
  @itemize @bullet
@@@ -5590,7 -5377,7 +5591,7 @@@ feedback will help to stabilize it.
  
  @c ============================================ lr.keep-unreachable-states
  
 -@item @code{lr.keep-unreachable-states}
 +@item lr.keep-unreachable-states
  @findex %define lr.keep-unreachable-states
  
  @itemize @bullet
@@@ -5600,11 -5387,10 +5601,11 @@@ remain in the parser tables.  @xref{Unr
  @item Accepted Values: Boolean
  @item Default Value: @code{false}
  @end itemize
 +@c lr.keep-unreachable-states
  
  @c ================================================== lr.type
  
 -@item @code{lr.type}
 +@item lr.type
  @findex %define lr.type
  
  @itemize @bullet
@@@ -5619,62 -5405,62 +5620,62 @@@ More user feedback will help to stabili
  @item Default Value: @code{lalr}
  @end itemize
  
 -@c ================================================== namespace
  
 -@item @code{namespace}
 +@c ================================================== namespace
 +@item namespace
  @findex %define namespace
 +Obsoleted by @code{api.namespace}
 +@c namespace
  
 -@itemize
 -@item Languages(s): C++
  
 -@item Purpose: Specify the namespace for the parser class.
 -For example, if you specify:
 +@c ================================================== parse.assert
 +@item parse.assert
 +@findex %define parse.assert
  
 -@smallexample
 -%define namespace "foo::bar"
 -@end smallexample
 +@itemize
 +@item Languages(s): C++
  
 -Bison uses @code{foo::bar} verbatim in references such as:
 +@item Purpose: Issue runtime assertions to catch invalid uses.
 +In C++, when variants are used (@pxref{C++ Variants}), symbols must be
 +constructed and
 +destroyed properly.  This option checks these constraints.
  
 -@smallexample
 -foo::bar::parser::semantic_type
 -@end smallexample
 +@item Accepted Values: Boolean
  
 -However, to open a namespace, Bison removes any leading @code{::} and then
 -splits on any remaining occurrences:
 +@item Default Value: @code{false}
 +@end itemize
 +@c parse.assert
  
 -@smallexample
 -namespace foo @{ namespace bar @{
 -  class position;
 -  class location;
 -@} @}
 -@end smallexample
 -
 -@item Accepted Values: Any absolute or relative C++ namespace reference without
 -a trailing @code{"::"}.
 -For example, @code{"foo"} or @code{"::foo::bar"}.
 -
 -@item Default Value: The value specified by @code{%name-prefix}, which defaults
 -to @code{yy}.
 -This usage of @code{%name-prefix} is for backward compatibility and can be
 -confusing since @code{%name-prefix} also specifies the textual prefix for the
 -lexical analyzer function.
 -Thus, if you specify @code{%name-prefix}, it is best to also specify
 -@code{%define namespace} so that @code{%name-prefix} @emph{only} affects the
 -lexical analyzer function.
 -For example, if you specify:
  
 -@smallexample
 -%define namespace "foo"
 -%name-prefix "bar::"
 -@end smallexample
 +@c ================================================== parse.error
 +@item parse.error
 +@findex %define parse.error
 +@itemize
 +@item Languages(s):
 +all
 +@item Purpose:
 +Control the kind of error messages passed to the error reporting
 +function.  @xref{Error Reporting, ,The Error Reporting Function
 +@code{yyerror}}.
 +@item Accepted Values:
 +@itemize
 +@item @code{simple}
 +Error messages passed to @code{yyerror} are simply @w{@code{"syntax
 +error"}}.
 +@item @code{verbose}
 +Error messages report the unexpected token, and possibly the expected ones.
 +However, this report can often be incorrect when LAC is not enabled
 +(@pxref{LAC}).
 +@end itemize
  
 -The parser namespace is @code{foo} and @code{yylex} is referenced as
 -@code{bar::lex}.
 +@item Default Value:
 +@code{simple}
  @end itemize
 +@c parse.error
 +
  
  @c ================================================== parse.lac
 -@item @code{parse.lac}
 +@item parse.lac
  @findex %define parse.lac
  
  @itemize
@@@ -5685,50 -5471,7 +5686,50 @@@ syntax error handling.  @xref{LAC}
  @item Accepted Values: @code{none}, @code{full}
  @item Default Value: @code{none}
  @end itemize
 +@c parse.lac
 +
 +@c ================================================== parse.trace
 +@item parse.trace
 +@findex %define parse.trace
 +
 +@itemize
 +@item Languages(s): C, C++, Java
 +
 +@item Purpose: Require parser instrumentation for tracing.
 +@xref{Tracing, ,Tracing Your Parser}.
 +
 +In C/C++, define the macro @code{YYDEBUG} (or @code{@var{prefix}DEBUG} with
 +@samp{%define api.prefix @var{prefix}}), see @ref{Multiple Parsers,
 +,Multiple Parsers in the Same Program}) to 1 in the parser implementation
 +file if it is not already defined, so that the debugging facilities are
 +compiled.
 +
 +@item Accepted Values: Boolean
 +
 +@item Default Value: @code{false}
 +@end itemize
 +@c parse.trace
 +
 +@c ================================================== variant
 +@item variant
 +@findex %define variant
 +
 +@itemize @bullet
 +@item Language(s):
 +C++
 +
 +@item Purpose:
 +Request variant-based semantic values.
 +@xref{C++ Variants}.
 +
 +@item Accepted Values:
 +Boolean.
 +
 +@item Default Value:
 +@code{false}
  @end itemize
 +@c variant
 +@end table
  
  
  @node %code Summary
@@@ -5774,7 -5517,7 +5775,7 @@@ file
  Not all qualifiers are accepted for all target languages.  Unaccepted
  qualifiers produce an error.  Some of the accepted qualifiers are:
  
 -@itemize @bullet
 +@table @code
  @item requires
  @findex %code requires
  
@@@ -5838,7 -5581,7 +5839,7 @@@ parser implementation file.  For exampl
  @item Location(s): The parser Java file after any Java package directive and
  before any class definitions.
  @end itemize
 -@end itemize
 +@end table
  
  Though we say the insertion locations are language-dependent, they are
  technically skeleton-dependent.  Writers of non-standard skeletons
@@@ -6000,10 -5743,10 +6001,10 @@@ If you use a reentrant parser, you can 
  parameter information to it in a reentrant way.  To do so, use the
  declaration @code{%parse-param}:
  
 -@deffn {Directive} %parse-param @{@var{argument-declaration}@}
 +@deffn {Directive} %parse-param @{@var{argument-declaration}@} @dots{}
  @findex %parse-param
 -Declare that an argument declared by the braced-code
 -@var{argument-declaration} is an additional @code{yyparse} argument.
 +Declare that one or more
 +@var{argument-declaration} are additional @code{yyparse} arguments.
  The @var{argument-declaration} is used when declaring
  functions or prototypes.  The last identifier in
  @var{argument-declaration} must be the argument name.
  Here's an example.  Write this in the parser:
  
  @example
 -%parse-param @{int *nastiness@}
 -%parse-param @{int *randomness@}
 +%parse-param @{int *nastiness@} @{int *randomness@}
  @end example
  
  @noindent
@@@ -6042,8 -5786,8 +6043,8 @@@ exp: @dots{}    @{ @dots{}; *randomnes
  More user feedback will help to stabilize it.)
  
  You call the function @code{yypush_parse} to parse a single token.  This
 -function is available if either the @code{%define api.push-pull push} or
 -@code{%define api.push-pull both} declaration is used.
 +function is available if either the @samp{%define api.push-pull push} or
 +@samp{%define api.push-pull both} declaration is used.
  @xref{Push Decl, ,A Push Parser}.
  
  @deftypefun int yypush_parse (yypstate *yyps)
@@@ -6060,7 -5804,7 +6061,7 @@@ required to finish parsing the grammar
  More user feedback will help to stabilize it.)
  
  You call the function @code{yypull_parse} to parse the rest of the input
 -stream.  This function is available if the @code{%define api.push-pull both}
 +stream.  This function is available if the @samp{%define api.push-pull both}
  declaration is used.
  @xref{Push Decl, ,A Push Parser}.
  
@@@ -6076,8 -5820,8 +6077,8 @@@ The value returned by @code{yypull_pars
  More user feedback will help to stabilize it.)
  
  You call the function @code{yypstate_new} to create a new parser instance.
 -This function is available if either the @code{%define api.push-pull push} or
 -@code{%define api.push-pull both} declaration is used.
 +This function is available if either the @samp{%define api.push-pull push} or
 +@samp{%define api.push-pull both} declaration is used.
  @xref{Push Decl, ,A Push Parser}.
  
  @deftypefun {yypstate*} yypstate_new (void)
@@@ -6095,8 -5839,8 +6096,8 @@@ allocated
  More user feedback will help to stabilize it.)
  
  You call the function @code{yypstate_delete} to delete a parser instance.
 -function is available if either the @code{%define api.push-pull push} or
 -@code{%define api.push-pull both} declaration is used.
 +function is available if either the @samp{%define api.push-pull push} or
 +@samp{%define api.push-pull both} declaration is used.
  @xref{Push Decl, ,A Push Parser}.
  
  @deftypefun void yypstate_delete (yypstate *yyps)
@@@ -6285,7 -6029,7 +6286,7 @@@ The data type of @code{yylloc} has the 
  @node Pure Calling
  @subsection Calling Conventions for Pure Parsers
  
 -When you use the Bison declaration @code{%define api.pure} to request a
 +When you use the Bison declaration @samp{%define api.pure} to request a
  pure, reentrant parser, the global communication variables @code{yylval}
  and @code{yylloc} cannot be used.  (@xref{Pure Decl, ,A Pure (Reentrant)
  Parser}.)  In such parsers the two global variables are replaced by
@@@ -6309,57 -6053,46 +6310,57 @@@ textual locations, then the type @code{
  this case, omit the second argument; @code{yylex} will be called with
  only one argument.
  
 -
 -If you wish to pass the additional parameter data to @code{yylex}, use
 +If you wish to pass additional arguments to @code{yylex}, use
  @code{%lex-param} just like @code{%parse-param} (@pxref{Parser
 -Function}).
 +Function}).  To pass additional arguments to both @code{yylex} and
 +@code{yyparse}, use @code{%param}.
  
 -@deffn {Directive} lex-param @{@var{argument-declaration}@}
 +@deffn {Directive} %lex-param @{@var{argument-declaration}@} @dots{}
  @findex %lex-param
 -Declare that the braced-code @var{argument-declaration} is an
 -additional @code{yylex} argument declaration.
 +Specify that @var{argument-declaration} are additional @code{yylex} argument
 +declarations.  You may pass one or more such declarations, which is
 +equivalent to repeating @code{%lex-param}.
 +@end deffn
 +
 +@deffn {Directive} %param @{@var{argument-declaration}@} @dots{}
 +@findex %param
 +Specify that @var{argument-declaration} are additional
 +@code{yylex}/@code{yyparse} argument declaration.  This is equivalent to
 +@samp{%lex-param @{@var{argument-declaration}@} @dots{} %parse-param
 +@{@var{argument-declaration}@} @dots{}}.  You may pass one or more
 +declarations, which is equivalent to repeating @code{%param}.
  @end deffn
  
  For instance:
  
  @example
 -%parse-param @{int *nastiness@}
 -%lex-param   @{int *nastiness@}
 -%parse-param @{int *randomness@}
 +%lex-param   @{scanner_mode *mode@}
 +%parse-param @{parser_mode *mode@}
 +%param       @{environment_type *env@}
  @end example
  
  @noindent
  results in the following signatures:
  
  @example
 -int yylex   (int *nastiness);
 -int yyparse (int *nastiness, int *randomness);
 +int yylex   (scanner_mode *mode, environment_type *env);
 +int yyparse (parser_mode *mode, environment_type *env);
  @end example
  
 -If @code{%define api.pure} is added:
 +If @samp{%define api.pure} is added:
  
  @example
 -int yylex   (YYSTYPE *lvalp, int *nastiness);
 -int yyparse (int *nastiness, int *randomness);
 +int yylex   (YYSTYPE *lvalp, scanner_mode *mode, environment_type *env);
 +int yyparse (parser_mode *mode, environment_type *env);
  @end example
  
  @noindent
 -and finally, if both @code{%define api.pure} and @code{%locations} are used:
 +and finally, if both @samp{%define api.pure} and @code{%locations} are used:
  
  @example
 -int yylex   (YYSTYPE *lvalp, YYLTYPE *llocp, int *nastiness);
 -int yyparse (int *nastiness, int *randomness);
 +int yylex   (YYSTYPE *lvalp, YYLTYPE *llocp,
 +             scanner_mode *mode, environment_type *env);
 +int yyparse (parser_mode *mode, environment_type *env);
  @end example
  
  @node Error Reporting
  @cindex parse error
  @cindex syntax error
  
 -The Bison parser detects a @dfn{syntax error} or @dfn{parse error}
 +The Bison parser detects a @dfn{syntax error} (or @dfn{parse error})
  whenever it reads a token which cannot satisfy any syntax rule.  An
  action in the grammar can also explicitly proclaim an error, using the
  macro @code{YYERROR} (@pxref{Action Features, ,Special Features for Use
@@@ -6381,8 -6114,8 +6382,8 @@@ called by @code{yyparse} whenever a syn
  receives one argument.  For a syntax error, the string is normally
  @w{@code{"syntax error"}}.
  
 -@findex %error-verbose
 -If you invoke the directive @code{%error-verbose} in the Bison declarations
 +@findex %define parse.error
 +If you invoke @samp{%define parse.error verbose} in the Bison declarations
  section (@pxref{Bison Declarations, ,The Bison Declarations Section}), then
  Bison provides a more verbose and specific error message string instead of
  just plain @w{@code{"syntax error"}}.  However, that message sometimes
@@@ -6440,7 -6173,7 +6441,7 @@@ void yyerror (int *nastiness, char cons
  Finally, GLR and Yacc parsers share the same @code{yyerror} calling
  convention for absolutely pure parsers, i.e., when the calling
  convention of @code{yylex} @emph{and} the calling convention of
 -@code{%define api.pure} are pure.
 +@samp{%define api.pure} are pure.
  I.e.:
  
  @example
@@@ -6962,8 -6695,7 +6963,8 @@@ shift and when to reduce
  
  @menu
  * Why Precedence::    An example showing why precedence is needed.
 -* Using Precedence::  How to specify precedence in Bison grammars.
 +* Using Precedence::  How to specify precedence and associativity.
 +* Precedence Only::   How to specify precedence only.
  * Precedence Examples::  How these features are used in the previous example.
  * How Precedence::    How they work.
  @end menu
@@@ -7019,9 -6751,8 +7020,9 @@@ makes right-associativity
  @node Using Precedence
  @subsection Specifying Operator Precedence
  @findex %left
 -@findex %right
  @findex %nonassoc
 +@findex %precedence
 +@findex %right
  
  Bison allows you to specify these choices with the operator precedence
  declarations @code{%left} and @code{%right}.  Each such declaration
@@@ -7031,63 -6762,13 +7032,63 @@@ those operators left-associative and th
  them right-associative.  A third alternative is @code{%nonassoc}, which
  declares that it is a syntax error to find the same operator twice ``in a
  row''.
 +The last alternative, @code{%precedence}, allows to define only
 +precedence and no associativity at all.  As a result, any
 +associativity-related conflict that remains will be reported as an
 +compile-time error.  The directive @code{%nonassoc} creates run-time
 +error: using the operator in a associative way is a syntax error.  The
 +directive @code{%precedence} creates compile-time errors: an operator
 +@emph{can} be involved in an associativity-related conflict, contrary to
 +what expected the grammar author.
  
  The relative precedence of different operators is controlled by the
 -order in which they are declared.  The first @code{%left} or
 -@code{%right} declaration in the file declares the operators whose
 +order in which they are declared.  The first precedence/associativity
 +declaration in the file declares the operators whose
  precedence is lowest, the next such declaration declares the operators
  whose precedence is a little higher, and so on.
  
 +@node Precedence Only
 +@subsection Specifying Precedence Only
 +@findex %precedence
 +
 +Since POSIX Yacc defines only @code{%left}, @code{%right}, and
 +@code{%nonassoc}, which all defines precedence and associativity, little
 +attention is paid to the fact that precedence cannot be defined without
 +defining associativity.  Yet, sometimes, when trying to solve a
 +conflict, precedence suffices.  In such a case, using @code{%left},
 +@code{%right}, or @code{%nonassoc} might hide future (associativity
 +related) conflicts that would remain hidden.
 +
 +The dangling @code{else} ambiguity (@pxref{Shift/Reduce, , Shift/Reduce
 +Conflicts}) can be solved explicitly.  This shift/reduce conflicts occurs
 +in the following situation, where the period denotes the current parsing
 +state:
 +
 +@example
 +if @var{e1} then if  @var{e2} then @var{s1} . else @var{s2}
 +@end example
 +
 +The conflict involves the reduction of the rule @samp{IF expr THEN
 +stmt}, which precedence is by default that of its last token
 +(@code{THEN}), and the shifting of the token @code{ELSE}.  The usual
 +disambiguation (attach the @code{else} to the closest @code{if}),
 +shifting must be preferred, i.e., the precedence of @code{ELSE} must be
 +higher than that of @code{THEN}.  But neither is expected to be involved
 +in an associativity related conflict, which can be specified as follows.
 +
 +@example
 +%precedence THEN
 +%precedence ELSE
 +@end example
 +
 +The unary-minus is another typical example where associativity is
 +usually over-specified, see @ref{Infix Calc, , Infix Notation
 +Calculator: @code{calc}}.  The @code{%left} directive is traditionally
 +used to declare the precedence of @code{NEG}, which is more than needed
 +since it also defines its associativity.  While this is harmless in the
 +traditional example, who knows how @code{NEG} might be used in future
 +evolutions of the grammar@dots{}
 +
  @node Precedence Examples
  @subsection Precedence Examples
  
@@@ -7149,8 -6830,8 +7150,8 @@@ outlandish at first, but it is really v
  sign typically has a very high precedence as a unary operator, and a
  somewhat lower precedence (lower than multiplication) as a binary operator.
  
 -The Bison precedence declarations, @code{%left}, @code{%right} and
 -@code{%nonassoc}, can only be used once for a given token; so a token has
 +The Bison precedence declarations
 +can only be used once for a given token; so a token has
  only one precedence declared in this way.  For context-dependent
  precedence, you need to use an additional mechanism: the @code{%prec}
  modifier for rules.
@@@ -7495,9 -7176,9 +7496,9 @@@ The default behavior of Bison's LR-base
  historical reasons, but that behavior is often not robust.  For example, in
  the previous section, we discussed the mysterious conflicts that can be
  produced by LALR(1), Bison's default parser table construction algorithm.
 -Another example is Bison's @code{%error-verbose} directive, which instructs
 -the generated parser to produce verbose syntax error messages, which can
 -sometimes contain incorrect information.
 +Another example is Bison's @code{%define parse.error verbose} directive,
 +which instructs the generated parser to produce verbose syntax error
 +messages, which can sometimes contain incorrect information.
  
  In this section, we explore several modern features of Bison that allow you
  to tune fundamental aspects of the generated LR-based parsers.  Some of
@@@ -8021,14 -7702,12 +8022,14 @@@ that allows variable-length arrays.  Th
  
  Do not allow @code{YYINITDEPTH} to be greater than @code{YYMAXDEPTH}.
  
 -@c FIXME: C++ output.
 -Because of semantic differences between C and C++, the deterministic
 -parsers in C produced by Bison cannot grow when compiled
 -by C++ compilers.  In this precise case (compiling a C parser as C++) you are
 -suggested to grow @code{YYINITDEPTH}.  The Bison maintainers hope to fix
 -this deficiency in a future release.
 +You can generate a deterministic parser containing C++ user code from
 +the default (C) skeleton, as well as from the C++ skeleton
 +(@pxref{C++ Parsers}).  However, if you do use the default skeleton
 +and want to allow the parsing stack to grow,
 +be careful not to use semantic types or location types that require
 +non-trivial copy constructors.
 +The C skeleton bypasses these constructors when copying data to
 +new, larger stacks.
  
  @node Error Recovery
  @chapter Error Recovery
@@@ -8835,19 -8514,12 +8836,19 @@@ otherwise it defines @code{YYDEBUG} to 
  @item the directive @samp{%debug}
  @findex %debug
  Add the @code{%debug} directive (@pxref{Decl Summary, ,Bison Declaration
 -Summary}).  This is a Bison extension, especially useful for languages that
 -don't use a preprocessor.  Unless POSIX and Yacc portability matter to you,
 -this is the preferred solution.
 +Summary}).  This Bison extension is maintained for backward
 +compatibility with previous versions of Bison.
 +
 +@item the variable @samp{parse.trace}
 +@findex %define parse.trace
 +Add the @samp{%define parse.trace} directive (@pxref{%define
 +Summary,,parse.trace}), or pass the @option{-Dparse.trace} option
 +(@pxref{Bison Options}).  This is a Bison extension, which is especially
 +useful for languages that don't use a preprocessor.  Unless POSIX and Yacc
 +portability matter to you, this is the preferred solution.
  @end table
  
 -We suggest that you always enable the debug option so that debugging is
 +We suggest that you always enable the trace option so that debugging is
  always possible.
  
  @findex YYFPRINTF
@@@ -9499,16 -9171,16 +9500,16 @@@ The C++ deterministic parser is selecte
  
  When run, @command{bison} will create several entities in the @samp{yy}
  namespace.
 -@findex %define namespace
 -Use the @samp{%define namespace} directive to change the namespace
 -name, see @ref{%define Summary,,namespace}.  The various classes are
 -generated in the following files:
 +@findex %define api.namespace
 +Use the @samp{%define api.namespace} directive to change the namespace name,
 +see @ref{%define Summary,,api.namespace}.  The various classes are generated
 +in the following files:
  
  @table @file
  @item position.hh
  @itemx location.hh
  The definition of the classes @code{position} and @code{location},
 -used for location tracking.  @xref{C++ Location Values}.
 +used for location tracking when enabled.  @xref{C++ Location Values}.
  
  @item stack.hh
  An auxiliary class @code{stack} used by the parser.
@@@ -9534,22 -9206,11 +9535,22 @@@ for a complete and accurate documentati
  @c - YYSTYPE
  @c - Printer and destructor
  
 +Bison supports two different means to handle semantic values in C++.  One is
 +alike the C interface, and relies on unions (@pxref{C++ Unions}).  As C++
 +practitioners know, unions are inconvenient in C++, therefore another
 +approach is provided, based on variants (@pxref{C++ Variants}).
 +
 +@menu
 +* C++ Unions::             Semantic values cannot be objects
 +* C++ Variants::           Using objects as semantic values
 +@end menu
 +
 +@node C++ Unions
 +@subsubsection C++ Unions
 +
  The @code{%union} directive works as for C, see @ref{Union Decl, ,The
  Collection of Value Types}.  In particular it produces a genuine
 -@code{union}@footnote{In the future techniques to allow complex types
 -within pseudo-unions (similar to Boost variants) might be implemented to
 -alleviate these issues.}, which have a few specific features in C++.
 +@code{union}, which have a few specific features in C++.
  @itemize @minus
  @item
  The type @code{YYSTYPE} is defined but its use is discouraged: rather
@@@ -9566,98 -9227,6 +9567,98 @@@ reclaimed automatically: using the @cod
  only means to avoid leaks.  @xref{Destructor Decl, , Freeing Discarded
  Symbols}.
  
 +@node C++ Variants
 +@subsubsection C++ Variants
 +
 +Starting with version 2.6, Bison provides a @emph{variant} based
 +implementation of semantic values for C++.  This alleviates all the
 +limitations reported in the previous section, and in particular, object
 +types can be used without pointers.
 +
 +To enable variant-based semantic values, set @code{%define} variable
 +@code{variant} (@pxref{%define Summary,, variant}).  Once this defined,
 +@code{%union} is ignored, and instead of using the name of the fields of the
 +@code{%union} to ``type'' the symbols, use genuine types.
 +
 +For instance, instead of
 +
 +@example
 +%union
 +@{
 +  int ival;
 +  std::string* sval;
 +@}
 +%token <ival> NUMBER;
 +%token <sval> STRING;
 +@end example
 +
 +@noindent
 +write
 +
 +@example
 +%token <int> NUMBER;
 +%token <std::string> STRING;
 +@end example
 +
 +@code{STRING} is no longer a pointer, which should fairly simplify the user
 +actions in the grammar and in the scanner (in particular the memory
 +management).
 +
 +Since C++ features destructors, and since it is customary to specialize
 +@code{operator<<} to support uniform printing of values, variants also
 +typically simplify Bison printers and destructors.
 +
 +Variants are stricter than unions.  When based on unions, you may play any
 +dirty game with @code{yylval}, say storing an @code{int}, reading a
 +@code{char*}, and then storing a @code{double} in it.  This is no longer
 +possible with variants: they must be initialized, then assigned to, and
 +eventually, destroyed.
 +
 +@deftypemethod {semantic_type} {T&} build<T> ()
 +Initialize, but leave empty.  Returns the address where the actual value may
 +be stored.  Requires that the variant was not initialized yet.
 +@end deftypemethod
 +
 +@deftypemethod {semantic_type} {T&} build<T> (const T& @var{t})
 +Initialize, and copy-construct from @var{t}.
 +@end deftypemethod
 +
 +
 +@strong{Warning}: We do not use Boost.Variant, for two reasons.  First, it
 +appeared unacceptable to require Boost on the user's machine (i.e., the
 +machine on which the generated parser will be compiled, not the machine on
 +which @command{bison} was run).  Second, for each possible semantic value,
 +Boost.Variant not only stores the value, but also a tag specifying its
 +type.  But the parser already ``knows'' the type of the semantic value, so
 +that would be duplicating the information.
 +
 +Therefore we developed light-weight variants whose type tag is external (so
 +they are really like @code{unions} for C++ actually).  But our code is much
 +less mature that Boost.Variant.  So there is a number of limitations in
 +(the current implementation of) variants:
 +@itemize
 +@item
 +Alignment must be enforced: values should be aligned in memory according to
 +the most demanding type.  Computing the smallest alignment possible requires
 +meta-programming techniques that are not currently implemented in Bison, and
 +therefore, since, as far as we know, @code{double} is the most demanding
 +type on all platforms, alignments are enforced for @code{double} whatever
 +types are actually used.  This may waste space in some cases.
 +
 +@item
 +Our implementation is not conforming with strict aliasing rules.  Alias
 +analysis is a technique used in optimizing compilers to detect when two
 +pointers are disjoint (they cannot ``meet'').  Our implementation breaks
 +some of the rules that G++ 4.4 uses in its alias analysis, so @emph{strict
 +alias analysis must be disabled}.  Use the option
 +@option{-fno-strict-aliasing} to compile the generated parser.
 +
 +@item
 +There might be portability issues we are not aware of.
 +@end itemize
 +
 +As far as we know, these limitations @emph{can} be alleviated.  All it takes
 +is some time and/or some talented C++ hacker willing to contribute to Bison.
  
  @node C++ Location Values
  @subsection C++ Location Values
@@@ -9801,7 -9370,7 +9802,7 @@@ additional argument for its constructor
  
  @defcv {Type} {parser} {semantic_type}
  @defcvx {Type} {parser} {location_type}
 -The types for semantics value and locations.
 +The types for semantic values and locations (if enabled).
  @end defcv
  
  @defcv {Type} {parser} {token}
@@@ -9812,27 -9381,11 +9813,27 @@@ use @code{yy::parser::token::FOO}.  Th
  (@pxref{Calc++ Scanner}).
  @end defcv
  
 +@defcv {Type} {parser} {syntax_error}
 +This class derives from @code{std::runtime_error}.  Throw instances of it
 +from the scanner or from the user actions to raise parse errors.  This is
 +equivalent with first
 +invoking @code{error} to report the location and message of the syntax
 +error, and then to invoke @code{YYERROR} to enter the error-recovery mode.
 +But contrary to @code{YYERROR} which can only be invoked from user actions
 +(i.e., written in the action itself), the exception can be thrown from
 +function invoked from the user action.
 +@end defcv
 +
  @deftypemethod {parser} {} parser (@var{type1} @var{arg1}, ...)
  Build a new parser object.  There are no arguments by default, unless
  @samp{%parse-param @{@var{type1} @var{arg1}@}} was used.
  @end deftypemethod
  
 +@deftypemethod {syntax_error} {} syntax_error (const location_type& @var{l}, const std::string& @var{m})
 +@deftypemethodx {syntax_error} {} syntax_error (const std::string& @var{m})
 +Instantiate a syntax-error exception.
 +@end deftypemethod
 +
  @deftypemethod {parser} {int} parse ()
  Run the syntactic analysis, and return 0 on success, 1 otherwise.
  @end deftypemethod
@@@ -9850,11 -9403,9 +9851,11 @@@ or nonzero, full tracing
  @end deftypemethod
  
  @deftypemethod {parser} {void} error (const location_type& @var{l}, const std::string& @var{m})
 +@deftypemethodx {parser} {void} error (const std::string& @var{m})
  The definition for this member function must be supplied by the user:
  the parser uses it to report a parser error occurring at @var{l},
 -described by @var{m}.
 +described by @var{m}.  If location tracking is not enabled, the second
 +signature is used.
  @end deftypemethod
  
  
  
  The parser invokes the scanner by calling @code{yylex}.  Contrary to C
  parsers, C++ parsers are always pure: there is no point in using the
 -@code{%define api.pure} directive.  Therefore the interface is as follows.
 +@samp{%define api.pure} directive.  The actual interface with @code{yylex}
 +depends whether you use unions, or variants.
 +
 +@menu
 +* Split Symbols::         Passing symbols as two/three components
 +* Complete Symbols::      Making symbols a whole
 +@end menu
 +
 +@node Split Symbols
 +@subsubsection Split Symbols
 +
 +Therefore the interface is as follows.
  
  @deftypemethod {parser} {int} yylex (semantic_type* @var{yylval}, location_type* @var{yylloc}, @var{type1} @var{arg1}, ...)
 -Return the next token.  Its type is the return value, its semantic
 -value and location being @var{yylval} and @var{yylloc}.  Invocations of
 +@deftypemethodx {parser} {int} yylex (semantic_type* @var{yylval}, @var{type1} @var{arg1}, ...)
 +Return the next token.  Its type is the return value, its semantic value and
 +location (if enabled) being @var{yylval} and @var{yylloc}.  Invocations of
  @samp{%lex-param @{@var{type1} @var{arg1}@}} yield additional arguments.
  @end deftypemethod
  
 +Note that when using variants, the interface for @code{yylex} is the same,
 +but @code{yylval} is handled differently.
 +
 +Regular union-based code in Lex scanner typically look like:
 +
 +@example
 +[0-9]+   @{
 +           yylval.ival = text_to_int (yytext);
 +           return yy::parser::INTEGER;
 +         @}
 +[a-z]+   @{
 +           yylval.sval = new std::string (yytext);
 +           return yy::parser::IDENTIFIER;
 +         @}
 +@end example
 +
 +Using variants, @code{yylval} is already constructed, but it is not
 +initialized.  So the code would look like:
 +
 +@example
 +[0-9]+   @{
 +           yylval.build<int>() = text_to_int (yytext);
 +           return yy::parser::INTEGER;
 +         @}
 +[a-z]+   @{
 +           yylval.build<std::string> = yytext;
 +           return yy::parser::IDENTIFIER;
 +         @}
 +@end example
 +
 +@noindent
 +or
 +
 +@example
 +[0-9]+   @{
 +           yylval.build(text_to_int (yytext));
 +           return yy::parser::INTEGER;
 +         @}
 +[a-z]+   @{
 +           yylval.build(yytext);
 +           return yy::parser::IDENTIFIER;
 +         @}
 +@end example
 +
 +
 +@node Complete Symbols
 +@subsubsection Complete Symbols
 +
 +If you specified both @code{%define variant} and @code{%define lex_symbol},
 +the @code{parser} class also defines the class @code{parser::symbol_type}
 +which defines a @emph{complete} symbol, aggregating its type (i.e., the
 +traditional value returned by @code{yylex}), its semantic value (i.e., the
 +value passed in @code{yylval}, and possibly its location (@code{yylloc}).
 +
 +@deftypemethod {symbol_type} {} symbol_type (token_type @var{type},  const semantic_type& @var{value}, const location_type& @var{location})
 +Build a complete terminal symbol which token type is @var{type}, and which
 +semantic value is @var{value}.  If location tracking is enabled, also pass
 +the @var{location}.
 +@end deftypemethod
 +
 +This interface is low-level and should not be used for two reasons.  First,
 +it is inconvenient, as you still have to build the semantic value, which is
 +a variant, and second, because consistency is not enforced: as with unions,
 +it is still possible to give an integer as semantic value for a string.
 +
 +So for each token type, Bison generates named constructors as follows.
 +
 +@deftypemethod {symbol_type} {} make_@var{token} (const @var{value_type}& @var{value}, const location_type& @var{location})
 +@deftypemethodx {symbol_type} {} make_@var{token} (const location_type& @var{location})
 +Build a complete terminal symbol for the token type @var{token} (not
 +including the @code{api.tokens.prefix}) whose possible semantic value is
 +@var{value} of adequate @var{value_type}.  If location tracking is enabled,
 +also pass the @var{location}.
 +@end deftypemethod
 +
 +For instance, given the following declarations:
 +
 +@example
 +%define api.tokens.prefix "TOK_"
 +%token <std::string> IDENTIFIER;
 +%token <int> INTEGER;
 +%token COLON;
 +@end example
 +
 +@noindent
 +Bison generates the following functions:
 +
 +@example
 +symbol_type make_IDENTIFIER(const std::string& v,
 +                            const location_type& l);
 +symbol_type make_INTEGER(const int& v,
 +                         const location_type& loc);
 +symbol_type make_COLON(const location_type& loc);
 +@end example
 +
 +@noindent
 +which should be used in a Lex-scanner as follows.
 +
 +@example
 +[0-9]+   return yy::parser::make_INTEGER(text_to_int (yytext), loc);
 +[a-z]+   return yy::parser::make_IDENTIFIER(yytext, loc);
 +":"      return yy::parser::make_COLON(loc);
 +@end example
 +
 +Tokens that do not have an identifier are not accessible: you cannot simply
 +use characters such as @code{':'}, they must be declared with @code{%token}.
  
  @node A Complete C++ Example
  @subsection A Complete C++ Example
  
  This section demonstrates the use of a C++ parser with a simple but
  complete example.  This example should be available on your system,
 -ready to compile, in the directory @dfn{../bison/examples/calc++}.  It
 +ready to compile, in the directory @dfn{.../bison/examples/calc++}.  It
  focuses on the use of Bison, therefore the design of the various C++
  classes is very naive: no accessors, no encapsulation of members etc.
  We will use a Lex scanner, and more precisely, a Flex scanner, to
 -demonstrate the various interaction.  A hand written scanner is
 +demonstrate the various interactions.  A hand-written scanner is
  actually easier to interface with.
  
  @menu
@@@ -10066,8 -9499,11 +10067,8 @@@ factor both as follows
  @comment file: calc++-driver.hh
  @example
  // Tell Flex the lexer's prototype ...
 -# define YY_DECL                                        \
 -  yy::calcxx_parser::token_type                         \
 -  yylex (yy::calcxx_parser::semantic_type* yylval,      \
 -         yy::calcxx_parser::location_type* yylloc,      \
 -         calcxx_driver& driver)
 +# define YY_DECL \
 +  yy::calcxx_parser::symbol_type yylex (calcxx_driver& driver)
  // ... and declare it for the parser's sake.
  YY_DECL;
  @end example
@@@ -10091,8 -9527,8 +10092,8 @@@ public
  @end example
  
  @noindent
 -To encapsulate the coordination with the Flex scanner, it is useful to
 -have two members function to open and close the scanning phase.
 +To encapsulate the coordination with the Flex scanner, it is useful to have
 +member functions to open and close the scanning phase.
  
  @comment file: calc++-driver.hh
  @example
@@@ -10107,13 -9543,9 +10108,13 @@@ Similarly for the parser itself
  
  @comment file: calc++-driver.hh
  @example
 -  // Run the parser.  Return 0 on success.
 +  // Run the parser on file F.
 +  // Return 0 on success.
    int parse (const std::string& f);
 +  // The name of the file being parsed.
 +  // Used later to pass the file name to the location tracker.
    std::string file;
 +  // Whether parser traces should be generated.
    bool trace_parsing;
  @end example
  
@@@ -10195,35 -9627,19 +10196,35 @@@ the grammar for
  %define parser_class_name "calcxx_parser"
  @end example
  
 +@noindent
 +@findex %define variant
 +@findex %define lex_symbol
 +This example will use genuine C++ objects as semantic values, therefore, we
 +require the variant-based interface.  To make sure we properly use it, we
 +enable assertions.  To fully benefit from type-safety and more natural
 +definition of ``symbol'', we enable @code{lex_symbol}.
 +
 +@comment file: calc++-parser.yy
 +@example
 +%define variant
 +%define parse.assert
 +%define lex_symbol
 +@end example
 +
  @noindent
  @findex %code requires
 -Then come the declarations/inclusions needed to define the
 -@code{%union}.  Because the parser uses the parsing driver and
 -reciprocally, both cannot include the header of the other.  Because the
 +Then come the declarations/inclusions needed by the semantic values.
 +Because the parser uses the parsing driver and reciprocally, both would like
 +to include the header of the other, which is, of course, insane.  This
 +mutual dependency will be broken using forward declarations.  Because the
  driver's header needs detailed knowledge about the parser class (in
 -particular its inner types), it is the parser's header which will simply
 -use a forward declaration of the driver.
 -@xref{%code Summary}.
 +particular its inner types), it is the parser's header which will use a
 +forward declaration of the driver.  @xref{%code Summary}.
  
  @comment file: calc++-parser.yy
  @example
 -%code requires @{
 +%code requires
 +@{
  # include <string>
  class calcxx_driver;
  @}
@@@ -10237,14 -9653,15 +10238,14 @@@ global variables
  @comment file: calc++-parser.yy
  @example
  // The parsing context.
 -%parse-param @{ calcxx_driver& driver @}
 -%lex-param   @{ calcxx_driver& driver @}
 +%param @{ calcxx_driver& driver @}
  @end example
  
  @noindent
 -Then we request the location tracking feature, and initialize the
 +Then we request location tracking, and initialize the
  first location's file name.  Afterward new locations are computed
  relatively to the previous locations: the file name will be
 -automatically propagated.
 +propagated.
  
  @comment file: calc++-parser.yy
  @example
  @end example
  
  @noindent
 -Use the two following directives to enable parser tracing and verbose error
 +Use the following two directives to enable parser tracing and verbose error
  messages.  However, verbose error messages can contain incorrect information
  (@pxref{LAC}).
  
  @comment file: calc++-parser.yy
  @example
 -%debug
 -%error-verbose
 -@end example
 -
 -@noindent
 -Semantic values cannot use ``real'' objects, but only pointers to
 -them.
 -
 -@comment file: calc++-parser.yy
 -@example
 -// Symbols.
 -%union
 -@{
 -  int          ival;
 -  std::string *sval;
 -@};
 +%define parse.trace
 +%define parse.error verbose
  @end example
  
  @noindent
@@@ -10274,8 -9705,7 +10275,8 @@@ The code between @samp{%code @{} and @s
  
  @comment file: calc++-parser.yy
  @example
 -%code @{
 +%code
 +@{
  # include "calc++-driver.hh"
  @}
  @end example
  
  @noindent
  The token numbered as 0 corresponds to end of file; the following line
 -allows for nicer error messages referring to ``end of file'' instead
 -of ``$end''.  Similarly user friendly named are provided for each
 -symbol.  Note that the tokens names are prefixed by @code{TOKEN_} to
 -avoid name clashes.
 +allows for nicer error messages referring to ``end of file'' instead of
 +``$end''.  Similarly user friendly names are provided for each symbol.  To
 +avoid name clashes in the generated files (@pxref{Calc++ Scanner}), prefix
 +tokens with @code{TOK_} (@pxref{%define Summary,,api.tokens.prefix}).
 +
 +@comment file: calc++-parser.yy
 +@example
 +%define api.tokens.prefix "TOK_"
 +%token
 +  END  0  "end of file"
 +  ASSIGN  ":="
 +  MINUS   "-"
 +  PLUS    "+"
 +  STAR    "*"
 +  SLASH   "/"
 +  LPAREN  "("
 +  RPAREN  ")"
 +;
 +@end example
 +
 +@noindent
 +Since we use variant-based semantic values, @code{%union} is not used, and
 +both @code{%type} and @code{%token} expect genuine types, as opposed to type
 +tags.
  
  @comment file: calc++-parser.yy
  @example
 -%token        END      0 "end of file"
 -%token        ASSIGN     ":="
 -%token <sval> IDENTIFIER "identifier"
 -%token <ival> NUMBER     "number"
 -%type  <ival> exp
 +%token <std::string> IDENTIFIER "identifier"
 +%token <int> NUMBER "number"
 +%type  <int> exp
  @end example
  
  @noindent
 -To enable memory deallocation during error recovery, use
 -@code{%destructor}.
 +No @code{%destructor} is needed to enable memory deallocation during error
 +recovery; the memory, for strings for instance, will be reclaimed by the
 +regular destructors.  All the values are printed using their
 +@code{operator<<}.
  
  @c FIXME: Document %printer, and mention that it takes a braced-code operand.
  @comment file: calc++-parser.yy
  @example
 -%printer    @{ yyoutput << *$$; @} "identifier"
 -%destructor @{ delete $$; @} "identifier"
 -
 -%printer    @{ yyoutput << $$; @} <ival>
 +%printer @{ yyoutput << $$; @} <*>;
  @end example
  
  @noindent
 -The grammar itself is straightforward.
 +The grammar itself is straightforward (@pxref{Location Tracking Calc, ,
 +Location Tracking Calculator: @code{ltcalc}}).
  
  @comment file: calc++-parser.yy
  @example
@@@ -10342,18 -9754,17 +10343,18 @@@ assignments
  | assignments assignment @{@};
  
  assignment:
 -     "identifier" ":=" exp
 -       @{ driver.variables[*$1] = $3; delete $1; @};
 -
 -%left '+' '-';
 -%left '*' '/';
 -exp: exp '+' exp   @{ $$ = $1 + $3; @}
 -   | exp '-' exp   @{ $$ = $1 - $3; @}
 -   | exp '*' exp   @{ $$ = $1 * $3; @}
 -   | exp '/' exp   @{ $$ = $1 / $3; @}
 -   | "identifier"  @{ $$ = driver.variables[*$1]; delete $1; @}
 -   | "number"      @{ $$ = $1; @};
 +  "identifier" ":=" exp @{ driver.variables[$1] = $3; @};
 +
 +%left "+" "-";
 +%left "*" "/";
 +exp:
 +  exp "+" exp   @{ $$ = $1 + $3; @}
 +| exp "-" exp   @{ $$ = $1 - $3; @}
 +| exp "*" exp   @{ $$ = $1 * $3; @}
 +| exp "/" exp   @{ $$ = $1 / $3; @}
 +| "(" exp ")"   @{ std::swap ($$, $2); @}
 +| "identifier"  @{ $$ = driver.variables[$1]; @}
 +| "number"      @{ std::swap ($$, $1); @};
  %%
  @end example
  
@@@ -10364,7 -9775,7 +10365,7 @@@ driver
  @comment file: calc++-parser.yy
  @example
  void
 -yy::calcxx_parser::error (const yy::calcxx_parser::location_type& l,
 +yy::calcxx_parser::error (const location_type& l,
                            const std::string& m)
  @{
    driver.error (l, m);
@@@ -10380,22 -9791,24 +10381,22 @@@ parser's to get the set of defined toke
  @comment file: calc++-scanner.ll
  @example
  %@{ /* -*- C++ -*- */
 -# include <cstdlib>
  # include <cerrno>
  # include <climits>
 +# include <cstdlib>
  # include <string>
  # include "calc++-driver.hh"
  # include "calc++-parser.hh"
  
 -/* Work around an incompatibility in flex (at least versions
 -   2.5.31 through 2.5.33): it generates code that does
 -   not conform to C89.  See Debian bug 333231
 -   <http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=333231>.  */
 +// Work around an incompatibility in flex (at least versions
 +// 2.5.31 through 2.5.33): it generates code that does
 +// not conform to C89.  See Debian bug 333231
 +// <http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=333231>.
  # undef yywrap
  # define yywrap() 1
  
 -/* By default yylex returns int, we use token_type.
 -   Unfortunately yyterminate by default returns 0, which is
 -   not of token_type.  */
 -#define yyterminate() return token::END
 +// The location of the current token.
 +static yy::location loc;
  %@}
  @end example
  
  Because there is no @code{#include}-like feature we don't need
  @code{yywrap}, we don't need @code{unput} either, and we parse an
  actual file, this is not an interactive session with the user.
 -Finally we enable the scanner tracing features.
 +Finally, we enable scanner tracing.
  
  @comment file: calc++-scanner.ll
  @example
@@@ -10423,8 -9836,8 +10424,8 @@@ blank [ \t
  @noindent
  The following paragraph suffices to track locations accurately.  Each
  time @code{yylex} is invoked, the begin position is moved onto the end
 -position.  Then when a pattern is matched, the end position is
 -advanced of its width.  In case it matched ends of lines, the end
 +position.  Then when a pattern is matched, its width is added to the end
 +column.  When matching ends of lines, the end
  cursor is adjusted, and each time blanks are matched, the begin cursor
  is moved onto the end cursor to effectively ignore the blanks
  preceding tokens.  Comments would be treated equally.
  @example
  @group
  %@{
 -# define YY_USER_ACTION  yylloc->columns (yyleng);
 +  // Code run each time a pattern is matched.
 +  # define YY_USER_ACTION  loc.columns (yyleng);
  %@}
  @end group
  %%
 +@group
  %@{
 -  yylloc->step ();
 +  // Code run each time yylex is called.
 +  loc.step ();
  %@}
 -@{blank@}+   yylloc->step ();
 -[\n]+      yylloc->lines (yyleng); yylloc->step ();
 +@end group
 +@{blank@}+   loc.step ();
 +[\n]+      loc.lines (yyleng); loc.step ();
  @end example
  
  @noindent
 -The rules are simple, just note the use of the driver to report errors.
 -It is convenient to use a typedef to shorten
 -@code{yy::calcxx_parser::token::identifier} into
 -@code{token::identifier} for instance.
 +The rules are simple.  The driver is used to report errors.
  
  @comment file: calc++-scanner.ll
  @example
 -%@{
 -  typedef yy::calcxx_parser::token token;
 -%@}
 -           /* Convert ints to the actual type of tokens.  */
 -[-+*/]     return yy::calcxx_parser::token_type (yytext[0]);
 -":="       return token::ASSIGN;
 +"-"      return yy::calcxx_parser::make_MINUS(loc);
 +"+"      return yy::calcxx_parser::make_PLUS(loc);
 +"*"      return yy::calcxx_parser::make_STAR(loc);
 +"/"      return yy::calcxx_parser::make_SLASH(loc);
 +"("      return yy::calcxx_parser::make_LPAREN(loc);
 +")"      return yy::calcxx_parser::make_RPAREN(loc);
 +":="     return yy::calcxx_parser::make_ASSIGN(loc);
 +
 +@group
  @{int@}      @{
    errno = 0;
    long n = strtol (yytext, NULL, 10);
    if (! (INT_MIN <= n && n <= INT_MAX && errno != ERANGE))
 -    driver.error (*yylloc, "integer is out of range");
 -  yylval->ival = n;
 -  return token::NUMBER;
 +    driver.error (loc, "integer is out of range");
 +  return yy::calcxx_parser::make_NUMBER(n, loc);
  @}
 -@{id@}       yylval->sval = new std::string (yytext); return token::IDENTIFIER;
 -.          driver.error (*yylloc, "invalid character");
 +@end group
 +@{id@}       return yy::calcxx_parser::make_IDENTIFIER(yytext, loc);
 +.          driver.error (loc, "invalid character");
 +<<EOF>>    return yy::calcxx_parser::make_END(loc);
  %%
  @end example
  
  @noindent
 -Finally, because the scanner related driver's member function depend
 +Finally, because the scanner-related driver's member-functions depend
  on the scanner's data, it is simpler to implement them in this file.
  
  @comment file: calc++-scanner.ll
@@@ -10520,7 -9928,6 +10521,7 @@@ The top level file, @file{calc++.cc}, p
  int
  main (int argc, char *argv[])
  @{
 +  int res = 0;
    calcxx_driver driver;
    for (int i = 1; i < argc; ++i)
      if (argv[i] == std::string ("-p"))
        driver.trace_scanning = true;
      else if (!driver.parse (argv[i]))
        std::cout << driver.result << std::endl;
 +    else
 +      res = 1;
 +  return res;
  @}
  @end group
  @end example
@@@ -10576,7 -9980,7 +10577,7 @@@ You can create documentation for genera
  Contrary to C parsers, Java parsers do not use global variables; the
  state of the parser is always local to an instance of the parser class.
  Therefore, all Java parsers are ``pure'', and the @code{%pure-parser}
 -and @code{%define api.pure} directives does not do anything when used in
 +and @samp{%define api.pure} directives does not do anything when used in
  Java.
  
  Push parsers are currently unsupported in Java and @code{%define
@@@ -10589,23 -9993,15 +10590,23 @@@ No header file can be generated for Jav
  @code{%defines} directive or the @option{-d}/@option{--defines} options.
  
  @c FIXME: Possible code change.
 -Currently, support for debugging and verbose errors are always compiled
 -in.  Thus the @code{%debug} and @code{%token-table} directives and the
 +Currently, support for tracing is always compiled
 +in.  Thus the @samp{%define parse.trace} and @samp{%token-table}
 +directives and the
  @option{-t}/@option{--debug} and @option{-k}/@option{--token-table}
  options have no effect.  This may change in the future to eliminate
 -unused code in the generated parser, so use @code{%debug} and
 -@code{%verbose-error} explicitly if needed.  Also, in the future the
 +unused code in the generated parser, so use @samp{%define parse.trace}
 +explicitly
 +if needed.  Also, in the future the
  @code{%token-table} directive might enable a public interface to
  access the token names and codes.
  
 +Getting a ``code too large'' error from the Java compiler means the code
 +hit the 64KB bytecode per method limitation of the Java class file.
 +Try reducing the amount of code in actions and static initializers;
 +otherwise, report a bug so that the parser skeleton will be improved.
 +
 +
  @node Java Semantic Values
  @subsection Java Semantic Values
  @c - No %union, specify type in %type/%token.
@@@ -10624,7 -10020,7 +10625,7 @@@ semantic values' types (class names) sh
  By default, the semantic stack is declared to have @code{Object} members,
  which means that the class types you specify can be of any class.
  To improve the type safety of the parser, you can declare the common
 -superclass of all the semantic values using the @code{%define stype}
 +superclass of all the semantic values using the @samp{%define stype}
  directive.  For example, after the following declaration:
  
  @example
@@@ -10663,11 -10059,11 +10664,11 @@@ class defines a @dfn{position}, a singl
  defines a class representing a @dfn{location}, a range composed of a pair of
  positions (possibly spanning several files).  The location class is an inner
  class of the parser; the name is @code{Location} by default, and may also be
 -renamed using @code{%define location_type "@var{class-name}"}.
 +renamed using @samp{%define location_type "@var{class-name}"}.
  
  The location class treats the position as a completely opaque value.
  By default, the class name is @code{Position}, but this can be changed
 -with @code{%define position_type "@var{class-name}"}.  This class must
 +with @samp{%define position_type "@var{class-name}"}.  This class must
  be supplied by the user.
  
  
@@@ -10702,22 -10098,20 +10703,22 @@@ properly, the position class should ove
  The name of the generated parser class defaults to @code{YYParser}.  The
  @code{YY} prefix may be changed using the @code{%name-prefix} directive
  or the @option{-p}/@option{--name-prefix} option.  Alternatively, use
 -@code{%define parser_class_name "@var{name}"} to give a custom name to
 +@samp{%define parser_class_name "@var{name}"} to give a custom name to
  the class.  The interface of this class is detailed below.
  
  By default, the parser class has package visibility.  A declaration
 -@code{%define public} will change to public visibility.  Remember that,
 +@samp{%define public} will change to public visibility.  Remember that,
  according to the Java language specification, the name of the @file{.java}
  file should match the name of the class in this case.  Similarly, you can
  use @code{abstract}, @code{final} and @code{strictfp} with the
  @code{%define} declaration to add other modifiers to the parser class.
 +A single @samp{%define annotations "@var{annotations}"} directive can
 +be used to add any number of annotations to the parser class.
  
  The Java package name of the parser class can be specified using the
 -@code{%define package} directive.  The superclass and the implemented
 +@samp{%define package} directive.  The superclass and the implemented
  interfaces of the parser class can be specified with the @code{%define
 -extends} and @code{%define implements} directives.
 +extends} and @samp{%define implements} directives.
  
  The parser class defines an inner class, @code{Location}, that is used
  for location tracking (see @ref{Java Location Values}), and a inner
@@@ -10726,33 -10120,30 +10727,33 @@@ these inner class/interface, and the me
  below, all the other members and fields are preceded with a @code{yy} or
  @code{YY} prefix to avoid clashes with user code.
  
 -@c FIXME: The following constants and variables are still undocumented:
 -@c @code{bisonVersion}, @code{bisonSkeleton} and @code{errorVerbose}.
 -
  The parser class can be extended using the @code{%parse-param}
  directive. Each occurrence of the directive will add a @code{protected
  final} field to the parser class, and an argument to its constructor,
  which initialize them automatically.
  
 -Token names defined by @code{%token} and the predefined @code{EOF} token
 -name are added as constant fields to the parser class.
 -
  @deftypeop {Constructor} {YYParser} {} YYParser (@var{lex_param}, @dots{}, @var{parse_param}, @dots{})
  Build a new parser object with embedded @code{%code lexer}.  There are
 -no parameters, unless @code{%parse-param}s and/or @code{%lex-param}s are
 -used.
 +no parameters, unless @code{%param}s and/or @code{%parse-param}s and/or
 +@code{%lex-param}s are used.
 +
 +Use @code{%code init} for code added to the start of the constructor
 +body. This is especially useful to initialize superclasses. Use
 +@samp{%define init_throws} to specify any uncaught exceptions.
  @end deftypeop
  
  @deftypeop {Constructor} {YYParser} {} YYParser (Lexer @var{lexer}, @var{parse_param}, @dots{})
  Build a new parser object using the specified scanner.  There are no
 -additional parameters unless @code{%parse-param}s are used.
 +additional parameters unless @code{%param}s and/or @code{%parse-param}s are
 +used.
  
  If the scanner is defined by @code{%code lexer}, this constructor is
  declared @code{protected} and is called automatically with a scanner
 -created with the correct @code{%lex-param}s.
 +created with the correct @code{%param}s and/or @code{%lex-param}s.
 +
 +Use @code{%code init} for code added to the start of the constructor
 +body. This is especially useful to initialize superclasses. Use
 +@samp{%define init_throws} to specify any uncaught exceptions.
  @end deftypeop
  
  @deftypemethod {YYParser} {boolean} parse ()
@@@ -10760,21 -10151,6 +10761,21 @@@ Run the syntactic analysis, and return 
  @code{false} otherwise.
  @end deftypemethod
  
 +@deftypemethod {YYParser} {boolean} getErrorVerbose ()
 +@deftypemethodx {YYParser} {void} setErrorVerbose (boolean @var{verbose})
 +Get or set the option to produce verbose error messages.  These are only
 +available with @samp{%define parse.error verbose}, which also turns on
 +verbose error messages.
 +@end deftypemethod
 +
 +@deftypemethod {YYParser} {void} yyerror (String @var{msg})
 +@deftypemethodx {YYParser} {void} yyerror (Position @var{pos}, String @var{msg})
 +@deftypemethodx {YYParser} {void} yyerror (Location @var{loc}, String @var{msg})
 +Print an error message using the @code{yyerror} method of the scanner
 +instance in use. The @code{Location} and @code{Position} parameters are
 +available only if location tracking is active.
 +@end deftypemethod
 +
  @deftypemethod {YYParser} {boolean} recovering ()
  During the syntactic analysis, return @code{true} if recovering
  from a syntax error.
@@@ -10793,11 -10169,6 +10794,11 @@@ Get or set the tracing level.  Currentl
  or nonzero, full tracing.
  @end deftypemethod
  
 +@deftypecv {Constant} {YYParser} {String} {bisonVersion}
 +@deftypecvx {Constant} {YYParser} {String} {bisonSkeleton}
 +Identify the Bison version and skeleton used to generate this parser.
 +@end deftypecv
 +
  
  @node Java Scanner Interface
  @subsection Java Scanner Interface
  There are two possible ways to interface a Bison-generated Java parser
  with a scanner: the scanner may be defined by @code{%code lexer}, or
  defined elsewhere.  In either case, the scanner has to implement the
 -@code{Lexer} inner interface of the parser class.
 +@code{Lexer} inner interface of the parser class.  This interface also
 +contain constants for all user-defined token names and the predefined
 +@code{EOF} token.
  
  In the first case, the body of the scanner class is placed in
  @code{%code lexer} blocks.  If you want to pass parameters from the
@@@ -10829,7 -10198,7 +10830,7 @@@ In both cases, the scanner has to imple
  @deftypemethod {Lexer} {void} yyerror (Location @var{loc}, String @var{msg})
  This method is defined by the user to emit an error message.  The first
  parameter is omitted if location tracking is not active.  Its type can be
 -changed using @code{%define location_type "@var{class-name}".}
 +changed using @samp{%define location_type "@var{class-name}".}
  @end deftypemethod
  
  @deftypemethod {Lexer} {int} yylex ()
@@@ -10837,7 -10206,7 +10838,7 @@@ Return the next token.  Its type is th
  value and location are saved and returned by the their methods in the
  interface.
  
 -Use @code{%define lex_throws} to specify any uncaught exceptions.
 +Use @samp{%define lex_throws} to specify any uncaught exceptions.
  Default is @code{java.io.IOException}.
  @end deftypemethod
  
@@@ -10847,14 -10216,14 +10848,14 @@@ Return respectively the first position 
  @code{yylex} returned, and the first position beyond it.  These
  methods are not needed unless location tracking is active.
  
 -The return type can be changed using @code{%define position_type
 +The return type can be changed using @samp{%define position_type
  "@var{class-name}".}
  @end deftypemethod
  
  @deftypemethod {Lexer} {Object} getLVal ()
  Return the semantic value of the last token that yylex returned.
  
 -The return type can be changed using @code{%define stype
 +The return type can be changed using @samp{%define stype
  "@var{class-name}".}
  @end deftypemethod
  
  The following special constructs can be uses in Java actions.
  Other analogous C action features are currently unavailable for Java.
  
 -Use @code{%define throws} to specify any uncaught exceptions from parser
 +Use @samp{%define throws} to specify any uncaught exceptions from parser
  actions, and initial actions specified by @code{%initial-action}.
  
  @defvar $@var{n}
@@@ -10882,7 -10251,7 +10883,7 @@@ Like @code{$@var{n}} but specifies a al
  @defvar $$
  The semantic value for the grouping made by the current rule.  As a
  value, this is in the base type (@code{Object} or as specified by
 -@code{%define stype}) as in not cast to the declared subtype because
 +@samp{%define stype}) as in not cast to the declared subtype because
  casts are not allowed on the left-hand side of Java assignments.
  Use an explicit Java cast if the correct subtype is needed.
  @xref{Java Semantic Values}.
@@@ -10929,12 -10298,11 +10930,12 @@@ operation
  @xref{Error Recovery}.
  @end deftypefn
  
 -@deftypefn  {Function} {protected void} yyerror (String msg)
 -@deftypefnx {Function} {protected void} yyerror (Position pos, String msg)
 -@deftypefnx {Function} {protected void} yyerror (Location loc, String msg)
 +@deftypefn  {Function} {void} yyerror (String @var{msg})
 +@deftypefnx {Function} {void} yyerror (Position @var{loc}, String @var{msg})
 +@deftypefnx {Function} {void} yyerror (Location @var{loc}, String @var{msg})
  Print an error message using the @code{yyerror} method of the scanner
 -instance in use.
 +instance in use. The @code{Location} and @code{Position} parameters are
 +available only if location tracking is active.
  @end deftypefn
  
  
@@@ -10978,7 -10346,7 +10979,7 @@@ The prologue declarations have a differ
  @item @code{%code imports}
  blocks are placed at the beginning of the Java source code.  They may
  include copyright notices.  For a @code{package} declarations, it is
 -suggested to use @code{%define package} instead.
 +suggested to use @samp{%define package} instead.
  
  @item unqualified @code{%code}
  blocks are placed inside the parser class.
@@@ -11019,7 -10387,7 +11020,7 @@@ constructor that @emph{creates} a lexer
  
  @deffn {Directive} %name-prefix "@var{prefix}"
  The prefix of the parser class name @code{@var{prefix}Parser} if
 -@code{%define parser_class_name} is not used.  Default is @code{YY}.
 +@samp{%define parser_class_name} is not used.  Default is @code{YY}.
  @xref{Java Bison Interface}.
  @end deffn
  
@@@ -11050,11 -10418,6 +11051,11 @@@ Code inserted just after the @code{pack
  @xref{Java Differences}.
  @end deffn
  
 +@deffn {Directive} {%code init} @{ @var{code} @dots{} @}
 +Code inserted at the beginning of the parser constructor body.
 +@xref{Java Parser Interface}.
 +@end deffn
 +
  @deffn {Directive} {%code lexer} @{ @var{code} @dots{} @}
  Code added to the body of a inner lexer class within the parser class.
  @xref{Java Scanner Interface}.
@@@ -11067,7 -10430,7 +11068,7 @@@ Code (after the second @code{%%}) appen
  @end deffn
  
  @deffn {Directive} %@{ @var{code} @dots{} %@}
 -Not supported.  Use @code{%code import} instead.
 +Not supported.  Use @code{%code imports} instead.
  @xref{Java Differences}.
  @end deffn
  
@@@ -11076,11 -10439,6 +11077,11 @@@ Whether the parser class is declared @c
  @xref{Java Bison Interface}.
  @end deffn
  
 +@deffn {Directive} {%define annotations} "@var{annotations}"
 +The Java annotations for the parser class.  Default is none.
 +@xref{Java Bison Interface}.
 +@end deffn
 +
  @deffn {Directive} {%define extends} "@var{superclass}"
  The superclass of the parser class.  Default is none.
  @xref{Java Bison Interface}.
@@@ -11097,12 -10455,6 +11098,12 @@@ Default is none
  @xref{Java Bison Interface}.
  @end deffn
  
 +@deffn {Directive} {%define init_throws} "@var{exceptions}"
 +The exceptions thrown by @code{%code init} from the parser class
 +constructor.  Default is none.
 +@xref{Java Parser Interface}.
 +@end deffn
 +
  @deffn {Directive} {%define lex_throws} "@var{exceptions}"
  The exceptions thrown by the @code{yylex} method of the lexer, a
  comma-separated list.  Default is @code{java.io.IOException}.
@@@ -11620,19 -10972,6 +11621,19 @@@ the grammar file.  @xref{Grammar Outlin
  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
 +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
@@@ -11742,8 -11081,8 +11743,8 @@@ token is reset to the token that origin
  @end deffn
  
  @deffn {Directive} %error-verbose
 -Bison declaration to request verbose, specific error message strings
 -when @code{yyerror} is called.  @xref{Error Reporting}.
 +An obsolete directive standing for @samp{%define parse.error verbose}
 +(@pxref{Error Reporting, ,The Error Reporting Function @code{yyerror}}).
  @end deffn
  
  @deffn {Directive} %file-prefix "@var{prefix}"
@@@ -11766,12 -11105,12 +11767,12 @@@ Specify the programming language for th
  @end deffn
  
  @deffn {Directive} %left
 -Bison declaration to assign left associativity to token(s).
 +Bison declaration to assign precedence and left associativity to token(s).
  @xref{Precedence Decl, ,Operator Precedence}.
  @end deffn
  
 -@deffn {Directive} %lex-param @{@var{argument-declaration}@}
 -Bison declaration to specifying an additional parameter that
 +@deffn {Directive} %lex-param @{@var{argument-declaration}@} @dots{}
 +Bison declaration to specifying additional arguments that
  @code{yylex} should accept.  @xref{Pure Calling,, Calling Conventions
  for Pure Parsers}.
  @end deffn
@@@ -11816,7 -11155,7 +11817,7 @@@ parser implementation file.  @xref{Dec
  @end deffn
  
  @deffn {Directive} %nonassoc
 -Bison declaration to assign nonassociativity to token(s).
 +Bison declaration to assign precedence and nonassociativity to token(s).
  @xref{Precedence Decl, ,Operator Precedence}.
  @end deffn
  
@@@ -11825,15 -11164,10 +11826,15 @@@ Bison declaration to set the name of th
  @xref{Decl Summary}.
  @end deffn
  
 -@deffn {Directive} %parse-param @{@var{argument-declaration}@}
 -Bison declaration to specifying an additional parameter that
 -@code{yyparse} should accept.  @xref{Parser Function,, The Parser
 -Function @code{yyparse}}.
 +@deffn {Directive} %param @{@var{argument-declaration}@} @dots{}
 +Bison declaration to specify additional arguments that both
 +@code{yylex} and @code{yyparse} should accept.  @xref{Parser Function,, The
 +Parser Function @code{yyparse}}.
 +@end deffn
 +
 +@deffn {Directive} %parse-param @{@var{argument-declaration}@} @dots{}
 +Bison declaration to specify additional arguments that @code{yyparse}
 +should accept.  @xref{Parser Function,, The Parser Function @code{yyparse}}.
  @end deffn
  
  @deffn {Directive} %prec
@@@ -11841,13 -11175,8 +11842,13 @@@ Bison declaration to assign a precedenc
  @xref{Contextual Precedence, ,Context-Dependent Precedence}.
  @end deffn
  
 +@deffn {Directive} %precedence
 +Bison declaration to assign precedence to token(s), but no associativity
 +@xref{Precedence Decl, ,Operator Precedence}.
 +@end deffn
 +
  @deffn {Directive} %pure-parser
 -Deprecated version of @code{%define api.pure} (@pxref{%define
 +Deprecated version of @samp{%define api.pure} (@pxref{%define
  Summary,,api.pure}), for which Bison is more careful to warn about
  unreasonable usage.
  @end deffn
@@@ -11858,7 -11187,7 +11859,7 @@@ Require a Version of Bison}
  @end deffn
  
  @deffn {Directive} %right
 -Bison declaration to assign right associativity to token(s).
 +Bison declaration to assign precedence and right associativity to token(s).
  @xref{Precedence Decl, ,Operator Precedence}.
  @end deffn
  
@@@ -11963,16 -11292,17 +11964,16 @@@ instead
  
  @deffn {Function} yyerror
  User-supplied function to be called by @code{yyparse} on error.
 -@xref{Error Reporting, ,The Error
 -Reporting Function @code{yyerror}}.
 +@xref{Error Reporting, ,The Error Reporting Function @code{yyerror}}.
  @end deffn
  
  @deffn {Macro} YYERROR_VERBOSE
 -An obsolete macro that you define with @code{#define} in the prologue
 -to request verbose, specific error message strings
 -when @code{yyerror} is called.  It doesn't matter what definition you
 -use for @code{YYERROR_VERBOSE}, just whether you define it.
 -Supported by the C skeletons only; using
 -@code{%error-verbose} is preferred.  @xref{Error Reporting}.
 +An obsolete macro used in the @file{yacc.c} skeleton, that you define
 +with @code{#define} in the prologue to request verbose, specific error
 +message strings when @code{yyerror} is called.  It doesn't matter what
 +definition you use for @code{YYERROR_VERBOSE}, just whether you define
 +it.  Using @samp{%define parse.error verbose} is preferred
 +(@pxref{Error Reporting, ,The Error Reporting Function @code{yyerror}}).
  @end deffn
  
  @deffn {Macro} YYFPRINTF
@@@ -12375,8 -11705,8 +12376,8 @@@ London, Department of Computer Science
  @uref{http://www.cs.rhul.ac.uk/research/languages/publications/tomita_style_1.ps}
  @end table
  
- @node Index
- @unnumbered Index
+ @node Index of Terms
+ @unnumbered Index of Terms
  
  @printindex cp
  
diff --combined src/muscle-tab.c
index 47d9fb654421817b5cc6511c7f759aeff685303e,5c624982a9a7795cfd3dfb5b17aa53c5aa97f0fe..1168a9c33e5d7e6604d025c63be2977d49b24edd
@@@ -50,7 -50,7 +50,7 @@@ hash_compare_muscles (void const *x, vo
  {
    muscle_entry const *m1 = x;
    muscle_entry const *m2 = y;
 -  return strcmp (m1->key, m2->key) == 0;
 +  return STREQ (m1->key, m2->key);
  }
  
  static size_t
@@@ -80,7 -80,7 +80,7 @@@ muscle_init (void
    obstack_init (&muscle_obstack);
  
    muscle_table = hash_initialize (HT_INITIAL_CAPACITY, NULL, hash_muscle,
 -                                hash_compare_muscles, muscle_entry_free);
 +                                  hash_compare_muscles, muscle_entry_free);
  
    /* Version and input file.  */
    MUSCLE_INSERT_STRING ("version", VERSION);
@@@ -177,10 -177,10 +177,10 @@@ static voi
  muscle_syncline_grow (char const *key, location loc)
  {
    char *extension = NULL;
-   obstack_fgrow1 (&muscle_obstack, "]b4_syncline(%d, [[", loc.start.line);
-   MUSCLE_OBSTACK_SGROW (&muscle_obstack,
-                         quotearg_style (c_quoting_style, loc.start.file));
-   obstack_sgrow (&muscle_obstack, "]])[");
+   obstack_fgrow1 (&muscle_obstack, "]b4_syncline(%d, ", loc.start.line);
+   obstack_quote (&muscle_obstack,
+                  quotearg_style (c_quoting_style, loc.start.file));
+   obstack_sgrow (&muscle_obstack, ")[");
    obstack_1grow (&muscle_obstack, 0);
    extension = obstack_finish (&muscle_obstack);
    muscle_grow (key, extension, "");
@@@ -202,14 -202,14 +202,14 @@@ muscle_code_grow (const char *key, cons
  
  
  void muscle_pair_list_grow (const char *muscle,
 -                          const char *a1, const char *a2)
 +                            const char *a1, const char *a2)
  {
    char *pair;
-   obstack_sgrow (&muscle_obstack, "[[[");
-   MUSCLE_OBSTACK_SGROW (&muscle_obstack, a1);
-   obstack_sgrow (&muscle_obstack, "]], [[");
-   MUSCLE_OBSTACK_SGROW (&muscle_obstack, a2);
-   obstack_sgrow (&muscle_obstack, "]]]");
+   obstack_sgrow (&muscle_obstack, "[");
+   obstack_quote (&muscle_obstack, a1);
+   obstack_sgrow (&muscle_obstack, "");
+   obstack_quote (&muscle_obstack, a2);
+   obstack_sgrow (&muscle_obstack, "]");
    obstack_1grow (&muscle_obstack, 0);
    pair = obstack_finish (&muscle_obstack);
    muscle_grow (muscle, pair, ",\n");
@@@ -259,53 -259,61 +259,61 @@@ muscle_find (char const *key
  }
  
  
- void
+ /* In the format `file_name:line.column', append BOUND to MUSCLE.  Use
+    digraphs for special characters in the file name.  */
+ static void
  muscle_boundary_grow (char const *key, boundary bound)
  {
    char *extension;
-   MUSCLE_OBSTACK_SGROW (&muscle_obstack, bound.file);
+   obstack_sgrow  (&muscle_obstack, "[[");
+   obstack_escape (&muscle_obstack, bound.file);
 -  obstack_1grow  (&muscle_obstack, ':');
 +  obstack_1grow (&muscle_obstack, ':');
    obstack_fgrow1 (&muscle_obstack, "%d", bound.line);
 -  obstack_1grow  (&muscle_obstack, '.');
 +  obstack_1grow (&muscle_obstack, '.');
    obstack_fgrow1 (&muscle_obstack, "%d", bound.column);
 -  obstack_1grow  (&muscle_obstack, '\0');
+   obstack_sgrow  (&muscle_obstack, "]]");
 +  obstack_1grow (&muscle_obstack, '\0');
    extension = obstack_finish (&muscle_obstack);
    muscle_grow (key, extension, "");
    obstack_free (&muscle_obstack, extension);
  }
  
- void
+ /* In the format `[[file_name:line.column]], [[file_name:line.column]]',
+    append LOC to MUSCLE.  Use digraphs for special characters in each
+    file name.  */
+ static void
  muscle_location_grow (char const *key, location loc)
  {
-   muscle_grow (key, "[[", "");
    muscle_boundary_grow (key, loc.start);
-   muscle_grow (key, "]], [[", "");
+   muscle_grow (key, "", ", ");
    muscle_boundary_grow (key, loc.end);
-   muscle_grow (key, "]]", "");
  }
  
- #define MUSCLE_COMMON_DECODE(Value)                                           \
-   case '$':                                                                   \
-     aver (*++(Value) == ']');                                                 \
-     aver (*++(Value) == '[');                                                 \
-     obstack_sgrow (&muscle_obstack, "$");                                     \
-     break;                                                                    \
-   case '@':                                                                   \
-     switch (*++(Value))                                                       \
-       {                                                                       \
-         case '@': obstack_sgrow (&muscle_obstack, "@" ); break;               \
-         case '{': obstack_sgrow (&muscle_obstack, "[" ); break;               \
-         case '}': obstack_sgrow (&muscle_obstack, "]" ); break;               \
-         default: aver (false); break;                                         \
-       }                                                                       \
-     break;                                                                    \
-   default:                                                                    \
-     obstack_1grow (&muscle_obstack, *(Value));                                \
+ #define COMMON_DECODE(Value)                                    \
+   case '$':                                                     \
+     aver (*++(Value) == ']');                                   \
+     aver (*++(Value) == '[');                                   \
+     obstack_sgrow (&muscle_obstack, "$");                       \
+     break;                                                      \
+   case '@':                                                     \
+     switch (*++(Value))                                         \
+       {                                                         \
+         case '@': obstack_sgrow (&muscle_obstack, "@" ); break; \
+         case '{': obstack_sgrow (&muscle_obstack, "[" ); break; \
+         case '}': obstack_sgrow (&muscle_obstack, "]" ); break; \
+         default: aver (false); break;                           \
+       }                                                         \
+     break;                                                      \
+   default:                                                      \
+     obstack_1grow (&muscle_obstack, *(Value));                  \
      break;
  
- /* Reverse of MUSCLE_OBSTACK_SGROW.  */
+ /* Reverse of obstack_escape.  */
  static char *
muscle_string_decode (char const *key)
+ string_decode (char const *key)
  {
    char const *value;
    char *value_decoded;
    do {
      switch (*value)
        {
-         MUSCLE_COMMON_DECODE (value)
+         COMMON_DECODE (value)
          case '[':
          case ']':
            aver (false);
  
  /* Reverse of muscle_location_grow.  */
  static location
muscle_location_decode (char const *key)
+ location_decode (char const *key)
  {
    location loc;
    char const *value = muscle_find_const (key);
    while (*++value)
      switch (*value)
        {
-         MUSCLE_COMMON_DECODE (value)
+         COMMON_DECODE (value)
          case '[':
            aver (false);
            break;
@@@ -388,42 -396,25 +396,42 @@@ muscle_user_name_list_grow (char const 
    muscle_grow (key, "]]", "");
  }
  
 +/** If the \a variable name is obsolete, return the name to use,
 + * otherwise \a variable. */
 +static
 +char const *
 +muscle_percent_variable_update (char const *variable)
 +{
 +  typedef struct
 +  {
 +    const char *obsolete;
 +    const char *updated;
 +  } conversion_type;
 +  const conversion_type conversion[] =
 +    {
 +      { "api.push_pull", "api.push-pull", },
 +      { "lr.keep_unreachable_states", "lr.keep-unreachable-states", },
 +      { "namespace", "api.namespace", },
 +    };
 +  int i;
 +  for (i = 0; i < sizeof conversion / sizeof *conversion; ++i)
 +    if (STREQ (conversion[i].obsolete, variable))
 +      return conversion[i].updated;
 +  return variable;
 +}
 +
  void
  muscle_percent_define_insert (char const *variable, location variable_loc,
                                char const *value,
                                muscle_percent_define_how how)
  {
 -  char *variable_tr = NULL;
    char const *name;
    char const *loc_name;
    char const *syncline_name;
    char const *how_name;
  
    /* Permit certain names with underscores for backward compatibility.  */
 -  if (0 == strcmp (variable, "api.push_pull")
 -      || 0 == strcmp (variable, "lr.keep_unreachable_states"))
 -    {
 -      variable_tr = strdup (variable);
 -      tr (variable_tr, '_', '-');
 -      variable = variable_tr;
 -    }
 +  variable = muscle_percent_variable_update (variable);
  
    name = UNIQSTR_CONCAT ("percent_define(", variable, ")");
    loc_name = UNIQSTR_CONCAT ("percent_define_loc(", variable, ")");
        muscle_percent_define_how how_old =
          atoi (muscle_find_const (how_name));
        if (how_old == MUSCLE_PERCENT_DEFINE_F)
 -        {
 -          free (variable_tr);
 -          return;
 -        }
 -      complain_at (variable_loc, _("%%define variable %s redefined"),
 +        return;
 +      complain_at (variable_loc, complaint, _("%%define variable %s redefined"),
                     quote (variable));
 -      complain_at (muscle_percent_define_get_loc (variable),
 -                   _("previous definition"));
 +      location loc = muscle_percent_define_get_loc (variable);
 +      complain_at (loc, complaint, _("previous definition"));
      }
  
    MUSCLE_INSERT_STRING (name, value);
    muscle_user_name_list_grow ("percent_define_user_variables", variable,
                                variable_loc);
    MUSCLE_INSERT_INT (how_name, how);
 +}
 +
 +/* This is used for backward compatibility, e.g., "%define api.pure"
 +   supersedes "%pure-parser".  */
 +void
 +muscle_percent_define_ensure (char const *variable, location loc,
 +                              bool value)
 +{
 +  char const *val = value ? "" : "false";
 +  char const *name;
 +  name = UNIQSTR_CONCAT ("percent_define(", variable, ")");
  
 -  free (variable_tr);
 +  /* %pure-parser is deprecated in favor of `%define api.pure', so use
 +     `%define api.pure' in a backward-compatible manner here.  First,
 +     don't complain if %pure-parser is specified multiple times.  */
 +  if (!muscle_find_const (name))
 +    muscle_percent_define_insert (variable, loc, val,
 +                                  MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE);
 +  /* In all cases, use api.pure now so that the backend doesn't complain if
 +     the skeleton ignores api.pure, but do warn now if there's a previous
 +     conflicting definition from an actual %define.  */
 +  if (muscle_percent_define_flag_if (variable) != value)
 +    muscle_percent_define_insert (variable, loc, val,
 +                                  MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE);
  }
  
  char *
@@@ -491,7 -463,7 +499,7 @@@ muscle_percent_define_get (char const *
                                 variable, ")");
  
    muscle_insert (usage_name, "");
-   value = muscle_string_decode (name);
+   value = string_decode (name);
    if (!value)
      value = xstrdup ("");
    return value;
@@@ -503,9 -475,9 +511,9 @@@ muscle_percent_define_get_loc (char con
    char const *loc_name;
    loc_name = UNIQSTR_CONCAT ("percent_define_loc(", variable, ")");
    if (!muscle_find_const (loc_name))
 -    fatal(_("%s: undefined %%define variable %s"),
 +    complain (fatal, _("%s: undefined %%define variable %s"),
            "muscle_percent_define_get_loc", quote (variable));
-   return muscle_location_decode (loc_name);
+   return location_decode (loc_name);
  }
  
  char const *
@@@ -517,7 -489,7 +525,7 @@@ muscle_percent_define_get_syncline (cha
      UNIQSTR_CONCAT ("percent_define_syncline(", variable, ")");
    syncline = muscle_find_const (syncline_name);
    if (!syncline)
 -    fatal(_("%s: undefined %%define variable %s"),
 +    complain (fatal, _("%s: undefined %%define variable %s"),
            "muscle_percent_define_get_syncline", quote (variable));
    return syncline;
  }
@@@ -555,23 -527,22 +563,23 @@@ muscle_percent_define_flag_if (char con
    if (muscle_percent_define_ifdef (variable))
      {
        char *value = muscle_percent_define_get (variable);
 -      if (value[0] == '\0' || 0 == strcmp (value, "true"))
 +      if (value[0] == '\0' || STREQ (value, "true"))
          result = true;
 -      else if (0 == strcmp (value, "false"))
 +      else if (STREQ (value, "false"))
          result = false;
        else if (!muscle_find_const (invalid_boolean_name))
          {
            muscle_insert (invalid_boolean_name, "");
 -          complain_at(muscle_percent_define_get_loc (variable),
 -                      _("invalid value for %%define Boolean variable %s"),
 -                      quote (variable));
 +          location loc = muscle_percent_define_get_loc (variable);
 +          complain_at (loc, complaint,
 +                       _("invalid value for %%define Boolean variable %s"),
 +                       quote (variable));
          }
        free (value);
      }
    else
 -    fatal(_("%s: undefined %%define variable %s"),
 -          "muscle_percent_define_flag", quote (variable));
 +    complain (fatal, _("%s: undefined %%define variable %s"),
 +              "muscle_percent_define_flag", quote (variable));
  
    return result;
  }
@@@ -610,23 -581,22 +618,23 @@@ muscle_percent_define_check_values (cha
  
        name = UNIQSTR_CONCAT ("percent_define(", *variablep, ")");
  
-       value = muscle_string_decode (name);
+       value = string_decode (name);
        if (value)
          {
            for (++values; *values; ++values)
              {
 -              if (0 == strcmp (value, *values))
 +              if (STREQ (value, *values))
                  break;
              }
            if (!*values)
              {
                location loc = muscle_percent_define_get_loc (*variablep);
 -              complain_at(loc,
 -                          _("invalid value for %%define variable %s: %s"),
 -                          quote (*variablep), quote_n (1, value));
 +              complain_at (loc, complaint,
 +                           _("invalid value for %%define variable %s: %s"),
 +                           quote (*variablep), quote_n (1, value));
                for (values = variablep + 1; *values; ++values)
 -                complain_at (loc, _("accepted value: %s"), quote (*values));
 +                complain_at (loc, complaint, _("accepted value: %s"),
 +                             quote (*values));
              }
            else
              {
            free (value);
          }
        else
 -        fatal (_("%s: undefined %%define variable %s"),
 -               "muscle_percent_define_check_values", quote (*variablep));
 +        complain (fatal, _("%s: undefined %%define variable %s"),
 +                  "muscle_percent_define_check_values", quote (*variablep));
      }
  }
  
diff --combined src/muscle-tab.h
index 5f701ae41a242aaee5dc7fb840d12a178230db2d,ddbad4085572477af12b7477295c01ca829c2e89..1f33f8c15a9bf1fc67750a654bd93dccdce825e5
@@@ -1,6 -1,7 +1,6 @@@
  /* Muscle table manager for Bison,
  
 -   Copyright (C) 2001-2003, 2006-2007, 2009-2012 Free Software
 -   Foundation, Inc.
 +   Copyright (C) 2001-2003, 2006-2012 Free Software Foundation, Inc.
  
     This file is part of Bison, the GNU Compiler Compiler.
  
@@@ -35,63 -36,46 +35,48 @@@ void muscle_free (void)
  extern struct obstack muscle_obstack;
  
  #define MUSCLE_INSERT_BOOL(Key, Value)                          \
- do {                                                            \
-   int v__ = Value;                                              \
-   MUSCLE_INSERT_INT (Key, v__);                                 \
- } while(0)
+   do {                                                          \
 -    int v = Value;                                              \
 -    MUSCLE_INSERT_INT (Key, v);                                 \
++    int v__ = Value;                                            \
++    MUSCLE_INSERT_INT (Key, v__);                               \
+   } while (0)
  
  #define MUSCLE_INSERT_INT(Key, Value)                           \
do {                                                            \
-   obstack_fgrow1 (&muscle_obstack, "%d", Value);                \
-   obstack_1grow (&muscle_obstack, 0);                           \
-   muscle_insert (Key, obstack_finish (&muscle_obstack));        \
} while(0)
  do {                                                          \
+     obstack_fgrow1 (&muscle_obstack, "%d", Value);              \
+     obstack_1grow (&muscle_obstack, 0);                         \
+     muscle_insert (Key, obstack_finish (&muscle_obstack));      \
  } while (0)
  
  #define MUSCLE_INSERT_LONG_INT(Key, Value)                      \
do {                                                            \
-   obstack_fgrow1 (&muscle_obstack, "%ld", Value);               \
-   obstack_1grow (&muscle_obstack, 0);                           \
-   muscle_insert (Key, obstack_finish (&muscle_obstack));        \
} while(0)
  do {                                                          \
+     obstack_fgrow1 (&muscle_obstack, "%ld", Value);             \
+     obstack_1grow (&muscle_obstack, 0);                         \
+     muscle_insert (Key, obstack_finish (&muscle_obstack));      \
  } while (0)
  
 +/* Key -> Value, but don't apply escaping to Value. */
  #define MUSCLE_INSERT_STRING_RAW(Key, Value)                    \
do {                                                            \
-   obstack_sgrow (&muscle_obstack, Value);                       \
-   obstack_1grow (&muscle_obstack, 0);                           \
-   muscle_insert (Key, obstack_finish (&muscle_obstack));        \
} while(0)
  do {                                                          \
+     obstack_sgrow (&muscle_obstack, Value);                     \
+     obstack_1grow (&muscle_obstack, 0);                         \
+     muscle_insert (Key, obstack_finish (&muscle_obstack));      \
  } while (0)
  
 +/* Key -> Value, applying M4 escaping to Value. */
  #define MUSCLE_INSERT_STRING(Key, Value)                        \
- do {                                                            \
-   MUSCLE_OBSTACK_SGROW (&muscle_obstack, Value);                \
-   obstack_1grow (&muscle_obstack, 0);                           \
-   muscle_insert (Key, obstack_finish (&muscle_obstack));        \
- } while(0)
- #define MUSCLE_OBSTACK_SGROW(Obstack, Value)            \
- do {                                                    \
-   char const *p__;                                      \
-   for (p__ = Value; *p__; p__++)                        \
-     switch (*p__)                                       \
-       {                                                 \
-       case '$': obstack_sgrow (Obstack, "$]["); break;  \
-       case '@': obstack_sgrow (Obstack, "@@" ); break;  \
-       case '[': obstack_sgrow (Obstack, "@{" ); break;  \
-       case ']': obstack_sgrow (Obstack, "@}" ); break;  \
-       default: obstack_1grow (Obstack, *p__); break;    \
-       }                                                 \
- } while(0)
+   do {                                                          \
+     obstack_escape (&muscle_obstack, Value);                    \
+     obstack_1grow (&muscle_obstack, 0);                         \
+     muscle_insert (Key, obstack_finish (&muscle_obstack));      \
+   } while (0)
  
  #define MUSCLE_INSERT_C_STRING(Key, Value)                      \
- do {                                                            \
-   MUSCLE_OBSTACK_SGROW (&muscle_obstack,                        \
-                         quotearg_style (c_quoting_style,        \
-                                         Value));                \
-   obstack_1grow (&muscle_obstack, 0);                           \
-   muscle_insert (Key, obstack_finish (&muscle_obstack));        \
- } while(0)
+   do {                                                          \
+     obstack_escape (&muscle_obstack,                            \
+                     quotearg_style (c_quoting_style, Value));   \
+     obstack_1grow (&muscle_obstack, 0);                         \
+     muscle_insert (Key, obstack_finish (&muscle_obstack));      \
+   } while (0)
  
  /* Append VALUE to the current value of KEY.  If KEY did not already
     exist, create it.  Use MUSCLE_OBSTACK.  De-allocate the previously
@@@ -113,14 -97,6 +98,6 @@@ void muscle_code_grow (const char *key
  void muscle_pair_list_grow (const char *muscle,
                              const char *a1, const char *a2);
  
- /* In the format `[[file_name:line.column]], [[file_name:line.column]]', append
-    LOC to MUSCLE.  Use digraphs for special characters in each file name.  */
- void muscle_location_grow (char const *key, location loc);
- /* In the format `file_name:line.column', append BOUND to MUSCLE.  Use digraphs
-    for special characters in the file name.  */
- void muscle_boundary_grow (char const *key, boundary bound);
  /* Grow KEY for the occurrence of the name USER_NAME at LOC appropriately for
     use with b4_check_user_names in ../data/bison.m4.  USER_NAME is not escaped
     with digraphs, so it must not contain `[' or `]'.  */
@@@ -147,13 -123,6 +124,13 @@@ void muscle_percent_define_insert (cha
                                     char const *value,
                                     muscle_percent_define_how how);
  
 +/* Make sure that VARIABLE is set to the boolean VALUE.  Warn on mismatches
 +   only, but accept repeated declaration.  Used for backward compatibility
 +   between old directives such as %pure-parser, and the recommended use of
 +   variables (%define api.pure).   */
 +void muscle_percent_define_ensure (char const *variable, location variable_loc,
 +                                   bool value);
 +
  /* Mimic b4_percent_define_get in ../data/bison.m4 exactly.  That is, if the
     %define variable VARIABLE is defined, return its value.  Otherwise, return
     the empty string.  Also, record Bison's usage of VARIABLE by defining
diff --combined src/output.c
index 26a6e7fe6c2fd06c83c9b3f256724d37bcbcd79e,d52a711393cf960b73c0a55ad8f69d752d699096..c227be223f4c89749696305e8aebc7f5ed3365d9
@@@ -21,9 -21,8 +21,9 @@@
  #include <config.h>
  #include "system.h"
  
 +#include <concat-filename.h>
  #include <configmake.h>
 -#include <error.h>
 +#include <filename.h>
  #include <get-errno.h>
  #include <quotearg.h>
  #include <spawn-pipe.h>
@@@ -42,6 -41,8 +42,6 @@@
  #include "symtab.h"
  #include "tables.h"
  
 -# define ARRAY_CARDINALITY(Array) (sizeof (Array) / sizeof *(Array))
 -
  static struct obstack format_obstack;
  
  
  `-------------------------------------------------------------------*/
  
  
 -#define GENERATE_MUSCLE_INSERT_TABLE(Name, Type)                      \
 -                                                                      \
 -static void                                                           \
 -Name (char const *name,                                                       \
 -      Type *table_data,                                                       \
 -      Type first,                                                     \
 -      int begin,                                                      \
 -      int end)                                                                \
 -{                                                                     \
 -  Type min = first;                                                   \
 -  Type max = first;                                                   \
 -  long int lmin;                                                      \
 -  long int lmax;                                                      \
 -  int i;                                                              \
 -  int j = 1;                                                          \
 -                                                                      \
 -  obstack_fgrow1 (&format_obstack, "%6d", first);                     \
 -  for (i = begin; i < end; ++i)                                               \
 -    {                                                                 \
 -      obstack_1grow (&format_obstack, ',');                           \
 -      if (j >= 10)                                                    \
 -      {                                                               \
 -        obstack_sgrow (&format_obstack, "\n  ");                      \
 -        j = 1;                                                        \
 -      }                                                               \
 -      else                                                            \
 -      ++j;                                                            \
 -      obstack_fgrow1 (&format_obstack, "%6d", table_data[i]);         \
 -      if (table_data[i] < min)                                                \
 -      min = table_data[i];                                            \
 -      if (max < table_data[i])                                                \
 -      max = table_data[i];                                            \
 -    }                                                                 \
 -  obstack_1grow (&format_obstack, 0);                                 \
 -  muscle_insert (name, obstack_finish (&format_obstack));             \
 -                                                                      \
 -  lmin = min;                                                         \
 -  lmax = max;                                                         \
 -  /* Build `NAME_min' and `NAME_max' in the obstack. */                       \
 -  obstack_fgrow1 (&format_obstack, "%s_min", name);                   \
 -  obstack_1grow (&format_obstack, 0);                                 \
 -  MUSCLE_INSERT_LONG_INT (obstack_finish (&format_obstack), lmin);    \
 -  obstack_fgrow1 (&format_obstack, "%s_max", name);                   \
 -  obstack_1grow (&format_obstack, 0);                                 \
 -  MUSCLE_INSERT_LONG_INT (obstack_finish (&format_obstack), lmax);    \
 +#define GENERATE_MUSCLE_INSERT_TABLE(Name, Type)                        \
 +                                                                        \
 +static void                                                             \
 +Name (char const *name,                                                 \
 +      Type *table_data,                                                 \
 +      Type first,                                                       \
 +      int begin,                                                        \
 +      int end)                                                          \
 +{                                                                       \
 +  Type min = first;                                                     \
 +  Type max = first;                                                     \
 +  long int lmin;                                                        \
 +  long int lmax;                                                        \
 +  int i;                                                                \
 +  int j = 1;                                                            \
 +                                                                        \
 +  obstack_fgrow1 (&format_obstack, "%6d", first);                       \
 +  for (i = begin; i < end; ++i)                                         \
 +    {                                                                   \
 +      obstack_1grow (&format_obstack, ',');                             \
 +      if (j >= 10)                                                      \
 +        {                                                               \
 +          obstack_sgrow (&format_obstack, "\n  ");                      \
 +          j = 1;                                                        \
 +        }                                                               \
 +      else                                                              \
 +        ++j;                                                            \
 +      obstack_fgrow1 (&format_obstack, "%6d", table_data[i]);           \
 +      if (table_data[i] < min)                                          \
 +        min = table_data[i];                                            \
 +      if (max < table_data[i])                                          \
 +        max = table_data[i];                                            \
 +    }                                                                   \
 +  obstack_1grow (&format_obstack, 0);                                   \
 +  muscle_insert (name, obstack_finish (&format_obstack));               \
 +                                                                        \
 +  lmin = min;                                                           \
 +  lmax = max;                                                           \
 +  /* Build `NAME_min' and `NAME_max' in the obstack. */                 \
 +  obstack_fgrow1 (&format_obstack, "%s_min", name);                     \
 +  obstack_1grow (&format_obstack, 0);                                   \
 +  MUSCLE_INSERT_LONG_INT (obstack_finish (&format_obstack), lmin);      \
 +  obstack_fgrow1 (&format_obstack, "%s_max", name);                     \
 +  obstack_1grow (&format_obstack, 0);                                   \
 +  MUSCLE_INSERT_LONG_INT (obstack_finish (&format_obstack), lmax);      \
  }
  
  GENERATE_MUSCLE_INSERT_TABLE(muscle_insert_unsigned_int_table, unsigned int)
@@@ -105,32 -106,43 +105,42 @@@ GENERATE_MUSCLE_INSERT_TABLE(muscle_ins
  GENERATE_MUSCLE_INSERT_TABLE(muscle_insert_base_table, base_number)
  GENERATE_MUSCLE_INSERT_TABLE(muscle_insert_rule_number_table, rule_number)
  GENERATE_MUSCLE_INSERT_TABLE(muscle_insert_symbol_number_table, symbol_number)
 -GENERATE_MUSCLE_INSERT_TABLE(muscle_insert_item_number_table, item_number)
  GENERATE_MUSCLE_INSERT_TABLE(muscle_insert_state_number_table, state_number)
  
  
- /*--------------------------------------------------------------------.
- | Print to OUT a representation of STRING escaped both for C and M4.  |
- `--------------------------------------------------------------------*/
+ /*----------------------------------------------------------------.
+ | Print to OUT a representation of CP quoted and escaped for M4.  |
+ `----------------------------------------------------------------*/
  
  static void
escaped_output (FILE *out, char const *string)
quoted_output (FILE *out, char const *cp)
  {
-   char const *p;
    fprintf (out, "[[");
  
-   for (p = quotearg_style (c_quoting_style, string); *p; p++)
-     switch (*p)
+   for (; *cp; cp++)
+     switch (*cp)
        {
        case '$': fputs ("$][", out); break;
        case '@': fputs ("@@",  out); break;
        case '[': fputs ("@{",  out); break;
        case ']': fputs ("@}",  out); break;
-       default: fputc (*p, out); break;
+       default:  fputc (*cp,   out); break;
        }
  
    fprintf (out, "]]");
  }
  
+ /*----------------------------------------------------------------.
+ | Print to OUT a representation of STRING quoted and escaped both |
+ | for C and M4.                                                   |
+ `----------------------------------------------------------------*/
+ static void
+ string_output (FILE *out, char const *string)
+ {
+   quoted_output (out, quotearg_style (c_quoting_style, string));
+ }
  
  /*------------------------------------------------------------------.
  | Prepare the muscles related to the symbols: translate, tname, and |
@@@ -142,14 -154,13 +152,14 @@@ prepare_symbols (void
  {
    MUSCLE_INSERT_INT ("tokens_number", ntokens);
    MUSCLE_INSERT_INT ("nterms_number", nvars);
 +  MUSCLE_INSERT_INT ("symbols_number", nsyms);
    MUSCLE_INSERT_INT ("undef_token_number", undeftoken->number);
    MUSCLE_INSERT_INT ("user_token_number_max", max_user_token_number);
  
    muscle_insert_symbol_number_table ("translate",
 -                                   token_translations,
 -                                   token_translations[0],
 -                                   1, max_user_token_number + 1);
 +                                     token_translations,
 +                                     token_translations[0],
 +                                     1, max_user_token_number + 1);
  
    /* tname -- token names.  */
    {
      set_quoting_flags (qo, QA_SPLIT_TRIGRAPHS);
      for (i = 0; i < nsyms; i++)
        {
 -      char *cp = quotearg_alloc (symbols[i]->tag, -1, qo);
 -      /* Width of the next token, including the two quotes, the
 -         comma and the space.  */
 -      int width = strlen (cp) + 2;
 -
 -      if (j + width > 75)
 -        {
 -          obstack_sgrow (&format_obstack, "\n ");
 -          j = 1;
 -        }
 -
 -      if (i)
 -        obstack_1grow (&format_obstack, ' ');
 -      obstack_escape (&format_obstack, cp);
 +        char *cp = quotearg_alloc (symbols[i]->tag, -1, qo);
 +        /* Width of the next token, including the two quotes, the
 +           comma and the space.  */
 +        int width = strlen (cp) + 2;
 +
 +        if (j + width > 75)
 +          {
 +            obstack_sgrow (&format_obstack, "\n ");
 +            j = 1;
 +          }
 +
 +        if (i)
 +          obstack_1grow (&format_obstack, ' ');
-         MUSCLE_OBSTACK_SGROW (&format_obstack, cp);
++        obstack_escape (&format_obstack, cp);
          free (cp);
 -      obstack_1grow (&format_obstack, ',');
 -      j += width;
 +        obstack_1grow (&format_obstack, ',');
 +        j += width;
        }
      free (qo);
      obstack_sgrow (&format_obstack, " ]b4_null[");
      for (i = 0; i < ntokens; ++i)
        values[i] = symbols[i]->user_token_number;
      muscle_insert_int_table ("toknum", values,
 -                           values[0], 1, ntokens);
 +                             values[0], 1, ntokens);
      free (values);
    }
  }
  
  
 -/*-------------------------------------------------------------.
 -| Prepare the muscles related to the rules: rhs, prhs, r1, r2, |
 -| rline, dprec, merger.                                        |
 -`-------------------------------------------------------------*/
 +/*----------------------------------------------------------------.
 +| Prepare the muscles related to the rules: r1, r2, rline, dprec, |
 +| merger, immediate.                                              |
 +`----------------------------------------------------------------*/
  
  static void
  prepare_rules (void)
  {
 -  rule_number r;
 -  unsigned int i = 0;
 -  item_number *rhs = xnmalloc (nritems, sizeof *rhs);
 -  unsigned int *prhs = xnmalloc (nrules, sizeof *prhs);
    unsigned int *rline = xnmalloc (nrules, sizeof *rline);
    symbol_number *r1 = xnmalloc (nrules, sizeof *r1);
    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)
      {
 -      item_number *rhsp = NULL;
 -      /* Index of rule R in RHS. */
 -      prhs[r] = i;
 -      /* RHS of the rule R. */
 -      for (rhsp = rules[r].rhs; *rhsp >= 0; ++rhsp)
 -      rhs[i++] = *rhsp;
        /* LHS of the rule R. */
        r1[r] = rules[r].lhs->number;
        /* Length of rule R's RHS. */
 -      r2[r] = i - prhs[r];
 -      /* Separator in RHS. */
 -      rhs[i++] = -1;
 +      r2[r] = rule_rhs_length(&rules[r]);
        /* Line where rule was defined. */
        rline[r] = rules[r].location.start.line;
        /* Dynamic precedence (GLR).  */
        dprec[r] = rules[r].dprec;
        /* Merger-function index (GLR).  */
        merger[r] = rules[r].merger;
 +      /* Immediate reduction flags (GLR).  */
 +      immediate[r] = rules[r].is_predicate;
      }
 -  aver (i == nritems);
  
 -  muscle_insert_item_number_table ("rhs", rhs, ritem[0], 1, nritems);
 -  muscle_insert_unsigned_int_table ("prhs", prhs, 0, 0, nrules);
    muscle_insert_unsigned_int_table ("rline", rline, 0, 0, nrules);
    muscle_insert_symbol_number_table ("r1", r1, 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);
  
 -  free (rhs);
 -  free (prhs);
    free (rline);
    free (r1);
    free (r2);
    free (dprec);
    free (merger);
 +  free (immediate);
  }
  
  /*--------------------------------------------.
@@@ -262,7 -284,7 +272,7 @@@ prepare_states (void
    for (i = 0; i < nstates; ++i)
      values[i] = states[i]->accessing_symbol;
    muscle_insert_symbol_number_table ("stos", values,
 -                                   0, 1, nstates);
 +                                     0, 1, nstates);
    free (values);
  
    MUSCLE_INSERT_INT ("last", high);
  }
  
  
 +/*-------------------------------------------------------.
 +| Compare two symbols by type-name, and then by number.  |
 +`-------------------------------------------------------*/
 +
 +static int
 +symbol_type_name_cmp (const symbol **lhs, const symbol **rhs)
 +{
 +  int res = UNIQSTR_CMP((*lhs)->type_name, (*rhs)->type_name);
 +  if (res)
 +    return res;
 +  return (*lhs)->number - (*rhs)->number;
 +}
 +
 +
 +/*----------------------------------------------------------------.
 +| Return a (malloc'ed) table of the symbols sorted by type-name.  |
 +`----------------------------------------------------------------*/
 +
 +static symbol **
 +symbols_by_type_name (void)
 +{
 +  typedef int (*qcmp_type) (const void *, const void *);
 +  symbol **res = xmemdup (symbols, nsyms * sizeof *res);
 +  qsort (res, nsyms, sizeof *res, (qcmp_type) &symbol_type_name_cmp);
 +  return res;
 +}
 +
 +
 +/*------------------------------------------------------------------.
 +| Define b4_type_names, which is a list of (lists of the numbers of |
 +| symbols with same type-name).                                     |
 +`------------------------------------------------------------------*/
 +
 +static void
 +type_names_output (FILE *out)
 +{
 +  int i;
 +  symbol **syms = symbols_by_type_name ();
 +  fputs ("m4_define([b4_type_names],\n[", out);
 +  for (i = 0; i < nsyms; /* nothing */)
 +    {
 +      // The index of the first symbol of the current type-name.
 +      int i0 = i;
 +      fputs (i ? ",\n[" : "[", out);
 +      for (; i < nsyms && syms[i]->type_name == syms[i0]->type_name; ++i)
 +        fprintf (out, "%s%d", i != i0 ? ", " : "", syms[i]->number);
 +      fputs ("]", out);
 +    }
 +  fputs ("])\n\n", out);
 +  free (syms);
 +}
 +
 +
 +/*-------------------------------------.
 +| The list of all the symbol numbers.  |
 +`-------------------------------------*/
 +
 +static void
 +symbol_numbers_output (FILE *out)
 +{
 +  int i;
 +  fputs ("m4_define([b4_symbol_numbers],\n[", out);
 +  for (i = 0; i < nsyms; ++i)
 +    fprintf (out, "%s[%d]", i ? ", " : "", i);
 +  fputs ("])\n\n", out);
 +}
 +
  
  /*---------------------------------.
  | Output the user actions to OUT.  |
@@@ -352,18 -307,17 +362,18 @@@ user_actions_output (FILE *out
    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);
 -      string_output (out, rules[r].action_location.start.file);
 -      fprintf (out, ")\n[    %s]])\n\n", rules[r].action);
 +        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);
++        string_output (out, rules[r].action_location.start.file);
 +        fprintf (out, ")\n[    %s]])\n\n", rules[r].action);
        }
    fputs ("])\n\n", out);
  }
  
 -/*--------------------------------------.
 -| Output the merge functions to OUT.   |
 -`--------------------------------------*/
 +/*------------------------------------.
 +| Output the merge functions to OUT.  |
 +`------------------------------------*/
  
  static void
  merger_output (FILE *out)
    for (n = 1, p = merge_functions; p != NULL; n += 1, p = p->next)
      {
        if (p->type[0] == '\0')
 -      fprintf (out, "  case %d: *yy0 = %s (*yy0, *yy1); break;\n",
 -               n, p->name);
 +        fprintf (out, "  case %d: *yy0 = %s (*yy0, *yy1); break;\n",
 +                 n, p->name);
        else
 -      fprintf (out, "  case %d: yy0->%s = %s (*yy0, *yy1); break;\n",
 -               n, p->type, p->name);
 +        fprintf (out, "  case %d: yy0->%s = %s (*yy0, *yy1); break;\n",
 +                 n, p->type, p->name);
      }
    fputs ("]])\n\n", out);
  }
  
 -/*--------------------------------------.
 -| Output the tokens definition to OUT.  |
 -`--------------------------------------*/
 +
 +/*---------------------------------------------.
 +| Prepare the muscles for symbol definitions.  |
 +`---------------------------------------------*/
  
  static void
 -token_definitions_output (FILE *out)
 +prepare_symbol_definitions (void)
  {
    int i;
 -  char const *sep = "";
 -
 -  fputs ("m4_define([b4_tokens], \n[", out);
 -  for (i = 0; i < ntokens; ++i)
 +  for (i = 0; i < nsyms; ++i)
      {
        symbol *sym = symbols[i];
 -      int number = sym->user_token_number;
 -
 -      /* At this stage, if there are literal string aliases, they are
 -         part of SYMBOLS, so we should not find their aliased symbols
 -         here.  */
 -      aver (number != USER_NUMBER_HAS_STRING_ALIAS);
 -
 -      /* Skip error token.  */
 -      if (sym == errtoken)
 -      continue;
 -
 -      /* If this string has an alias, then it is necessarily the alias
 -       which is to be output.  */
 -      if (sym->alias)
 -      sym = sym->alias;
 -
 -      /* Don't output literal chars or strings (when defined only as a
 -       string).  Note that must be done after the alias resolution:
 -       think about `%token 'f' "f"'.  */
 -      if (sym->tag[0] == '\'' || sym->tag[0] == '\"')
 -      continue;
 -
 -      /* Don't #define nonliteral tokens whose names contain periods,
 -         dashes or '$' (as does the default value of the EOF token).  */
 -      if (mbschr (sym->tag, '.')
 -          || mbschr (sym->tag, '-')
 -          || mbschr (sym->tag, '$'))
 -      continue;
 -
 -      fprintf (out, "%s[[[%s]], %d]",
 -             sep, sym->tag, number);
 -      sep = ",\n";
 -    }
 -  fputs ("])\n\n", out);
 -}
 +      const char *key;
 +      const char *value;
  
 +#define SET_KEY(Entry)                                          \
 +      obstack_fgrow2 (&format_obstack, "symbol(%d, %s)",        \
 +                      i, Entry);                                \
 +      obstack_1grow (&format_obstack, 0);                       \
 +      key = obstack_finish (&format_obstack);
  
 -/*---------------------------------------------------.
 -| Output the symbol destructors or printers to OUT.  |
 -`---------------------------------------------------*/
 +#define SET_KEY2(Entry, Suffix)                                 \
 +      obstack_fgrow3 (&format_obstack, "symbol(%d, %s_%s)",     \
 +                      i, Entry, Suffix);                        \
 +      obstack_1grow (&format_obstack, 0);                       \
 +      key = obstack_finish (&format_obstack);
  
 -static void
 -symbol_code_props_output (FILE *out, char const *what,
 -                          code_props const *(*get)(symbol const *))
 -{
 -  int i;
 -  char const *sep = "";
 +      // Whether the symbol has an identifier.
 +      value = symbol_id_get (sym);
 +      SET_KEY("has_id");
 +      MUSCLE_INSERT_INT (key, !!value);
  
 -  fputs ("m4_define([b4_symbol_", out);
 -  fputs (what, out);
 -  fputs ("], \n[", out);
 -  for (i = 0; i < nsyms; ++i)
 -    {
 -      symbol *sym = symbols[i];
 -      char const *code = (*get) (sym)->code;
 -      if (code)
 -        {
 -          location loc = (*get) (sym)->location;
 -          /* Filename, lineno,
 -             Symbol-name, Symbol-number,
 -             code, optional typename.  */
 -          fprintf (out, "%s[", sep);
 -          sep = ",\n";
 -          string_output (out, loc.start.file);
 -          fprintf (out, ", %d, ", loc.start.line);
 -          quoted_output (out, sym->tag);
 -          fprintf (out, ", %d, [[%s]]", sym->number, code);
 -          if (sym->type_name)
 -            {
 -              fputs (", ", out);
 -              quoted_output (out, sym->type_name);
 -            }
 -          fputc (']', out);
 -        }
 +      // Its identifier.
 +      SET_KEY("id");
 +      MUSCLE_INSERT_STRING (key, value ? value : "");
 +
 +      // Its tag.  Typically for documentation purpose.
 +      SET_KEY("tag");
 +      MUSCLE_INSERT_STRING (key, sym->tag);
 +
 +      SET_KEY("user_number");
 +      MUSCLE_INSERT_INT (key, sym->user_token_number);
 +
 +      SET_KEY("is_token");
 +      MUSCLE_INSERT_INT (key,
 +                         i < ntokens && sym != errtoken && sym != undeftoken);
 +
 +      SET_KEY("number");
 +      MUSCLE_INSERT_INT (key, sym->number);
 +
 +      SET_KEY("has_type");
 +      MUSCLE_INSERT_INT (key, !!sym->type_name);
 +
 +      SET_KEY("type");
 +      MUSCLE_INSERT_STRING (key, sym->type_name ? sym->type_name : "");
 +
 +      {
 +        int j;
 +        for (j = 0; j < CODE_PROPS_SIZE; ++j)
 +          {
 +            /* "printer", not "%printer".  */
 +            char const *pname = code_props_type_string (j) + 1;
 +            code_props const *p = symbol_code_props_get (sym, j);
 +            SET_KEY2("has", pname);
 +            MUSCLE_INSERT_INT (key, !!p->code);
 +
 +            if (p->code)
 +              {
 +                SET_KEY2(pname, "file");
 +                MUSCLE_INSERT_STRING (key, p->location.start.file);
 +
 +                SET_KEY2(pname, "line");
 +                MUSCLE_INSERT_INT (key, p->location.start.line);
 +
 +                SET_KEY(pname);
 +                MUSCLE_INSERT_STRING_RAW (key, p->code);
 +              }
 +          }
 +      }
 +#undef SET_KEY2
 +#undef SET_KEY
      }
 -  fputs ("])\n\n", out);
  }
  
  
@@@ -476,30 -438,30 +486,30 @@@ prepare_actions (void
       lookahead token type.  */
  
    muscle_insert_rule_number_table ("defact", yydefact,
 -                                 yydefact[0], 1, nstates);
 +                                   yydefact[0], 1, nstates);
  
    /* Figure out what to do after reducing with each rule, depending on
       the saved state from before the beginning of parsing the data
       that matched this rule.  */
    muscle_insert_state_number_table ("defgoto", yydefgoto,
 -                                  yydefgoto[0], 1, nsyms - ntokens);
 +                                    yydefgoto[0], 1, nsyms - ntokens);
  
  
    /* Output PACT. */
    muscle_insert_base_table ("pact", base,
 -                           base[0], 1, nstates);
 +                             base[0], 1, nstates);
    MUSCLE_INSERT_INT ("pact_ninf", base_ninf);
  
    /* Output PGOTO. */
    muscle_insert_base_table ("pgoto", base,
 -                           base[nstates], nstates + 1, nvectors);
 +                             base[nstates], nstates + 1, nvectors);
  
    muscle_insert_base_table ("table", table,
 -                          table[0], 1, high + 1);
 +                            table[0], 1, high + 1);
    MUSCLE_INSERT_INT ("table_ninf", table_ninf);
  
    muscle_insert_base_table ("check", check,
 -                          check[0], 1, high + 1);
 +                            check[0], 1, high + 1);
  
    /* GLR parsing slightly modifies YYTABLE and YYCHECK (and thus
       YYPACT) so that in states with unresolved conflicts, the default
       that case.  Nevertheless, it seems even better to be able to use
       the GLR skeletons even without the non-deterministic tables.  */
    muscle_insert_unsigned_int_table ("conflict_list_heads", conflict_table,
 -                                  conflict_table[0], 1, high + 1);
 +                                    conflict_table[0], 1, high + 1);
    muscle_insert_unsigned_int_table ("conflicting_rules", conflict_list,
 -                                  0, 1, conflict_list_cnt);
 +                                    0, 1, conflict_list_cnt);
  }
  
 +
  /*--------------------------------------------.
  | Output the definitions of all the muscles.  |
  `--------------------------------------------*/
@@@ -525,11 -486,13 +535,11 @@@ static voi
  muscles_output (FILE *out)
  {
    fputs ("m4_init()\n", out);
 -
 -  user_actions_output (out);
    merger_output (out);
 -  token_definitions_output (out);
 -  symbol_code_props_output (out, "destructors", &symbol_destructor_get);
 -  symbol_code_props_output (out, "printers", &symbol_printer_get);
 -
 +  symbol_numbers_output (out);
 +  type_names_output (out);
 +  user_actions_output (out);
 +  // Must be last.
    muscles_m4_output (out);
  }
  \f
  static void
  output_skeleton (void)
  {
 -  FILE *in;
    int filter_fd[2];
 -  char const *argv[10];
    pid_t pid;
  
    /* Compute the names of the package data dir and skeleton files.  */
 -  char const m4sugar[] = "m4sugar/m4sugar.m4";
 -  char const m4bison[] = "bison.m4";
 -  char *full_m4sugar;
 -  char *full_m4bison;
 -  char *full_skeleton;
 -  char const *p;
 -  char const *m4 = (p = getenv ("M4")) ? p : M4;
 -  char const *pkgdatadir = compute_pkgdatadir ();
 -  size_t skeleton_size = strlen (skeleton) + 1;
 -  size_t pkgdatadirlen = strlen (pkgdatadir);
 -  while (pkgdatadirlen && pkgdatadir[pkgdatadirlen - 1] == '/')
 -    pkgdatadirlen--;
 -  full_skeleton = xmalloc (pkgdatadirlen + 1
 -                         + (skeleton_size < sizeof m4sugar
 -                            ? sizeof m4sugar : skeleton_size));
 -  memcpy (full_skeleton, pkgdatadir, pkgdatadirlen);
 -  full_skeleton[pkgdatadirlen] = '/';
 -  strcpy (full_skeleton + pkgdatadirlen + 1, m4sugar);
 -  full_m4sugar = xstrdup (full_skeleton);
 -  strcpy (full_skeleton + pkgdatadirlen + 1, m4bison);
 -  full_m4bison = xstrdup (full_skeleton);
 -  if (mbschr (skeleton, '/'))
 -    strcpy (full_skeleton, skeleton);
 -  else
 -    strcpy (full_skeleton + pkgdatadirlen + 1, skeleton);
 +  char const *m4 = (m4 = getenv ("M4")) ? m4 : M4;
 +  char const *datadir = pkgdatadir ();
 +  char *m4sugar = xconcatenated_filename (datadir, "m4sugar/m4sugar.m4", NULL);
 +  char *m4bison = xconcatenated_filename (datadir, "bison.m4", NULL);
 +  char *skel = (IS_PATH_WITH_DIR (skeleton)
 +                ? xstrdup (skeleton)
 +                : xconcatenated_filename (datadir, skeleton, NULL));
  
    /* Test whether m4sugar.m4 is readable, to check for proper
       installation.  A faulty installation can cause deadlock, so a
       cheap sanity check is worthwhile.  */
 -  xfclose (xfopen (full_m4sugar, "r"));
 +  xfclose (xfopen (m4sugar, "r"));
  
    /* Create an m4 subprocess connected to us via two pipes.  */
  
    if (trace_flag & trace_tools)
      fprintf (stderr, "running: %s %s - %s %s\n",
 -             m4, full_m4sugar, full_m4bison, full_skeleton);
 +             m4, m4sugar, m4bison, skel);
  
    /* Some future version of GNU M4 (most likely 1.6) may treat the -dV in a
       position-dependent manner.  Keep it as the first argument so that all
       <http://lists.gnu.org/archive/html/bug-bison/2008-07/msg00000.html>
       for details.  */
    {
 +    char const *argv[10];
      int i = 0;
      argv[i++] = m4;
  
        argv[i++] = M4_GNU_OPTION;
  
      argv[i++] = "-I";
 -    argv[i++] = pkgdatadir;
 +    argv[i++] = datadir;
      if (trace_flag & trace_m4)
        argv[i++] = "-dV";
 -    argv[i++] = full_m4sugar;
 +    argv[i++] = m4sugar;
      argv[i++] = "-";
 -    argv[i++] = full_m4bison;
 -    argv[i++] = full_skeleton;
 +    argv[i++] = m4bison;
 +    argv[i++] = skel;
      argv[i++] = NULL;
      aver (i <= ARRAY_CARDINALITY (argv));
 +
 +    /* The ugly cast is because gnulib gets the const-ness wrong.  */
 +    pid = create_pipe_bidi ("m4", m4, (char **)(void*)argv, false, true,
 +                            true, filter_fd);
    }
  
 -  /* The ugly cast is because gnulib gets the const-ness wrong.  */
 -  pid = create_pipe_bidi ("m4", m4, (char **)(void*)argv, false, true,
 -                          true, filter_fd);
 -  free (full_m4sugar);
 -  free (full_m4bison);
 -  free (full_skeleton);
 +  free (m4sugar);
 +  free (m4bison);
 +  free (skel);
  
    if (trace_flag & trace_muscles)
      muscles_output (stderr);
    {
 -    FILE *out = fdopen (filter_fd[1], "w");
 -    if (! out)
 -      error (EXIT_FAILURE, get_errno (),
 -             "fdopen");
 +    FILE *out = xfdopen (filter_fd[1], "w");
      muscles_output (out);
      xfclose (out);
    }
  
    /* Read and process m4's output.  */
    timevar_push (TV_M4);
 -  in = fdopen (filter_fd[0], "r");
 -  if (! in)
 -    error (EXIT_FAILURE, get_errno (),
 -         "fdopen");
 -  scan_skel (in);
 -  /* scan_skel should have read all of M4's output.  Otherwise, when we
 -     close the pipe, we risk letting M4 report a broken-pipe to the
 -     Bison user.  */
 -  aver (feof (in));
 -  xfclose (in);
 +  {
 +    FILE *in = xfdopen (filter_fd[0], "r");
 +    scan_skel (in);
 +    /* scan_skel should have read all of M4's output.  Otherwise, when we
 +       close the pipe, we risk letting M4 report a broken-pipe to the
 +       Bison user.  */
 +    aver (feof (in));
 +    xfclose (in);
 +  }
    wait_subprocess (pid, "m4", false, false, true, true, NULL);
    timevar_pop (TV_M4);
  }
  static void
  prepare (void)
  {
 -  /* BISON_USE_PUSH_FOR_PULL is for the test suite and should not be documented
 -     for the user.  */
 -  char const *use_push_for_pull_env = getenv ("BISON_USE_PUSH_FOR_PULL");
 -  bool use_push_for_pull_flag = false;
 -  if (use_push_for_pull_env != NULL
 -      && use_push_for_pull_env[0] != '\0'
 -      && 0 != strcmp (use_push_for_pull_env, "0"))
 -    use_push_for_pull_flag = true;
 +  /* BISON_USE_PUSH_FOR_PULL is for the test suite and should not be
 +     documented for the user.  */
 +  char const *cp = getenv ("BISON_USE_PUSH_FOR_PULL");
 +  bool use_push_for_pull_flag = cp && *cp && strtol (cp, 0, 10);
  
    /* Flags. */
 -  MUSCLE_INSERT_BOOL ("debug_flag", debug_flag);
    MUSCLE_INSERT_BOOL ("defines_flag", defines_flag);
 -  MUSCLE_INSERT_BOOL ("error_verbose_flag", error_verbose);
    MUSCLE_INSERT_BOOL ("glr_flag", glr_parser);
 -  MUSCLE_INSERT_BOOL ("locations_flag", locations_flag);
    MUSCLE_INSERT_BOOL ("nondeterministic_flag", nondeterministic_parser);
    MUSCLE_INSERT_BOOL ("synclines_flag", !no_lines_flag);
    MUSCLE_INSERT_BOOL ("tag_seen_flag", tag_seen);
      /* b4_pkgdatadir is used inside m4_include in the skeletons, so digraphs
         would never be expanded.  Hopefully no one has M4-special characters in
         his Bison installation path.  */
 -    MUSCLE_INSERT_STRING_RAW ("pkgdatadir", compute_pkgdatadir ());
 +    MUSCLE_INSERT_STRING_RAW ("pkgdatadir", pkgdatadir ());
    }
  }
  
@@@ -694,7 -686,6 +704,7 @@@ output (void
    prepare_rules ();
    prepare_states ();
    prepare_actions ();
 +  prepare_symbol_definitions ();
  
    prepare ();
  
  }
  
  char const *
 -compute_pkgdatadir (void)
 +pkgdatadir (void)
  {
 -  char const *pkgdatadir = getenv ("BISON_PKGDATADIR");
 -  return pkgdatadir ? pkgdatadir : PKGDATADIR;
 +  char const *cp = getenv ("BISON_PKGDATADIR");
 +  return cp ? cp : PKGDATADIR;
  }
diff --combined src/parse-gram.y
index 9d9d1a42f58209557821cf439fd49527624fcaef,e6a27c50dcfac14e72c74234c1b0b3e57dbf7a5f..518969948f0586a22d438f41606175240e32e19d
@@@ -30,7 -30,6 +30,7 @@@
  #include "quotearg.h"
  #include "reader.h"
  #include "symlist.h"
 +#include "symtab.h"
  #include "scan-gram.h"
  #include "scan-code.h"
  #include "xmemdup0.h"
@@@ -39,7 -38,7 +39,7 @@@
  static YYLTYPE lloc_default (YYLTYPE const *, int);
  
  #define YY_LOCATION_PRINT(File, Loc) \
 -        location_print (File, Loc)
 +          location_print (File, Loc)
  
  static void version_check (location const *loc, char const *version);
  
     FIXME: depends on the undocumented availability of YYLLOC.  */
  #undef  yyerror
  #define yyerror(Msg) \
 -      gram_error (&yylloc, Msg)
 +        gram_error (&yylloc, Msg)
  static void gram_error (location const *, char const *);
  
  static char const *char_name (char);
 +%}
  
 -/** Add a lex-param or a parse-param.
 - *
 - * \param type  \a lex_param or \a parse_param
 - * \param decl  the formal argument
 - * \param loc   the location in the source.
 - */
 -static void add_param (char const *type, char *decl, location loc);
 -
 -
 -static symbol_class current_class = unknown_sym;
 -static uniqstr current_type = NULL;
 -static symbol *current_lhs_symbol;
 -static location current_lhs_location;
 -static named_ref *current_lhs_named_ref;
 -static int current_prec = 0;
 -
 -/** Set the new current left-hand side symbol, possibly common
 - * to several right-hand side parts of rule.
 - */
 -static
 -void
 -current_lhs(symbol *sym, location loc, named_ref *ref)
 +%code
  {
 -  current_lhs_symbol = sym;
 -  current_lhs_location = loc;
 -  /* In order to simplify memory management, named references for lhs
 -     are always assigned by deep copy into the current symbol_list
 -     node.  This is because a single named-ref in the grammar may
 -     result in several uses when the user factors lhs between several
 -     rules using "|".  Therefore free the parser's original copy.  */
 -  free (current_lhs_named_ref);
 -  current_lhs_named_ref = ref;
 -}
 -
 +  static int current_prec = 0;
 +  static location current_lhs_location;
 +  static named_ref *current_lhs_named_ref;
 +  static symbol *current_lhs_symbol;
 +  static symbol_class current_class = unknown_sym;
 +  static uniqstr current_type = NULL;
 +
 +  /** Set the new current left-hand side symbol, possibly common
 +   * to several right-hand side parts of rule.
 +   */
 +  static
 +  void
 +  current_lhs(symbol *sym, location loc, named_ref *ref)
 +  {
 +    current_lhs_symbol = sym;
 +    current_lhs_location = loc;
 +    /* In order to simplify memory management, named references for lhs
 +       are always assigned by deep copy into the current symbol_list
 +       node.  This is because a single named-ref in the grammar may
 +       result in several uses when the user factors lhs between several
 +       rules using "|".  Therefore free the parser's original copy.  */
 +    free (current_lhs_named_ref);
 +    current_lhs_named_ref = ref;
 +  }
  
 -#define YYTYPE_INT16 int_fast16_t
 -#define YYTYPE_INT8 int_fast8_t
 -#define YYTYPE_UINT16 uint_fast16_t
 -#define YYTYPE_UINT8 uint_fast8_t
 -%}
 +  #define YYTYPE_INT16 int_fast16_t
 +  #define YYTYPE_INT8 int_fast8_t
 +  #define YYTYPE_UINT16 uint_fast16_t
 +  #define YYTYPE_UINT8 uint_fast8_t
 +}
  
  %debug
  %verbose
  %defines
  %locations
  %pure-parser
 -%error-verbose
 +%define parse.error "verbose"
  %define parse.lac full
  %name-prefix="gram_"
  %expect 0
  
  %union
  {
 +  assoc assoc;
 +  char *code;
 +  char const *chars;
 +  int integer;
 +  named_ref *named_ref;
    symbol *symbol;
    symbol_list *list;
 -  int integer;
 -  char const *chars;
 -  char *code;
 -  assoc assoc;
    uniqstr uniqstr;
    unsigned char character;
 -  named_ref *named_ref;
  };
  
  /* Define the tokens together with their human representation.  */
  %token PERCENT_LEFT        "%left"
  %token PERCENT_RIGHT       "%right"
  %token PERCENT_NONASSOC    "%nonassoc"
 +%token PERCENT_PRECEDENCE  "%precedence"
  
  %token PERCENT_PREC          "%prec"
  %token PERCENT_DPREC         "%dprec"
  %token PERCENT_MERGE         "%merge"
  
 -
  /*----------------------.
  | Global Declarations.  |
  `----------------------*/
  
  %token
    PERCENT_CODE            "%code"
 -  PERCENT_DEBUG           "%debug"
    PERCENT_DEFAULT_PREC    "%default-prec"
    PERCENT_DEFINE          "%define"
    PERCENT_DEFINES         "%defines"
    PERCENT_ERROR_VERBOSE   "%error-verbose"
    PERCENT_EXPECT          "%expect"
 -  PERCENT_EXPECT_RR     "%expect-rr"
 +  PERCENT_EXPECT_RR       "%expect-rr"
 +  PERCENT_FLAG            "%<flag>"
    PERCENT_FILE_PREFIX     "%file-prefix"
    PERCENT_GLR_PARSER      "%glr-parser"
    PERCENT_INITIAL_ACTION  "%initial-action"
    PERCENT_LANGUAGE        "%language"
 -  PERCENT_LEX_PARAM       "%lex-param"
 -  PERCENT_LOCATIONS       "%locations"
    PERCENT_NAME_PREFIX     "%name-prefix"
    PERCENT_NO_DEFAULT_PREC "%no-default-prec"
    PERCENT_NO_LINES        "%no-lines"
    PERCENT_NONDETERMINISTIC_PARSER
 -                        "%nondeterministic-parser"
 +                          "%nondeterministic-parser"
    PERCENT_OUTPUT          "%output"
 -  PERCENT_PARSE_PARAM     "%parse-param"
 -  PERCENT_PURE_PARSER     "%pure-parser"
 -  PERCENT_REQUIRE       "%require"
 +  PERCENT_REQUIRE         "%require"
    PERCENT_SKELETON        "%skeleton"
    PERCENT_START           "%start"
    PERCENT_TOKEN_TABLE     "%token-table"
  ;
  
  %token BRACED_CODE     "{...}"
 +%token BRACED_PREDICATE "%?{...}"
  %token BRACKETED_ID    "[identifier]"
  %token CHAR            "char"
  %token EPILOGUE        "epilogue"
  %token PIPE            "|"
  %token PROLOGUE        "%{...%}"
  %token SEMICOLON       ";"
 -%token TYPE            "type"
 -%token TYPE_TAG_ANY    "<*>"
 -%token TYPE_TAG_NONE   "<>"
 +%token TAG             "<tag>"
 +%token TAG_ANY         "<*>"
 +%token TAG_NONE        "<>"
  
  %type <character> CHAR
 -%printer { fputs (char_name ($$), stderr); } CHAR
 +%printer { fputs (char_name ($$), yyo); } 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
 -%type <code> "{...}"
 -%printer { fputs (quotearg_style (c_quoting_style, $$), stderr); }
 -       STRING
 -%printer { fprintf (stderr, "{\n%s\n}", $$); }
 -       braceless content.opt "{...}" "%{...%}" EPILOGUE
 -
 -%type <uniqstr> BRACKETED_ID ID ID_COLON TYPE variable
 -%printer { fputs ($$, stderr); } <uniqstr>
 -%printer { fprintf (stderr, "[%s]", $$); } BRACKETED_ID
 -%printer { fprintf (stderr, "%s:", $$); } ID_COLON
 -%printer { fprintf (stderr, "<%s>", $$); } TYPE
 +%type <code> "{...}" "%?{...}"
 +%printer { fputs (quotearg_style (c_quoting_style, $$), yyo); }
 +         STRING
 +%printer { fprintf (yyo, "{\n%s\n}", $$); }
 +         braceless content.opt "{...}" "%{...%}" EPILOGUE
 +
 +%type <uniqstr> BRACKETED_ID ID ID_COLON PERCENT_FLAG TAG tag variable
 +%printer { fputs ($$, yyo); } <uniqstr>
 +%printer { fprintf (yyo, "[%s]", $$); } BRACKETED_ID
 +%printer { fprintf (yyo, "%s:", $$); } ID_COLON
 +%printer { fprintf (yyo, "%%%s", $$); } PERCENT_FLAG
 +%printer { fprintf (yyo, "<%s>", $$); } TAG tag
  
  %type <integer> INT
 -%printer { fprintf (stderr, "%d", $$); } <integer>
 +%printer { fprintf (yyo, "%d", $$); } <integer>
  
  %type <symbol> id id_colon string_as_id symbol symbol.prec
 -%printer { fprintf (stderr, "%s", $$->tag); } <symbol>
 -%printer { fprintf (stderr, "%s:", $$->tag); } id_colon
 +%printer { fprintf (yyo, "%s", $$->tag); } <symbol>
 +%printer { fprintf (yyo, "%s:", $$->tag); } id_colon
  
  %type <assoc> precedence_declarator
  %type <list>  symbols.1 symbols.prec generic_symlist generic_symlist_item
  %type <named_ref> named_ref.opt
  
 +/*---------.
 +| %param.  |
 +`---------*/
 +%code requires
 +{
 +# ifndef PARAM_TYPE
 +#  define PARAM_TYPE
 +  typedef enum
 +  {
 +    param_none   = 0,
 +    param_lex    = 1 << 0,
 +    param_parse  = 1 << 1,
 +    param_both   = param_lex | param_parse
 +  } param_type;
 +# endif
 +};
 +%code
 +{
 +  /** Add a lex-param and/or a parse-param.
 +   *
 +   * \param type  where to push this formal argument.
 +   * \param decl  the formal argument.  Destroyed.
 +   * \param loc   the location in the source.
 +   */
 +  static void add_param (param_type type, char *decl, location loc);
 +  static param_type current_param = param_none;
 +};
 +%union
 +{
 +  param_type param;
 +}
 +%token <param> PERCENT_PARAM "%param";
 +%printer
 +{
 +  switch ($$)
 +    {
 +#define CASE(In, Out)                                           \
 +      case param_ ## In: fputs ("%" #Out, stderr); break
 +      CASE(lex,   lex-param);
 +      CASE(parse, parse-param);
 +      CASE(both,  param);
 +#undef CASE
 +      case param_none: aver (false); break;
 +    }
 +} <param>;
 +
 +
 +                     /*==========\
 +                     | Grammar.  |
 +                     \==========*/
  %%
  
  input:
  ;
  
  
 -      /*------------------------------------.
 -      | Declarations: before the first %%.  |
 -      `------------------------------------*/
 +        /*------------------------------------.
 +        | Declarations: before the first %%.  |
 +        `------------------------------------*/
  
  prologue_declarations:
    /* Nothing */
@@@ -293,10 -251,7 +293,10 @@@ prologue_declaration
                          plain_code.code, @1);
        code_scanner_last_string_free ();
      }
 -| "%debug"                         { debug_flag = true; }
 +| "%<flag>"
 +    {
 +      muscle_percent_define_ensure ($1, @1, true);
 +    }
  | "%define" variable content.opt
      {
        muscle_percent_define_insert ($2, @2, $3,
        defines_flag = true;
        spec_defines_file = xstrdup ($2);
      }
 -| "%error-verbose"                 { error_verbose = true; }
 +| "%error-verbose"
 +    {
 +      muscle_percent_define_insert ("parse.error", @1, "verbose",
 +                                    MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE);
 +    }
  | "%expect" INT                    { expected_sr_conflicts = $2; }
 -| "%expect-rr" INT               { expected_rr_conflicts = $2; }
 +| "%expect-rr" INT                 { expected_rr_conflicts = $2; }
  | "%file-prefix" STRING            { spec_file_prefix = $2; }
  | "%file-prefix" "=" STRING        { spec_file_prefix = $3; } /* deprecated */
  | "%glr-parser"
        muscle_code_grow ("initial_action", action.code, @2);
        code_scanner_last_string_free ();
      }
 -| "%language" STRING          { language_argmatch ($2, grammar_prio, @1); }
 -| "%lex-param" "{...}"                { add_param ("lex_param", $2, @2); }
 -| "%locations"                  { locations_flag = true; }
 +| "%language" STRING            { language_argmatch ($2, grammar_prio, @1); }
  | "%name-prefix" STRING         { spec_name_prefix = $2; }
  | "%name-prefix" "=" STRING     { spec_name_prefix = $3; } /* deprecated */
  | "%no-lines"                   { no_lines_flag = true; }
 -| "%nondeterministic-parser"  { nondeterministic_parser = true; }
 +| "%nondeterministic-parser"    { nondeterministic_parser = true; }
  | "%output" STRING              { spec_outfile = $2; }
  | "%output" "=" STRING          { spec_outfile = $3; }  /* deprecated */
 -| "%parse-param" "{...}"      { add_param ("parse_param", $2, @2); }
 -| "%pure-parser"
 -    {
 -      /* %pure-parser is deprecated in favor of `%define api.pure', so use
 -         `%define api.pure' in a backward-compatible manner here.  First, don't
 -         complain if %pure-parser is specified multiple times.  */
 -      if (!muscle_find_const ("percent_define(api.pure)"))
 -        muscle_percent_define_insert ("api.pure", @1, "",
 -                                      MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE);
 -      /* In all cases, use api.pure now so that the backend doesn't complain if
 -         the skeleton ignores api.pure, but do warn now if there's a previous
 -         conflicting definition from an actual %define.  */
 -      if (!muscle_percent_define_flag_if ("api.pure"))
 -        muscle_percent_define_insert ("api.pure", @1, "",
 -                                      MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE);
 -    }
 +| "%param" { current_param = $1; } params { current_param = param_none; }
  | "%require" STRING             { version_check (&@2, $2); }
  | "%skeleton" STRING
      {
        char const *skeleton_user = $2;
 -      if (mbschr (skeleton_user, '/'))
 +      if (strchr (skeleton_user, '/'))
          {
            size_t dir_length = strlen (current_file);
            char *skeleton_build;
  | /*FIXME: Err?  What is this horror doing here? */ ";"
  ;
  
 +params:
 +   params "{...}"  { add_param (current_param, $2, @2); }
 +| "{...}"          { add_param (current_param, $1, @1); }
 +;
 +
 +
 +/*----------------------.
 +| grammar_declaration.  |
 +`----------------------*/
 +
  grammar_declaration:
    precedence_declaration
  | symbol_declaration
      {
        grammar_start_symbol_set ($2, @2);
      }
 -| "%destructor" "{...}" generic_symlist
 -    {
 -      code_props code;
 -      code_props_symbol_action_init (&code, $2, @2);
 -      code_props_translate_code (&code);
 -      {
 -        symbol_list *list;
 -        for (list = $3; list; list = list->next)
 -          symbol_list_destructor_set (list, &code);
 -        symbol_list_free ($3);
 -      }
 -    }
 -| "%printer" "{...}" generic_symlist
 +| code_props_type "{...}" generic_symlist
      {
-       symbol_list *list;
-       for (list = $3; list; list = list->next)
-         symbol_list_code_props_set (list, $1, @2, $2);
-       symbol_list_free ($3);
+       code_props code;
+       code_props_symbol_action_init (&code, $2, @2);
+       code_props_translate_code (&code);
+       {
+         symbol_list *list;
+         for (list = $3; list; list = list->next)
 -          symbol_list_printer_set (list, &code);
++          symbol_list_code_props_set (list, $1, &code);
+         symbol_list_free ($3);
+       }
      }
  | "%default-prec"
      {
      }
  ;
  
 +%type <code_type> code_props_type;
 +%union {code_props_type code_type;};
 +%printer { fprintf (yyo, "%s", code_props_type_string ($$)); } <code_type>;
 +code_props_type:
 +  "%destructor"  { $$ = destructor; }
 +| "%printer"     { $$ = printer; }
 +;
  
 -/*----------*
 - | %union.  |
 - *----------*/
 +/*---------.
 +| %union.  |
 +`---------*/
  
  %token PERCENT_UNION "%union";
  
@@@ -458,41 -426,40 +463,41 @@@ symbol_declaration
        current_class = unknown_sym;
        current_type = NULL;
      }
 -| "%type" TYPE symbols.1
 +| "%type" TAG symbols.1
      {
        symbol_list *list;
        tag_seen = true;
        for (list = $3; list; list = list->next)
 -      symbol_type_set (list->content.sym, $2, @2);
 +        symbol_type_set (list->content.sym, $2, @2);
        symbol_list_free ($3);
      }
  ;
  
  precedence_declaration:
 -  precedence_declarator type.opt symbols.prec
 +  precedence_declarator tag.opt symbols.prec
      {
        symbol_list *list;
        ++current_prec;
        for (list = $3; list; list = list->next)
 -      {
 -        symbol_type_set (list->content.sym, current_type, @2);
 -        symbol_precedence_set (list->content.sym, current_prec, $1, @1);
 -      }
 +        {
 +          symbol_type_set (list->content.sym, current_type, @2);
 +          symbol_precedence_set (list->content.sym, current_prec, $1, @1);
 +        }
        symbol_list_free ($3);
        current_type = NULL;
      }
  ;
  
  precedence_declarator:
 -  "%left"     { $$ = left_assoc; }
 -| "%right"    { $$ = right_assoc; }
 -| "%nonassoc" { $$ = non_assoc; }
 +  "%left"       { $$ = left_assoc; }
 +| "%right"      { $$ = right_assoc; }
 +| "%nonassoc"   { $$ = non_assoc; }
 +| "%precedence" { $$ = precedence_assoc; }
  ;
  
 -type.opt:
 +tag.opt:
    /* Nothing. */ { current_type = NULL; }
 -| TYPE           { current_type = $1; tag_seen = true; }
 +| TAG            { current_type = $1; tag_seen = true; }
  ;
  
  /* Just like symbols.1 but accept INT for the sake of POSIX.  */
@@@ -504,9 -471,9 +509,9 @@@ symbols.prec
  ;
  
  symbol.prec:
 -    symbol { $$ = $1; }
 -  | symbol INT { $$ = $1; symbol_user_token_number_set ($1, $2, @2); }
 -  ;
 +  symbol     { $$ = $1; }
 +| symbol INT { $$ = $1; symbol_user_token_number_set ($1, $2, @2); }
 +;
  
  /* One or more symbols to be %typed. */
  symbols.1:
@@@ -522,19 -489,15 +527,19 @@@ generic_symlist
  ;
  
  generic_symlist_item:
 -  symbol            { $$ = symbol_list_sym_new ($1, @1); }
 -| TYPE              { $$ = symbol_list_type_new ($1, @1); }
 -| "<*>"             { $$ = symbol_list_default_tagged_new (@1); }
 -| "<>"             { $$ = symbol_list_default_tagless_new (@1); }
 +  symbol    { $$ = symbol_list_sym_new ($1, @1); }
 +| tag       { $$ = symbol_list_type_new ($1, @1); }
 +;
 +
 +tag:
 +  TAG
 +| "<*>" { $$ = uniqstr_new ("*"); }
 +| "<>"  { $$ = uniqstr_new (""); }
  ;
  
  /* One token definition.  */
  symbol_def:
 -  TYPE
 +  TAG
       {
         current_type = $1;
         tag_seen = true;
@@@ -572,9 -535,9 +577,9 @@@ symbol_defs.1
  ;
  
  
 -      /*------------------------------------------.
 -      | The grammar section: between the two %%.  |
 -      `------------------------------------------*/
 +        /*------------------------------------------.
 +        | The grammar section: between the two %%.  |
 +        `------------------------------------------*/
  
  grammar:
    rules_or_grammar_declaration
@@@ -609,18 -572,16 +614,18 @@@ rhses.1
  rhs:
    /* Nothing.  */
      { grammar_current_rule_begin (current_lhs_symbol, current_lhs_location,
 -                                current_lhs_named_ref); }
 +                                  current_lhs_named_ref); }
  | 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
      { grammar_current_rule_dprec_set ($3, @3); }
 -| rhs "%merge" TYPE
 +| rhs "%merge" TAG
      { grammar_current_rule_merge_set ($3, @3); }
  ;
  
@@@ -630,9 -591,10 +635,9 @@@ named_ref.opt
    BRACKETED_ID   { $$ = named_ref_new($1, @1); }
  ;
  
 -
 -/*----------------------------*
 - | variable and content.opt.  |
 - *---------------------------*/
 +/*---------------------------.
 +| variable and content.opt.  |
 +`---------------------------*/
  
  /* The STRING form of variable is deprecated and is not M4-friendly.
     For example, M4 fails for `%define "[" "value"'.  */
@@@ -649,9 -611,9 +654,9 @@@ content.opt
  ;
  
  
 -/*-------------*
 - | braceless.  |
 - *-------------*/
 +/*------------.
 +| braceless.  |
 +`------------*/
  
  braceless:
    "{...}"
  ;
  
  
 -/*---------------*
 - | Identifiers.  |
 - *---------------*/
 +/*--------------.
 +| Identifiers.  |
 +`--------------*/
  
  /* Identifiers are returned as uniqstr values by the scanner.
     Depending on their use, we may need to make them genuine symbols.  */
@@@ -741,52 -703,49 +746,52 @@@ lloc_default (YYLTYPE const *rhs, int n
    for (i = 1; i <= n; i++)
      if (! equal_boundaries (rhs[i].start, rhs[i].end))
        {
 -      loc.start = rhs[i].start;
 -      break;
 +        loc.start = rhs[i].start;
 +        break;
        }
  
    return loc;
  }
  
  
 -/* Add a lex-param or a parse-param (depending on TYPE) with
 -   declaration DECL and location LOC.  */
 -
  static void
 -add_param (char const *type, char *decl, location loc)
 +add_param (param_type type, char *decl, location loc)
  {
    static char const alphanum[26 + 26 + 1 + 10] =
      "abcdefghijklmnopqrstuvwxyz"
      "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
      "_"
      "0123456789";
 +
    char const *name_start = NULL;
 -  char *p;
 -
 -  /* Stop on last actual character.  */
 -  for (p = decl; p[1]; p++)
 -    if ((p == decl
 -       || ! memchr (alphanum, p[-1], sizeof alphanum))
 -      && memchr (alphanum, p[0], sizeof alphanum - 10))
 -      name_start = p;
 -
 -  /* Strip the surrounding '{' and '}', and any blanks just inside
 -     the braces.  */
 -  while (*--p == ' ' || *p == '\t')
 -    continue;
 -  p[1] = '\0';
 -  while (*++decl == ' ' || *decl == '\t')
 -    continue;
 +  {
 +    char *p;
 +    /* Stop on last actual character.  */
 +    for (p = decl; p[1]; p++)
 +      if ((p == decl
 +           || ! memchr (alphanum, p[-1], sizeof alphanum))
 +          && memchr (alphanum, p[0], sizeof alphanum - 10))
 +        name_start = p;
 +
 +    /* Strip the surrounding '{' and '}', and any blanks just inside
 +       the braces.  */
 +    while (*--p == ' ' || *p == '\t')
 +      continue;
 +    p[1] = '\0';
 +    while (*++decl == ' ' || *decl == '\t')
 +      continue;
 +  }
  
    if (! name_start)
 -    complain_at (loc, _("missing identifier in parameter declaration"));
 +    complain_at (loc, complaint,
 +                 _("missing identifier in parameter declaration"));
    else
      {
        char *name = xmemdup0 (name_start, strspn (name_start, alphanum));
 -      muscle_pair_list_grow (type, decl, name);
 +      if (type & param_lex)
 +        muscle_pair_list_grow ("lex_param", decl, name);
 +      if (type & param_parse)
 +        muscle_pair_list_grow ("parse_param", decl, name);
        free (name);
      }
  
@@@ -799,7 -758,7 +804,7 @@@ version_check (location const *loc, cha
  {
    if (strverscmp (version, PACKAGE_VERSION) > 0)
      {
 -      complain_at (*loc, "require bison %s, but have %s",
 +      complain_at (*loc, complaint, "require bison %s, but have %s",
                     version, PACKAGE_VERSION);
        exit (EX_MISMATCH);
      }
  static void
  gram_error (location const *loc, char const *msg)
  {
 -  complain_at (*loc, "%s", msg);
 +  complain_at (*loc, complaint, "%s", msg);
  }
  
  char const *
diff --combined src/scan-code.h
index 2dfb1704adb0386cfa0b0c932de1ea5099f14c63,c8d554d5b095396871e03dcf8e2b486985dc894c..348d9e3f820e9e865644993cd00e74cd42d8f607
@@@ -45,7 -45,10 +45,10 @@@ typedef struct code_props 
      CODE_PROPS_SYMBOL_ACTION, CODE_PROPS_RULE_ACTION
    } kind;
  
-   /** \c NULL iff \c code_props::kind is \c CODE_PROPS_NONE.  */
+   /**
+    * \c NULL iff \c code_props::kind is \c CODE_PROPS_NONE.
+    * Memory is allocated in an obstack freed elsewhere.
+    */
    char const *code;
    /** Undefined iff \c code_props::code is \c NULL.  */
    location location;
     */
    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;
 +
 +  /**
 +   * Whether this is actually used (i.e., not completely masked by
 +   * other code props).  */
 +  bool is_used;
 +
    /** \c NULL iff \c code_props::kind is not \c CODE_PROPS_RULE_ACTION.  */
    struct symbol_list *rule;
  
  void code_props_none_init (code_props *self);
  
  /** Equivalent to \c code_props_none_init.  */
 -#define CODE_PROPS_NONE_INIT \
 -  {CODE_PROPS_NONE, NULL, EMPTY_LOCATION_INIT, false, NULL, NULL}
 +#define CODE_PROPS_NONE_INIT                    \
 +  {                                             \
 +    /* .kind = */ CODE_PROPS_NONE,              \
 +    /* .code = */ NULL,                         \
 +    /* .location = */ EMPTY_LOCATION_INIT,      \
 +    /* .is_value_used = */ false,               \
 +    /* .is_predicate = */ false,                \
 +    /* .is_used = */ false,                     \
 +    /* .rule = */ NULL,                         \
 +    /* .named_ref = */ NULL                     \
 +  }
  
  /** Initialized by \c CODE_PROPS_NONE_INIT with no further modification.  */
 -extern code_props const code_props_none;
 +extern code_props code_props_none;
  
  /**
   * \pre
@@@ -154,7 -137,7 +157,7 @@@ void code_props_symbol_action_init (cod
   */
  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
diff --combined src/scan-code.l
index f6efeffdfec9898cb05c8f7e65f09763b689e9a6,31befe9172f9bc7e8d6c99f543e4f8c5649ff2af..2fe880ed6a371d03215cc19af83d16320a6759e7
  #define code_wrap() 1
  
  #define FLEX_PREFIX(Id) code_ ## Id
 -#include "flex-scanner.h"
 +#include <src/flex-scanner.h>
  
 -#include "complain.h"
 -#include "reader.h"
 -#include "getargs.h"
 -#include "scan-code.h"
 -#include "symlist.h"
 +#include <src/complain.h>
 +#include <src/reader.h>
 +#include <src/getargs.h>
 +#include <src/muscle-tab.h>
 +#include <src/scan-code.h>
 +#include <src/symlist.h>
  
  #include <c-ctype.h>
  #include <get-errno.h>
@@@ -47,8 -46,11 +47,11 @@@ YY_DECL
  
  #define YY_USER_ACTION  location_compute (loc, &loc->end, yytext, yyleng);
  
+ static char *fetch_type_name (char *cp, char const **type_name,
+                               location dollar_loc);
  static void handle_action_dollar (symbol_list *rule, char *cp,
 -                                location dollar_loc);
 +                                  location dollar_loc);
  static void handle_action_at (symbol_list *rule, char *cp, location at_loc);
  
  /* A string to be pushed to obstack after dollar/at has been handled. */
@@@ -76,17 -78,17 +79,17 @@@ static bool untyped_var_seen
  /* POSIX says that a tag must be both an id and a C union member, but
     historically almost any character is allowed in a tag.  We disallow
     NUL and newline, as this simplifies our implementation.  */
 -tag    [^\0\n>]+
 +tag      [^\0\n>]+
  
  /* Zero or more instances of backslash-newline.  Following GCC, allow
     white space between the backslash and the newline.  */
 -splice         (\\[ \f\t\v]*\n)*
 +splice   (\\[ \f\t\v]*\n)*
  
  /* C style identifier. Must start with letter. Will be used for
     named symbol references. Shall be kept synchronized with
     scan-gram.l "letter" and "id". */
 -letter          [.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_]
 -id      {letter}({letter}|[-0-9])*
 +letter    [.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_]
 +id        {letter}({letter}|[-0-9])*
  ref      -?[0-9]+|{id}|"["{id}"]"|"$"
  
  %%
    int braces_level = 0;
  
    /* Whether a semicolon is probably needed.
-      The heuristic is that a semicolon is not needed after '{', '}', ';',
-      or a C preprocessor directive, and that whitespaces and comments
-      do not affect this flag.
-      Note that '{' does not need a semicolon because of '{}'.
-      A semicolon may be needed before a cpp direcive, but don't bother.  */
+      The heuristic is that a semicolon is not needed after '{', '}',
+      ';', or a C preprocessor directive, and that whitespaces and
+      comments do not affect this flag.  Note that '{' does not need a
+      semicolon because of '{}'.  A semicolon may be needed before a
+      cpp directive, but don't bother.
+      While it is maintained in several start-conditions (factoring
+      opportunities), it is meaningful only for SC_RULE_ACTION. */
    bool need_semicolon = false;
  
    /* Whether in a C preprocessor directive.  Don't use a start condition
       is expected to return only once.  This initialization is
       therefore done once per action to translate. */
    aver (sc_context == SC_SYMBOL_ACTION
 -      || sc_context == SC_RULE_ACTION
 -      || sc_context == INITIAL);
 +        || sc_context == SC_RULE_ACTION
 +        || sc_context == INITIAL);
    BEGIN sc_context;
  %}
  
  
  <SC_LINE_COMMENT>
  {
 -  "\n"                 STRING_GROW; BEGIN sc_context;
 -  {splice}     STRING_GROW;
 +  "\n"           STRING_GROW; BEGIN sc_context;
 +  {splice}       STRING_GROW;
  }
  
  
  
  <SC_CHARACTER,SC_STRING>
  {
 -  {splice}|\\{splice}.        STRING_GROW;
 +  {splice}|\\{splice}.  STRING_GROW;
  }
  
  <SC_CHARACTER>
  {
 -  "'"         STRING_GROW; BEGIN sc_context;
 +  "'"           STRING_GROW; BEGIN sc_context;
  }
  
  <SC_STRING>
  {
 -  "\""                STRING_GROW; BEGIN sc_context;
 +  "\""          STRING_GROW; BEGIN sc_context;
  }
  
  
- <SC_RULE_ACTION,SC_SYMBOL_ACTION>{
+ <SC_RULE_ACTION,SC_SYMBOL_ACTION>
+ {
    "'" {
      STRING_GROW;
      BEGIN SC_CHARACTER;
      STRING_GROW;
      BEGIN SC_LINE_COMMENT;
    }
 -    warn_at (*loc, _("stray '%s'"), yytext);
+   [$@]  {
++    complain_at (*loc, Wother, _("stray '%s'"), yytext);
+     obstack_escape (&obstack_for_string, yytext);
+     need_semicolon = true;
+   }
+   [\[\]]  {
+     obstack_escape (&obstack_for_string, yytext);
+     need_semicolon = true;
+   }
  }
  
  <SC_RULE_ACTION>
  {
    "$"("<"{tag}">")?{ref}  {
-     ref_tail_fields = 0;
+     ref_tail_fields = NULL;
      handle_action_dollar (self->rule, yytext, *loc);
-     if (ref_tail_fields) {
+     if (ref_tail_fields)
        obstack_sgrow (&obstack_for_string, ref_tail_fields);
-     }
      need_semicolon = true;
    }
    "@"{ref} {
-     ref_tail_fields = 0;
+     ref_tail_fields = NULL;
      handle_action_at (self->rule, yytext, *loc);
-     if (ref_tail_fields) {
+     if (ref_tail_fields)
        obstack_sgrow (&obstack_for_string, ref_tail_fields);
-     }
-     need_semicolon = true;
-   }
-   "$"  {
-     complain_at (*loc, Wother, _("stray '$'"));
-     obstack_sgrow (&obstack_for_string, "$][");
-     need_semicolon = true;
-   }
-   "@"  {
-     complain_at (*loc, Wother, _("stray '@'"));
-     obstack_sgrow (&obstack_for_string, "@@");
-     need_semicolon = true;
-   }
-   "["  {
-     obstack_sgrow (&obstack_for_string, "@{");
-     need_semicolon = true;
-   }
-   "]"  {
-     obstack_sgrow (&obstack_for_string, "@}");
      need_semicolon = true;
    }
  
      if (outer_brace && !yacc_flag && language_prio == default_prio
          && skeleton_prio == default_prio && need_semicolon && ! in_cpp)
        {
 -        warn_at (*loc, _("a ';' might be needed at the end of action code"));
 -        warn_at (*loc, _("future versions of Bison will not add the ';'"));
 +        complain_at (*loc, Wother,
 +                     _("a ';' might be needed at the end of action code"));
 +        complain_at (*loc, Wother,
 +                     _("future versions of Bison will not add the ';'"));
          obstack_1grow (&obstack_for_string, ';');
        }
  
    {splice}  STRING_GROW;
    [\n\r]    STRING_GROW; if (in_cpp) in_cpp = need_semicolon = false;
    [ \t\f]   STRING_GROW;
 -
 -  /* YYFAIL is undocumented and was formally deprecated in Bison
 -     2.4.2.  */
 -  YYFAIL {
 -    STRING_GROW; need_semicolon = true;
 -    warn_at (*loc, _("use of YYFAIL, which is deprecated and will be"
 -                     " removed"));
 -  }
 -
 -  /* The sole purpose of this is to make sure identifiers that merely
 -     contain YYFAIL don't produce the above warning.  */
 -  [A-Za-z_][0-9A-Za-z_]* STRING_GROW; need_semicolon = true;
 -
 -  . STRING_GROW; need_semicolon = true;
 +  .         STRING_GROW; need_semicolon = true;
  }
  
  <SC_SYMBOL_ACTION>
  {
-   "$$" {
-     obstack_sgrow (&obstack_for_string, "]b4_dollar_dollar[");
+   "$"("<"{tag}">")?"$" {
+     const char *type_name = NULL;
+     fetch_type_name (yytext + 1, &type_name, *loc)[-1] = 0;
+     obstack_sgrow (&obstack_for_string, "]b4_dollar_dollar(");
+     obstack_quote (&obstack_for_string, type_name);
+     obstack_sgrow (&obstack_for_string, ")[");
      self->is_value_used = true;
    }
    "@$" {
      obstack_sgrow (&obstack_for_string, "]b4_at_dollar[");
 -    locations_flag = true;
 +    muscle_percent_define_ensure("locations", the_location, true);
    }
  }
  
  
-   /*-----------------------------------------.
-   | Escape M4 quoting characters in C code.  |
-   `-----------------------------------------*/
  <*>
  {
-   \$    obstack_sgrow (&obstack_for_string, "$][");
-   \@    obstack_sgrow (&obstack_for_string, "@@");
-   \[    obstack_sgrow (&obstack_for_string, "@{");
-   \]    obstack_sgrow (&obstack_for_string, "@}");
- }
-   /*-----------------------------------------------------.
-   | By default, grow the string obstack with the input.  |
-   `-----------------------------------------------------*/
+   /* Escape M4 quoting characters in C code.  */
+   [$@\[\]]    obstack_escape (&obstack_for_string, yytext);
  
- <*>.|\n STRING_GROW;
+   /* By default, grow the string obstack with the input.  */
+   .|\n        STRING_GROW;
  
 -  /* End of processing. */
 + /* End of processing. */
- <*><<EOF>>       {
-                    STRING_FINISH;
-                    return last_string;
-                  }
+   <<EOF>>     STRING_FINISH; return last_string;
+ }
  
  %%
  
@@@ -335,7 -334,7 +324,7 @@@ typedef struc
     not visible from current midrule. */
  #define VARIANT_NOT_VISIBLE_FROM_MIDRULE (1 << 2)
  
- static variant *variant_table = 0;
+ static variant *variant_table = NULL;
  static unsigned variant_table_size = 0;
  static unsigned variant_count = 0;
  
@@@ -346,9 -345,9 +335,9 @@@ variant_table_grow (void
    if (variant_count > variant_table_size)
      {
        while (variant_count > variant_table_size)
 -      variant_table_size = 2 * variant_table_size + 3;
 +        variant_table_size = 2 * variant_table_size + 3;
        variant_table = xnrealloc (variant_table, variant_table_size,
 -                               sizeof *variant_table);
 +                                 sizeof *variant_table);
      }
    return &variant_table[variant_count - 1];
  }
@@@ -357,7 -356,7 +346,7 @@@ static voi
  variant_table_free (void)
  {
    free (variant_table);
-   variant_table = 0;
+   variant_table = NULL;
    variant_table_size = variant_count = 0;
  }
  
@@@ -378,7 -377,7 +367,7 @@@ find_prefix_end (const char *prefix, ch
  
  static variant *
  variant_add (uniqstr id, location id_loc, unsigned symbol_index,
 -           char *cp, char *cp_end, bool explicit_bracketing)
 +             char *cp, char *cp_end, bool explicit_bracketing)
  {
    char *prefix_end;
  
  }
  
  static const char *
 -get_at_spec (unsigned symbol_index)
 +get_at_spec(unsigned symbol_index)
  {
    static char at_buf[20];
    if (symbol_index == 0)
@@@ -425,62 -424,60 +414,62 @@@ show_sub_messages (const char* cp, boo
        if (var->err == 0)
          {
            if (is_warning)
 -            warn_at_indent (var->loc, &indent, _("refers to: %c%s at %s"),
 -                            dollar_or_at, var->id, at_spec);
 +            complain_at_indent (var->loc, Wother, &indent,
 +                                _("refers to: %c%s at %s"), dollar_or_at,
 +                                var->id, at_spec);
            else
 -            complain_at_indent (var->loc, &indent, _("refers to: %c%s at %s"),
 -                                dollar_or_at, var->id, at_spec);
 +            complain_at_indent (var->loc, complaint, &indent,
 +                                _("refers to: %c%s at %s"), dollar_or_at,
 +                                var->id, at_spec);
          }
        else
 -      {
 -        static struct obstack msg_buf;
 -        const char *tail = explicit_bracketing ? "" :
 -          cp + strlen (var->id);
 -        const char *id = var->hidden_by ? var->hidden_by->id :
 -          var->id;
 -        location id_loc = var->hidden_by ? var->hidden_by->loc :
 -          var->loc;
 -
 -        /* Create the explanation message. */
 -        obstack_init (&msg_buf);
 -
 -        obstack_fgrow1 (&msg_buf, _("possibly meant: %c"), dollar_or_at);
 -        if (contains_dot_or_dash (id))
 -          obstack_fgrow1 (&msg_buf, "[%s]", id);
 -        else
 -          obstack_sgrow (&msg_buf, id);
 -        obstack_sgrow (&msg_buf, tail);
 -
 -        if (var->err & VARIANT_HIDDEN)
 -          {
 -            obstack_fgrow1 (&msg_buf, _(", hiding %c"), dollar_or_at);
 -            if (contains_dot_or_dash (var->id))
 -              obstack_fgrow1 (&msg_buf, "[%s]", var->id);
 -            else
 -              obstack_sgrow (&msg_buf, var->id);
 -            obstack_sgrow (&msg_buf, tail);
 -          }
 -
 -        obstack_fgrow1 (&msg_buf, _(" at %s"), at_spec);
 -
 -        if (var->err & VARIANT_NOT_VISIBLE_FROM_MIDRULE)
 +        {
 +          static struct obstack msg_buf;
 +          const char *tail = explicit_bracketing ? "" :
 +            cp + strlen (var->id);
 +          const char *id = var->hidden_by ? var->hidden_by->id :
 +            var->id;
 +          location id_loc = var->hidden_by ? var->hidden_by->loc :
 +            var->loc;
 +
 +          /* Create the explanation message. */
 +          obstack_init (&msg_buf);
 +
 +          obstack_fgrow1 (&msg_buf, _("possibly meant: %c"), dollar_or_at);
 +          if (contains_dot_or_dash (id))
 +            obstack_fgrow1 (&msg_buf, "[%s]", id);
 +          else
 +            obstack_sgrow (&msg_buf, id);
 +          obstack_sgrow (&msg_buf, tail);
 +
 +          if (var->err & VARIANT_HIDDEN)
 +            {
 +              obstack_fgrow1 (&msg_buf, _(", hiding %c"), dollar_or_at);
 +              if (contains_dot_or_dash (var->id))
 +                obstack_fgrow1 (&msg_buf, "[%s]", var->id);
 +              else
 +                obstack_sgrow (&msg_buf, var->id);
 +              obstack_sgrow (&msg_buf, tail);
 +            }
 +
 +          obstack_fgrow1 (&msg_buf, _(" at %s"), at_spec);
 +
 +          if (var->err & VARIANT_NOT_VISIBLE_FROM_MIDRULE)
              {
                const char *format =
                  _(", cannot be accessed from mid-rule action at $%d");
                obstack_fgrow1 (&msg_buf, format, midrule_rhs_index);
              }
  
 -        obstack_1grow (&msg_buf, '\0');
 +          obstack_1grow (&msg_buf, '\0');
            if (is_warning)
 -            warn_at_indent (id_loc, &indent, "%s",
 -                            (char *) obstack_finish (&msg_buf));
 +            complain_at_indent (id_loc, Wother, &indent, "%s",
 +                                (char *) obstack_finish (&msg_buf));
            else
 -            complain_at_indent (id_loc, &indent, "%s",
 +            complain_at_indent (id_loc, complaint, &indent, "%s",
                                  (char *) obstack_finish (&msg_buf));
 -        obstack_free (&msg_buf, 0);
 -      }
 +          obstack_free (&msg_buf, 0);
 +        }
      }
  }
  
     accesses. */
  static long int
  parse_ref (char *cp, symbol_list *rule, int rule_length,
 -         int midrule_rhs_index, char *text, location text_loc,
 -         char dollar_or_at)
 +           int midrule_rhs_index, char *text, location text_loc,
 +           char dollar_or_at)
  {
    symbol_list *l;
    char *cp_end;
      {
        long int num = strtol (cp, &cp, 10);
        if (1 - INT_MAX + rule_length <= num && num <= rule_length)
 -      return num;
 +        return num;
        else
 -      {
 -        complain_at (text_loc, _("integer out of range: %s"),
 +        {
 +          complain_at (text_loc, complaint, _("integer out of range: %s"),
                         quote (text));
 -        return INVALID_REF;
 -      }
 +          return INVALID_REF;
 +        }
      }
  
    if ('[' == *cp)
        /* Ignore the brackets. */
        char *p;
        for (p = ++cp; *p != ']'; ++p)
 -      continue;
 +        continue;
        cp_end = p;
  
        explicit_bracketing = true;
        /* Take all characters of the name. */
        char* p;
        for (p = cp; *p; ++p)
 -      if (is_dot_or_dash (*p))
 -        {
 -          ref_tail_fields = p;
 -          break;
 -        }
 +        if (is_dot_or_dash (*p))
 +          {
 +            ref_tail_fields = p;
 +            break;
 +          }
        for (p = cp; *p; ++p)
 -      continue;
 +        continue;
        cp_end = p;
  
        explicit_bracketing = false;
      for (symbol_index = 0, l = rule; !symbol_list_null (l);
           ++symbol_index, l = l->next)
        {
 -      variant *var;
 -      if (l->content_type != SYMLIST_SYMBOL)
 -        continue;
 +        variant *var;
 +        if (l->content_type != SYMLIST_SYMBOL)
 +          continue;
  
 -      var = variant_add (l->content.sym->tag, l->sym_loc,
 +        var = variant_add (l->content.sym->tag, l->sym_loc,
                             symbol_index, cp, cp_end, explicit_bracketing);
 -      if (var && l->named_ref)
 -        var->hidden_by = l->named_ref;
 +        if (var && l->named_ref)
 +          var->hidden_by = l->named_ref;
  
 -      if (l->named_ref)
 -        variant_add (l->named_ref->id, l->named_ref->loc,
 +        if (l->named_ref)
 +          variant_add (l->named_ref->id, l->named_ref->loc,
                         symbol_index, cp, cp_end, explicit_bracketing);
        }
    }
  
        /* Check visibility from mid-rule actions. */
        if (midrule_rhs_index != 0
 -        && (symbol_index == 0 || midrule_rhs_index < symbol_index))
 +          && (symbol_index == 0 || midrule_rhs_index < symbol_index))
          var->err |= VARIANT_NOT_VISIBLE_FROM_MIDRULE;
  
        /* Check correct bracketing. */
            cp_end - cp : ref_tail_fields - cp;
          unsigned indent = 0;
  
 -        complain_at_indent (text_loc, &indent, _("invalid reference: %s"),
 -                            quote (text));
 +        complain_at_indent (text_loc, complaint, &indent,
 +                            _("invalid reference: %s"), quote (text));
          indent += SUB_INDENT;
          if (len == 0)
            {
              const char *format =
                _("syntax error after '%c', expecting integer, letter,"
                  " '_', '[', or '$'");
 -            complain_at_indent (sym_loc, &indent, format, dollar_or_at);
 +            complain_at_indent (sym_loc, complaint, &indent, format,
 +                                dollar_or_at);
            }
          else if (midrule_rhs_index)
            {
              const char *format =
                _("symbol not found in production before $%d: %.*s");
 -            complain_at_indent (rule->location, &indent, format,
 +            complain_at_indent (rule->location, complaint, &indent, format,
                                  midrule_rhs_index, len, cp);
            }
          else
            {
              const char *format =
                _("symbol not found in production: %.*s");
 -            complain_at_indent (rule->location, &indent, format,
 +            complain_at_indent (rule->location, complaint, &indent, format,
                                  len, cp);
            }
  
          unsigned indent = 0;
          if (variant_count > 1)
            {
 -            warn_at_indent (text_loc, &indent, _("misleading reference: %s"),
 -                            quote (text));
 +            complain_at_indent (text_loc, Wother, &indent,
 +                                _("misleading reference: %s"), quote (text));
              show_sub_messages (cp, explicit_bracketing, midrule_rhs_index,
                                 dollar_or_at, true, indent + SUB_INDENT);
            }
      default:
        {
          unsigned indent = 0;
 -        complain_at_indent (text_loc, &indent, _("ambiguous reference: %s"),
 -                            quote (text));
 +        complain_at_indent (text_loc, complaint, &indent,
 +                            _("ambiguous reference: %s"), quote (text));
          show_sub_messages (cp, explicit_bracketing, midrule_rhs_index,
                             dollar_or_at, false, indent + SUB_INDENT);
          return INVALID_REF;
  int max_left_semantic_context = 0;
  
  
 -      ++cp;
+ /* If CP points to a typename (i.e., <.*?>), set TYPE_NAME to its
+    beginning (i.e., after the opening "<", and return the pointer
+    immediately after it.  */
+ static
+ char *
+ fetch_type_name (char *cp, char const **type_name,
+                  location dollar_loc)
+ {
+   if (*cp == '<')
+     {
+       *type_name = ++cp;
+       while (*cp != '>')
 -       'text' is needed for error messages. */
++        ++cp;
+       /* The '>' symbol will be later replaced by '\0'. Original
 -      complain_at (dollar_loc, _("explicit type given in untyped grammar"));
++         'text' is needed for error messages. */
+       ++cp;
+       if (untyped_var_seen)
++        complain_at (dollar_loc, complaint,
++                     _("explicit type given in untyped grammar"));
+       tag_seen = true;
+     }
+   return cp;
+ }
  /*------------------------------------------------------------------.
  | TEXT is pointing to a wannabee semantic value (i.e., a '$').      |
  |                                                                   |
@@@ -694,7 -715,6 +709,6 @@@ handle_action_dollar (symbol_list *rule
  {
    char const *type_name = NULL;
    char *cp = text + 1;
-   char *gt_ptr = 0;
    symbol_list *effective_rule;
    int effective_rule_length;
    int n;
      }
  
    /* Get the type name if explicit. */
-   if (*cp == '<')
-     {
-       type_name = ++cp;
-       while (*cp != '>')
-         ++cp;
-       /* The '>' symbol will be later replaced by '\0'. Original
-          'text' is needed for error messages. */
-       gt_ptr = cp;
-       ++cp;
-       if (untyped_var_seen)
-         complain_at (dollar_loc, complaint,
-                   _("explicit type given in untyped grammar"));
-       tag_seen = true;
-     }
+   cp = fetch_type_name (cp, &type_name, dollar_loc);
  
    n = parse_ref (cp, effective_rule, effective_rule_length,
 -               rule->midrule_parent_rhs_index, text, dollar_loc, '$');
 +                 rule->midrule_parent_rhs_index, text, dollar_loc, '$');
  
-   if (gt_ptr)
-     *gt_ptr = '\0';
+   /* End type_name. */
+   if (type_name)
+     cp[-1] = '\0';
  
    switch (n)
      {
  
      case LHS_REF:
        if (!type_name)
 -      type_name = symbol_list_n_type_name_get (rule, dollar_loc, 0);
 +        type_name = symbol_list_n_type_name_get (rule, dollar_loc, 0);
  
        if (!type_name)
          {
            if (union_seen | tag_seen)
              {
                if (rule->midrule_parent_rule)
 -                complain_at (dollar_loc,
 +                complain_at (dollar_loc, complaint,
                               _("$$ for the midrule at $%d of %s"
                                 " has no declared type"),
                               rule->midrule_parent_rhs_index,
                               quote (effective_rule->content.sym->tag));
                else
 -                complain_at (dollar_loc, _("$$ of %s has no declared type"),
 +                complain_at (dollar_loc, complaint,
 +                             _("$$ of %s has no declared type"),
                               quote (rule->content.sym->tag));
              }
            else
              untyped_var_seen = true;
-           type_name = "";
          }
  
-       obstack_fgrow1 (&obstack_for_string,
-                       "]b4_lhs_value([%s])[", type_name);
+       obstack_sgrow (&obstack_for_string, "]b4_lhs_value(");
+       obstack_quote (&obstack_for_string, type_name);
+       obstack_sgrow (&obstack_for_string, ")[");
        rule->action_props.is_value_used = true;
        break;
  
      default:
        if (max_left_semantic_context < 1 - n)
 -      max_left_semantic_context = 1 - n;
 +        max_left_semantic_context = 1 - n;
        if (!type_name && 0 < n)
 -      type_name =
 -        symbol_list_n_type_name_get (effective_rule, dollar_loc, n);
 +        type_name =
 +          symbol_list_n_type_name_get (effective_rule, dollar_loc, n);
        if (!type_name)
          {
            if (union_seen | tag_seen)
 -            complain_at (dollar_loc, _("$%s of %s has no declared type"),
 -                         cp, quote (effective_rule->content.sym->tag));
 +            complain_at (dollar_loc, complaint,
 +                         _("$%s of %s has no declared type"), cp,
 +                         quote (effective_rule->content.sym->tag));
            else
              untyped_var_seen = true;
-           type_name = "";
          }
  
-       obstack_fgrow3 (&obstack_for_string,
-                       "]b4_rhs_value(%d, %d, [%s])[",
-                       effective_rule_length, n, type_name);
+       obstack_fgrow2 (&obstack_for_string,
 -                    "]b4_rhs_value(%d, %d, ", effective_rule_length, n);
++                      "]b4_rhs_value(%d, %d, ", effective_rule_length, n);
+       obstack_quote (&obstack_for_string, type_name);
+       obstack_sgrow (&obstack_for_string, ")[");
        if (n > 0)
 -      symbol_list_n_get (effective_rule, n)->action_props.is_value_used =
 -        true;
 +        symbol_list_n_get (effective_rule, n)->action_props.is_value_used =
 +          true;
        break;
      }
  }
@@@ -819,10 -824,10 +820,10 @@@ handle_action_at (symbol_list *rule, ch
        effective_rule_length = symbol_list_length (rule->next);
      }
  
 -  locations_flag = true;
 +  muscle_percent_define_ensure("locations", at_loc, true);
  
    n = parse_ref (cp, effective_rule, effective_rule_length,
 -                 rule->midrule_parent_rhs_index, text, at_loc, '@');
 +                       rule->midrule_parent_rhs_index, text, at_loc, '@');
    switch (n)
      {
      case INVALID_REF:
  
      default:
        obstack_fgrow2 (&obstack_for_string, "]b4_rhs_location(%d, %d)[",
 -                    effective_rule_length, n);
 +                      effective_rule_length, n);
        break;
      }
  }
@@@ -877,40 -882,43 +878,40 @@@ code_props_none_init (code_props *self
    *self = code_props_none;
  }
  
 -code_props const code_props_none = CODE_PROPS_NONE_INIT;
 +code_props code_props_none = CODE_PROPS_NONE_INIT;
  
  void
  code_props_plain_init (code_props *self, char const *code,
 -                     location code_loc)
 +                       location code_loc)
  {
 +  code_props_none_init (self);
    self->kind = CODE_PROPS_PLAIN;
    self->code = code;
    self->location = code_loc;
 -  self->is_value_used = false;
 -  self->rule = NULL;
 -  self->named_ref = NULL;
  }
  
  void
  code_props_symbol_action_init (code_props *self, char const *code,
                                 location code_loc)
  {
 +  code_props_none_init (self);
    self->kind = CODE_PROPS_SYMBOL_ACTION;
    self->code = code;
    self->location = code_loc;
 -  self->is_value_used = false;
 -  self->rule = NULL;
 -  self->named_ref = NULL;
  }
  
  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)
  {
 +  code_props_none_init (self);
    self->kind = CODE_PROPS_RULE_ACTION;
    self->code = code;
    self->location = code_loc;
 -  self->is_value_used = false;
    self->rule = rule;
    self->named_ref = name;
 +  self->is_predicate = is_predicate;
  }
  
  void
diff --combined src/scan-skel.l
index 17382a73890ec54ac47cb7e473e331777b40ba62,862b34fd37e43131aef9a68ac3c66e285bae363f..b79e58323e0cc2a95fc1232c6437ed2a56099151
@@@ -1,6 -1,6 +1,6 @@@
  /* Scan Bison Skeletons.                                       -*- C -*-
  
 -   Copyright (C) 2001-2007, 2009-2012 Free Software Foundation, Inc.
 +   Copyright (C) 2001-2012 Free Software Foundation, Inc.
  
     This file is part of Bison, the GNU Compiler Compiler.
  
  #define skel_wrap() 1
  
  #define FLEX_PREFIX(Id) skel_ ## Id
 -#include "flex-scanner.h"
 +#include <src/flex-scanner.h>
  
  #include <dirname.h>
  #include <error.h>
  #include <quotearg.h>
  
 -#include "complain.h"
 -#include "getargs.h"
 -#include "files.h"
 -#include "scan-skel.h"
 +#include <src/complain.h>
 +#include <src/getargs.h>
 +#include <src/files.h>
 +#include <src/scan-skel.h>
  
  #define YY_DECL static int skel_lex (void)
  YY_DECL;
@@@ -72,8 -72,8 +72,8 @@@ static void fail_for_invalid_at (char c
  "@@" fputc ('@', yyout);
  "@{" fputc ('[', yyout);
  "@}" fputc (']', yyout);
- "@`" /* Empty.  Used by b4_cat in ../data/bison.m4.  */
- @\n  /* Likewise.  */
+ "@`" continue;  /* Used by b4_cat in ../data/bison.m4.  */
+ @\n  continue;
  
  "@oline@"  fprintf (yyout, "%d", out_lineno + 1);
  "@ofile@"  QPUTS (outname);
  }
  
    /* This pattern must not match more than the previous @ patterns. */
 -@[^@{}`(\n]*  fail_for_invalid_at (yytext);
 -\n            out_lineno++; ECHO;
 -[^@\n]+       ECHO;
 +@[^@{}`(\n]* fail_for_invalid_at (yytext);
 +\n         out_lineno++; ECHO;
 +[^@\n]+    ECHO;
  
- <INITIAL><<EOF>> {
+ <<EOF>> {
    if (outname)
      {
        free (outname);
    return EOF;
  }
  
- <SC_AT_DIRECTIVE_ARGS>{
-   [^@]+ { STRING_GROW; }
+ <SC_AT_DIRECTIVE_ARGS>
+ {
+   [^@]+  STRING_GROW;
  
-   "@@" { obstack_1grow (&obstack_for_string, '@'); }
-   "@{" { obstack_1grow (&obstack_for_string, '['); }
-   "@}" { obstack_1grow (&obstack_for_string, ']'); }
-   "@`" /* Empty.  Useful for starting an argument
-           that begins with whitespace. */
-   @\n  /* Empty.  */
+   "@@"   obstack_1grow (&obstack_for_string, '@');
+   "@{"   obstack_1grow (&obstack_for_string, '[');
+   "@}"   obstack_1grow (&obstack_for_string, ']');
+   "@`"   continue; /* For starting an argument that begins with whitespace. */
+   @\n    continue;
  
    @[,)] {
      if (at_directive_argc >= AT_DIRECTIVE_ARGC_MAX)
        }
    }
  
-   @.? { fail_for_invalid_at (yytext); }
+   @.?  fail_for_invalid_at (yytext);
  }
  
- <SC_AT_DIRECTIVE_SKIP_WS>{
-   [ \t\r\n]
+ <SC_AT_DIRECTIVE_SKIP_WS>
+ {
+   [ \t\r\n]    continue;
 -  .            { yyless (0); BEGIN SC_AT_DIRECTIVE_ARGS; }
 +  . { yyless (0); BEGIN SC_AT_DIRECTIVE_ARGS; }
  }
  
- <SC_AT_DIRECTIVE_ARGS,SC_AT_DIRECTIVE_SKIP_WS>{
+ <SC_AT_DIRECTIVE_ARGS,SC_AT_DIRECTIVE_SKIP_WS>
+ {
    <<EOF>> {
 -    fatal (_("unclosed %s directive in skeleton"), at_directive_argv[0]);
 +    complain (fatal, _("unclosed %s directive in skeleton"),
 +              at_directive_argv[0]);
    }
  }
  
@@@ -179,98 -180,94 +181,98 @@@ at_directive_perform (int at_directive_
                        char *at_directive_argv[],
                        char **outnamep, int *out_linenop)
  {
 -  if (0 == strcmp (at_directive_argv[0], "@basename"))
 +  if (STREQ (at_directive_argv[0], "@basename"))
      {
        if (at_directive_argc > 2)
          fail_for_at_directive_too_many_args (at_directive_argv[0]);
        fputs (last_component (at_directive_argv[1]), yyout);
      }
 -  else if (0 == strcmp (at_directive_argv[0], "@warn")
 -           || 0 == strcmp (at_directive_argv[0], "@complain")
 -           || 0 == strcmp (at_directive_argv[0], "@fatal"))
 +  else if (STREQ (at_directive_argv[0], "@warn")
 +           || STREQ (at_directive_argv[0], "@complain")
 +           || STREQ (at_directive_argv[0], "@fatal"))
      {
 -      void (*func)(char const *, ...);
 +      warnings complaint_flag;
        switch (at_directive_argv[0][1])
          {
 -          case 'w': func = warn; break;
 -          case 'c': func = complain; break;
 -          case 'f': func = fatal; break;
 -          default: aver (false); break;
 +        case 'w': complaint_flag = Wother; break;
 +        case 'c': complaint_flag = complaint; break;
 +        case 'f': complaint_flag = fatal; break;
 +        default: aver (false); break;
          }
        switch (at_directive_argc)
          {
            case 2:
 -            func (_(at_directive_argv[1]));
 +            complain (complaint_flag, "%s", _(at_directive_argv[1]));
              break;
            case 3:
 -            func (_(at_directive_argv[1]), at_directive_argv[2]);
 +            complain (complaint_flag, _(at_directive_argv[1]),
 +                      at_directive_argv[2]);
              break;
            case 4:
 -            func (_(at_directive_argv[1]), at_directive_argv[2],
 -                  at_directive_argv[3]);
 +            complain (complaint_flag, _(at_directive_argv[1]),
 +                      at_directive_argv[2], at_directive_argv[3]);
              break;
            case 5:
 -            func (_(at_directive_argv[1]), at_directive_argv[2],
 -                  at_directive_argv[3], at_directive_argv[4]);
 +            complain (complaint_flag, _(at_directive_argv[1]),
 +                      at_directive_argv[2], at_directive_argv[3],
 +                      at_directive_argv[4]);
              break;
            case 6:
 -            func (_(at_directive_argv[1]), at_directive_argv[2],
 -                  at_directive_argv[3], at_directive_argv[4],
 -                  at_directive_argv[5]);
 +            complain (complaint_flag, _(at_directive_argv[1]),
 +                      at_directive_argv[2], at_directive_argv[3],
 +                      at_directive_argv[4], at_directive_argv[5]);
              break;
            default:
              fail_for_at_directive_too_many_args (at_directive_argv[0]);
              break;
          }
      }
 -  else if (0 == strcmp (at_directive_argv[0], "@warn_at")
 -           || 0 == strcmp (at_directive_argv[0], "@complain_at")
 -           || 0 == strcmp (at_directive_argv[0], "@fatal_at"))
 +  else if (STREQ (at_directive_argv[0], "@warn_at")
 +           || STREQ (at_directive_argv[0], "@complain_at")
 +           || STREQ (at_directive_argv[0], "@fatal_at"))
      {
 -      void (*func)(location, char const *, ...);
 +      warnings complaint_flag;
        location loc;
        if (at_directive_argc < 4)
          fail_for_at_directive_too_few_args (at_directive_argv[0]);
        switch (at_directive_argv[0][1])
          {
 -          case 'w': func = warn_at; break;
 -          case 'c': func = complain_at; break;
 -          case 'f': func = fatal_at; break;
 -          default: aver (false); break;
 +        case 'w': complaint_flag = Wother; break;
 +        case 'c': complaint_flag = complaint; break;
 +        case 'f': complaint_flag = fatal; break;
 +        default: aver (false); break;
          }
        boundary_set_from_string (&loc.start, at_directive_argv[1]);
        boundary_set_from_string (&loc.end, at_directive_argv[2]);
        switch (at_directive_argc)
          {
            case 4:
 -            func (loc, _(at_directive_argv[3]));
 +            complain_at (loc, complaint_flag, "%s", _(at_directive_argv[3]));
              break;
            case 5:
 -            func (loc, _(at_directive_argv[3]), at_directive_argv[4]);
 +            complain_at (loc, complaint_flag, _(at_directive_argv[3]),
 +                      at_directive_argv[4]);
              break;
            case 6:
 -            func (loc, _(at_directive_argv[3]), at_directive_argv[4],
 -                  at_directive_argv[5]);
 +            complain_at (loc, complaint_flag, _(at_directive_argv[3]),
 +                      at_directive_argv[4], at_directive_argv[5]);
              break;
            case 7:
 -            func (loc, _(at_directive_argv[3]), at_directive_argv[4],
 -                  at_directive_argv[5], at_directive_argv[6]);
 +            complain_at (loc, complaint_flag, _(at_directive_argv[3]),
 +                      at_directive_argv[4], at_directive_argv[5],
 +                      at_directive_argv[6]);
              break;
            case 8:
 -            func (loc, _(at_directive_argv[3]), at_directive_argv[4],
 -                  at_directive_argv[5], at_directive_argv[6],
 -                  at_directive_argv[7]);
 +            complain_at (loc, complaint_flag, _(at_directive_argv[3]),
 +                      at_directive_argv[4], at_directive_argv[5],
 +                      at_directive_argv[6], at_directive_argv[7]);
              break;
            default:
              fail_for_at_directive_too_many_args (at_directive_argv[0]);
              break;
          }
      }
 -  else if (0 == strcmp (at_directive_argv[0], "@output"))
 +  else if (STREQ (at_directive_argv[0], "@output"))
      {
        if (at_directive_argc > 2)
          fail_for_at_directive_too_many_args (at_directive_argv[0]);
  static void
  fail_for_at_directive_too_few_args (char const *at_directive_name)
  {
 -  fatal (_("too few arguments for %s directive in skeleton"),
 +  complain (fatal, _("too few arguments for %s directive in skeleton"),
           at_directive_name);
  }
  
  static void
  fail_for_at_directive_too_many_args (char const *at_directive_name)
  {
 -  fatal (_("too many arguments for %s directive in skeleton"),
 -         at_directive_name);
 +  complain (fatal, _("too many arguments for %s directive in skeleton"),
 +            at_directive_name);
  }
  
  static void
  fail_for_invalid_at (char const *at)
  {
 -  fatal ("invalid @ in skeleton: %s", at);
 +  complain (fatal, "invalid @ in skeleton: %s", at);
  }
diff --combined src/symlist.c
index bd9f3c233191402b8daa7cbe6d782d9881314966,69ac8a1b574c9684cd49157ab9a25184839dbeeb..2bbedb585c95028b5a58bec55577ab9a2c048c2f
@@@ -24,6 -24,7 +24,6 @@@
  #include "complain.h"
  #include "symlist.h"
  
 -
  /*--------------------------------------.
  | Create a list containing SYM at LOC.  |
  `--------------------------------------*/
@@@ -65,11 -66,43 +65,11 @@@ symbol_list_type_new (uniqstr type_name
    symbol_list *res = xmalloc (sizeof *res);
  
    res->content_type = SYMLIST_TYPE;
 -  res->content.type_name = type_name;
 -  res->location = res->sym_loc = loc;
 -  res->named_ref = NULL;
 -  res->next = NULL;
 +  res->content.sem_type = xmalloc (sizeof (semantic_type));
 +  res->content.sem_type->tag = type_name;
 +  res->content.sem_type->location = loc;
 +  res->content.sem_type->status = undeclared;
  
 -  return res;
 -}
 -
 -
 -/*----------------------------------------.
 -| Create a list containing a <*> at LOC.  |
 -`----------------------------------------*/
 -
 -symbol_list *
 -symbol_list_default_tagged_new (location loc)
 -{
 -  symbol_list *res = xmalloc (sizeof *res);
 -
 -  res->content_type = SYMLIST_DEFAULT_TAGGED;
 -  res->location = res->sym_loc = loc;
 -  res->named_ref = NULL;
 -  res->next = NULL;
 -
 -  return res;
 -}
 -
 -
 -/*---------------------------------------.
 -| Create a list containing a <> at LOC.  |
 -`---------------------------------------*/
 -
 -symbol_list *
 -symbol_list_default_tagless_new (location loc)
 -{
 -  symbol_list *res = xmalloc (sizeof *res);
 -
 -  res->content_type = SYMLIST_DEFAULT_TAGLESS;
    res->location = res->sym_loc = loc;
    res->named_ref = NULL;
    res->next = NULL;
@@@ -90,7 -123,7 +90,7 @@@ symbol_list_syms_print (const symbol_li
        symbol_print (l->content.sym, f);
        fprintf (stderr, l->action_props.is_value_used ? " used" : " unused");
        if (l && l->content.sym)
 -      fprintf (f, ", ");
 +        fprintf (f, ", ");
      }
  }
  
@@@ -157,7 -190,7 +157,7 @@@ symbol_list_n_get (symbol_list *l, int 
        l = l->next;
        if (l == NULL
            || (l->content_type == SYMLIST_SYMBOL && l->content.sym == NULL))
 -      return NULL;
 +        return NULL;
      }
  
    return l;
@@@ -175,7 -208,7 +175,7 @@@ symbol_list_n_type_name_get (symbol_lis
    l = symbol_list_n_get (l, n);
    if (!l)
      {
 -      complain_at (loc, _("invalid $ value: $%d"), n);
 +      complain_at (loc, complaint, _("invalid $ value: $%d"), n);
        return NULL;
      }
    aver (l->content_type == SYMLIST_SYMBOL);
@@@ -190,26 -223,43 +190,23 @@@ symbol_list_null (symbol_list *node
  }
  
  void
 -symbol_list_destructor_set (symbol_list *node, code_props const *destructor)
 -{
 -  switch (node->content_type)
 -    {
 -      case SYMLIST_SYMBOL:
 -        symbol_destructor_set (node->content.sym, destructor);
 -        break;
 -      case SYMLIST_TYPE:
 -        semantic_type_destructor_set (
 -          semantic_type_get (node->content.type_name), destructor);
 -        break;
 -      case SYMLIST_DEFAULT_TAGGED:
 -        default_tagged_destructor_set (destructor);
 -        break;
 -      case SYMLIST_DEFAULT_TAGLESS:
 -        default_tagless_destructor_set (destructor);
 -        break;
 -    }
 -}
 -
 -void
 -symbol_list_printer_set (symbol_list *node, code_props const *printer)
 +symbol_list_code_props_set (symbol_list *node, code_props_type kind,
-                             location loc, char const *code)
++                            code_props const *cprops)
  {
-   code_props cprops;
-   code_props_symbol_action_init (&cprops, code, loc);
-   code_props_translate_code (&cprops);
    switch (node->content_type)
      {
        case SYMLIST_SYMBOL:
-         symbol_code_props_set (node->content.sym, kind, &cprops);
 -        symbol_printer_set (node->content.sym, printer);
++        symbol_code_props_set (node->content.sym, kind, cprops);
 +        if (node->content.sym->status == undeclared)
 +          node->content.sym->status = used;
          break;
        case SYMLIST_TYPE:
 -        semantic_type_printer_set (
 -          semantic_type_get (node->content.type_name), printer);
 -        break;
 -      case SYMLIST_DEFAULT_TAGGED:
 -        default_tagged_printer_set (printer);
 -        break;
 -      case SYMLIST_DEFAULT_TAGLESS:
 -        default_tagless_printer_set (printer);
 +        semantic_type_code_props_set
 +          (semantic_type_get (node->content.sem_type->tag,
 +                              &node->content.sem_type->location),
-            kind, &cprops);
++           kind, cprops);
 +        if (node->content.sem_type->status == undeclared)
 +          node->content.sem_type->status = used;
          break;
      }
  }
diff --combined src/symlist.h
index dd63408339b791d5d8a6890f584d9408889bd004,63577f798b7862845c90b11a40f5e4572df954c7..03ffebef16572034acc847f03c7a5e78e9c98fe2
@@@ -34,8 -34,8 +34,8 @@@ typedef struct symbol_lis
     * \c <>.
     */
    enum {
 -    SYMLIST_SYMBOL, SYMLIST_TYPE,
 -    SYMLIST_DEFAULT_TAGGED, SYMLIST_DEFAULT_TAGLESS
 +    SYMLIST_SYMBOL,
 +    SYMLIST_TYPE
    } content_type;
    union {
      /**
@@@ -46,7 -46,7 +46,7 @@@
      /**
       * The semantic type iff <tt>symbol_list::content_type = SYMLIST_TYPE</tt>.
       */
 -    uniqstr type_name;
 +    semantic_type *sem_type;
    } content;
    location location;
  
@@@ -88,6 -88,11 +88,6 @@@ symbol_list *symbol_list_sym_new (symbo
  /** Create a list containing \c type_name at \c loc.  */
  symbol_list *symbol_list_type_new (uniqstr type_name, location loc);
  
 -/** Create a list containing a \c <*> at \c loc.  */
 -symbol_list *symbol_list_default_tagged_new (location loc);
 -/** Create a list containing a \c <> at \c loc.  */
 -symbol_list *symbol_list_default_tagless_new (location loc);
 -
  /** Print this list.
  
    \pre For every node \c n in the list, <tt>n->content_type =
@@@ -113,9 -118,12 +113,8 @@@ uniqstr symbol_list_n_type_name_get (sy
  /* Check whether the node is a border element of a rule. */
  bool symbol_list_null (symbol_list *node);
  
- /** Set the \c \%destructor or \c \%printer for \c node as \c code at
-     \c loc.  */
 -/** Set the \c \%destructor for \c node as \c code at \c loc.  */
 -void symbol_list_destructor_set (symbol_list *node,
 -                                 code_props const *destructor);
 -
 -/** Set the \c \%printer for \c node as \c code at \c loc.  */
 -void symbol_list_printer_set (symbol_list *node,
 -                              code_props const *printer);
++/** Set the \c \%destructor or \c \%printer for \c node as \c cprops.  */
 +void symbol_list_code_props_set (symbol_list *node, code_props_type kind,
-                                  location loc, char const *code);
++                                 code_props const *cprops);
  
  #endif /* !SYMLIST_H_ */
diff --combined src/symtab.h
index 9377800801e4d6bc793e6e622545de7d616a1e9a,7d8cf982650f36ff71f829976388eaa23a7563dd..49eebd4c2aaf34f286d639eaf49d0dce88f35d5e
@@@ -1,7 -1,7 +1,7 @@@
  /* Definitions for symtab.c and callers, part of Bison.
  
 -   Copyright (C) 1984, 1989, 1992, 2000-2002, 2004-2007, 2009-2012 Free
 -   Software Foundation, Inc.
 +   Copyright (C) 1984, 1989, 1992, 2000-2002, 2004-2012 Free Software
 +   Foundation, Inc.
  
     This file is part of Bison, the GNU Compiler Compiler.
  
@@@ -39,8 -39,8 +39,8 @@@
  typedef enum
  {
    unknown_sym,          /**< Undefined.  */
 -  token_sym,          /**< Terminal. */
 -  nterm_sym           /**< Non-terminal. */
 +  token_sym,            /**< Terminal. */
 +  nterm_sym             /**< Non-terminal. */
  } symbol_class;
  
  
@@@ -51,38 -51,6 +51,38 @@@ typedef int symbol_number
  
  typedef struct symbol symbol;
  
 +/* Declaration status of a symbol.
 +
 +   First, it is "undeclared".  Then, if "undeclared" and used in a
 +   %printer/%destructor, it is "used".  If not "declared" by used in a
 +   rule, it is "needed".  Finally, if declared (via a rule for
 +   nonterminals, or %oken), it is "declared".
 +
 +   When status are checked at the end, "declared" symbols are fine,
 +   "used" symbols trigger warnings, otherwise it's an error.
 +*/
 +
 +typedef enum
 +  {
 +    /** Used in the input file for an unknown reason (error).  */
 +    undeclared,
 +    /** Used by %destructor/%printer but not defined (warning).  */
 +    used,
 +    /** Used in the gramar (rules) but not defined (error).  */
 +    needed,
 +    /** Defined with %type or %token (good).  */
 +    declared,
 +  } status;
 +
 +typedef enum code_props_type code_props_type;
 +enum code_props_type
 +  {
 +    destructor = 0,
 +    printer = 1,
 +  };
 +
 +enum { CODE_PROPS_SIZE = 2 };
 +
  /* When extending this structure, be sure to complete
     symbol_check_alias_consistency.  */
  struct symbol
    /** The location of its first occurrence.  */
    location location;
  
-   /** Its \c \%type.  */
+   /** Its \c \%type.
+       Beware that this is the type_name as was entered by the user,
+       including silly things such as "]" if she entered "%token <]> t".
+       Therefore, when outputting type_name to M4, be sure to escape it
+       into "@}".  See quoted_output for instance.  */
    uniqstr type_name;
    /** Its \c \%type's location.  */
    location type_location;
  
 -  /** Any \c \%destructor declared specifically for this symbol.
 -
 -      Access this field only through <tt>symbol</tt>'s interface
 -      functions.  For example, if <tt>symbol::destructor = NULL</tt>, a
 -      default \c \%destructor or a per-type \c \%destructor might be
 -      appropriate, and \c symbol_destructor_get will compute the
 -      correct one.  */
 -  code_props destructor;
 -
 -  /** Any \c \%printer declared specifically for this symbol.
 +  /** Any \c \%destructor (resp. \%printer) declared specificially for this
 +      symbol.
  
 -      Access this field only through <tt>symbol</tt>'s interface functions.
 -      \sa symbol::destructor  */
 -  code_props printer;
 +      Access this field only through <tt>symbol</tt>'s interface functions. For
-       Example, if <tt>symbol::destructor = NULL</tt> (resp. <tt>symbol::printer
++      example, if <tt>symbol::destructor = NULL</tt> (resp. <tt>symbol::printer
 +      = NULL</tt>), a default \c \%destructor (resp. \%printer) or a per-type
-       \c symbol_destructor_printer_get will compute the corect one. */
++      \c symbol_destructor_printer_get will compute the correct one. */
 +  code_props props[CODE_PROPS_SIZE];
  
    symbol_number number;
    location prec_location;
       symbol-string pair for an alias.  */
    symbol *alias;
    symbol_class class;
 -  bool declared;
 +  status status;
  };
  
  /** Undefined user number.  */
  /* Undefined internal token number.  */
  #define NUMBER_UNDEFINED (-1)
  
 -/** Print a symbol (for debugging). */
 -void symbol_print (symbol *s, FILE *f);
 -
  /** Fetch (or create) the symbol associated to KEY.  */
  symbol *symbol_from_uniqstr (const uniqstr key, location loc);
  
@@@ -143,26 -126,9 +149,26 @@@ symbol *symbol_get (const char *key, lo
     Its name cannot conflict with the user's names.  */
  symbol *dummy_symbol_get (location loc);
  
 +
 +/*--------------------.
 +| Methods on symbol.  |
 +`--------------------*/
 +
 +/** Print a symbol (for debugging). */
 +void symbol_print (symbol const *s, FILE *f);
 +
  /** Is this a dummy nonterminal?  */
  bool symbol_is_dummy (const symbol *sym);
  
 +/** The name of the code_props type: "\%destructor" or "\%printer".  */
 +char const *code_props_type_string (code_props_type kind);
 +
 +/** The name of the symbol that can be used as an identifier.
 + ** Consider the alias if needed.
 + ** Return 0 if there is none (e.g., the symbol is only defined as
 + ** a string). */
 +uniqstr symbol_id_get (symbol const *sym);
 +
  /**
   * Make \c str the literal string alias of \c sym.  Copy token number,
   * symbol number, and type from \c sym to \c str.
@@@ -174,34 -140,34 +180,34 @@@ void symbol_make_alias (symbol *sym, sy
      Do nothing if passed 0 as \c type_name.  */
  void symbol_type_set (symbol *sym, uniqstr type_name, location loc);
  
 -/** Set the \c destructor associated with \c sym.  */
 -void symbol_destructor_set (symbol *sym, code_props const *destructor);
 -
 -/** Get the computed \c \%destructor for \c sym, which was initialized with
 -    \c code_props_none_init if there's no \c \%destructor.  */
 -code_props const *symbol_destructor_get (symbol const *sym);
 +/** Set the \c \%destructor or \c \%printer associated with \c sym.  */
 +void symbol_code_props_set (symbol *sym, code_props_type kind,
 +                            code_props const *destructor);
  
 -/** Set the \c printer associated with \c sym.  */
 -void symbol_printer_set (symbol *sym, code_props const *printer);
 +/** Get the computed \c \%destructor or \c %printer for \c sym, which was
 +    initialized with \c code_props_none_init if there's no \c \%destructor or
 +    \c %printer.  */
 +code_props *symbol_code_props_get (symbol *sym, code_props_type kind);
  
 -/** Get the computed \c \%printer for \c sym, which was initialized with
 -    \c code_props_none_init if there's no \c \%printer.  */
 -code_props const *symbol_printer_get (symbol const *sym);
 +/** Set the \c precedence associated with \c sym.
  
 -/* Set the \c precedence associated with \c sym.
 -
 -   Ensure that \a symbol is a terminal.
 -   Do nothing if invoked with \c undef_assoc as \c assoc.  */
 +    Ensure that \a symbol is a terminal.
 +    Do nothing if invoked with \c undef_assoc as \c assoc.  */
  void symbol_precedence_set (symbol *sym, int prec, assoc a, location loc);
  
  /** Set the \c class associated with \c sym.  */
  void symbol_class_set (symbol *sym, symbol_class class, location loc,
 -                     bool declaring);
 +                       bool declaring);
  
  /** Set the \c user_token_number associated with \c sym.  */
  void symbol_user_token_number_set (symbol *sym, int user_number, location loc);
  
  
 +
 +/*------------------.
 +| Special symbols.  |
 +`------------------*/
 +
  /** The error token. */
  extern symbol *errtoken;
  /** The token for unknown tokens.  */
@@@ -231,30 -197,25 +237,30 @@@ typedef struct 
    /** The key, name of the semantic type.  */
    uniqstr tag;
  
 -  /** Any \c %destructor declared for this semantic type.  */
 -  code_props destructor;
 -  /** Any \c %printer declared for this semantic type.  */
 -  code_props printer;
 +  /** The location of its first occurence.  */
 +  location location;
 +
 +  /** Its status : "undeclared", "used" or "declared".
 +      It cannot be "needed".  */
 +  status status;
 +
 +  /** Any \c %destructor and %printer declared for this
 +      semantic type.  */
 +  code_props props[CODE_PROPS_SIZE];
 +
  } semantic_type;
  
  /** Fetch (or create) the semantic type associated to KEY.  */
 -semantic_type *semantic_type_from_uniqstr (const uniqstr key);
 +semantic_type *semantic_type_from_uniqstr (const uniqstr key,
 +                                           const location *loc);
  
  /** Fetch (or create) the semantic type associated to KEY.  */
 -semantic_type *semantic_type_get (const char *key);
 +semantic_type *semantic_type_get (const char *key, const location *loc);
  
 -/** Set the \c destructor associated with \c type.  */
 -void semantic_type_destructor_set (semantic_type *type,
 -                                   code_props const *destructor);
 -
 -/** Set the \c printer associated with \c type.  */
 -void semantic_type_printer_set (semantic_type *type,
 -                                code_props const *printer);
 +/** Set the \c destructor or \c printer associated with \c type.  */
 +void semantic_type_code_props_set (semantic_type *type,
 +                                   code_props_type kind,
 +                                   code_props const *code);
  
  /*----------------------------------.
  | Symbol and semantic type tables.  |
@@@ -277,4 -238,19 +283,4 @@@ void symbols_check_defined (void)
     #token_translations.  */
  void symbols_pack (void);
  
 -
 -/*---------------------------------------.
 -| Default %destructor's and %printer's.  |
 -`---------------------------------------*/
 -
 -/** Set the default \c \%destructor for tagged values.  */
 -void default_tagged_destructor_set (code_props const *destructor);
 -/** Set the default \c \%destructor for tagless values.  */
 -void default_tagless_destructor_set (code_props const *destructor);
 -
 -/** Set the default \c \%printer for tagged values.  */
 -void default_tagged_printer_set (code_props const *printer);
 -/** Set the default \c \%printer for tagless values.  */
 -void default_tagless_printer_set (code_props const *printer);
 -
  #endif /* !SYMTAB_H_ */
diff --combined src/system.h
index 5613a92f711777a5ac9fb96ebd37b2ac3d5db392,06fd0f0a9d578901a14b14a3e4804dc4f660142d..1d0af8fabddb6e7b5c10678dc1288de5c9abd369
     along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
  
  #ifndef BISON_SYSTEM_H
 -# define BISON_SYSTEM_H
 +#define BISON_SYSTEM_H
  
  /* flex 2.5.31 gratutiously defines macros like INT8_MIN.  But this
     runs afoul of pre-C99 compilers that have <inttypes.h> or
     <stdint.h>, which are included below if available.  It also runs
     afoul of pre-C99 compilers that define these macros in <limits.h>.  */
 -# if ! defined __STDC_VERSION__ || __STDC_VERSION__ < 199901
 -#  undef INT8_MIN
 -#  undef INT16_MIN
 -#  undef INT32_MIN
 -#  undef INT8_MAX
 -#  undef INT16_MAX
 -#  undef UINT8_MAX
 -#  undef INT32_MAX
 -#  undef UINT16_MAX
 -#  undef UINT32_MAX
 -# endif
 -
 -# include <limits.h>
 -# include <stddef.h>
 -# include <stdlib.h>
 -# include <string.h>
 -
 -# if HAVE_SYS_TYPES_H
 -#  include <sys/types.h>
 -# endif
 -
 -# include <unistd.h>
 -# include <inttypes.h>
 -
 -# ifndef UINTPTR_MAX
 +#if ! defined __STDC_VERSION__ || __STDC_VERSION__ < 199901
 +# undef INT8_MIN
 +# undef INT16_MIN
 +# undef INT32_MIN
 +# undef INT8_MAX
 +# undef INT16_MAX
 +# undef UINT8_MAX
 +# undef INT32_MAX
 +# undef UINT16_MAX
 +# undef UINT32_MAX
 +#endif
 +
 +#include <limits.h>
 +#include <stddef.h>
 +#include <stdlib.h>
 +#include <string.h>
 +
 +#define ARRAY_CARDINALITY(Array) (sizeof (Array) / sizeof *(Array))
 +#define STREQ(L, R)  (strcmp(L, R) == 0)
 +#define STRNEQ(L, R) (!STREQ(L, R))
 +
 +/* Just like strncmp, but the second argument must be a literal string
 +   and you don't specify the length.  */
 +#define STRNCMP_LIT(S, Literal)                         \
 +  strncmp (S, "" Literal "", sizeof (Literal) - 1)
 +
 +/* Whether Literal is a prefix of S.  */
 +#define STRPREFIX_LIT(Literal, S)               \
 +  (STRNCMP_LIT (S, Literal) == 0)
 +
 +#if HAVE_SYS_TYPES_H
 +# include <sys/types.h>
 +#endif
 +
 +#include <unistd.h>
 +#include <inttypes.h>
 +
 +#ifndef UINTPTR_MAX
  /* This isn't perfect, but it's good enough for Bison, which needs
     only to hash pointers.  */
  typedef size_t uintptr_t;
 -# endif
 +#endif
  
  // Version mismatch.
 -# define EX_MISMATCH 63
 +#define EX_MISMATCH 63
  
  /*---------.
  | Gnulib.  |
  `---------*/
  
 -# include <unlocked-io.h>
 -# include <verify.h>
 -# include <xalloc.h>
 +#include <unlocked-io.h>
 +#include <verify.h>
 +#include <xalloc.h>
  
  
  /*-----------------.
     and safer logic than it would for users.  Due to the overhead of M4,
     suppressing Code is unlikely to offer any significant improvement in
     Bison's performance anyway.  */
 -# define PACIFY_CC(Code) Code
 +#define PACIFY_CC(Code) Code
  
 -# ifndef __attribute__
 +#ifndef __attribute__
  /* This feature is available in gcc versions 2.5 and later.  */
 -#  if (! defined __GNUC__ || __GNUC__ < 2 \
 +# if (! defined __GNUC__ || __GNUC__ < 2 \
         || (__GNUC__ == 2 && __GNUC_MINOR__ < 5))
 -#   define __attribute__(Spec) /* empty */
 -#  endif
 +#  define __attribute__(Spec) /* empty */
  # endif
 +#endif
  
  /* The __-protected variants of `format' and `printf' attributes
     are accepted by gcc versions 2.6.4 (effectively 2.7) and later.  */
 -# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
 -#  define __format__ format
 -#  define __printf__ printf
 -# endif
 +#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
 +# define __format__ format
 +# define __printf__ printf
 +#endif
  
 -# ifndef ATTRIBUTE_NORETURN
 -#  define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
 -# endif
 +#ifndef ATTRIBUTE_NORETURN
 +# define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
 +#endif
  
 -# ifndef ATTRIBUTE_UNUSED
 -#  define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
 -# endif
 +#ifndef ATTRIBUTE_UNUSED
 +# define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
 +#endif
  
 -# define FUNCTION_PRINT() fprintf (stderr, "%s: ", __func__)
 +#define FUNCTION_PRINT() fprintf (stderr, "%s: ", __func__)
  
  /*------.
  | NLS.  |
  `------*/
  
 -# include <locale.h>
 +#include <locale.h>
  
 -# include <gettext.h>
 -# define _(Msgid)  gettext (Msgid)
 -# define N_(Msgid) (Msgid)
 +#include <gettext.h>
 +#define _(Msgid)  gettext (Msgid)
 +#define N_(Msgid) (Msgid)
  
  
  /*-----------.
  | Booleans.  |
  `-----------*/
  
 -# include <stdbool.h>
 +#include <stdbool.h>
  
  
  
     For now, we use assert but we call it aver throughout Bison in case
     we later wish to try another scheme.
  */
 -# include <assert.h>
 -# define aver assert
 +#include <assert.h>
 +#define aver assert
  
  
  /*-----------.
  | Obstacks.  |
  `-----------*/
  
 -# define obstack_chunk_alloc xmalloc
 -# define obstack_chunk_free  free
 -# include <obstack.h>
 +#define obstack_chunk_alloc xmalloc
 +#define obstack_chunk_free  free
 +#include <obstack.h>
  
 -# define obstack_sgrow(Obs, Str)                \
 +#define obstack_sgrow(Obs, Str) \
    obstack_grow (Obs, Str, strlen (Str))
  
 -# define obstack_fgrow1(Obs, Format, Arg1)      \
 +#define obstack_fgrow1(Obs, Format, Arg1)       \
do {                                            \
-   char buf[4096];                               \
-   sprintf (buf, Format, Arg1);                  \
-   obstack_grow (Obs, buf, strlen (buf));        \
- } while (0)
  do {                                          \
+     char buf[4096];                             \
+     sprintf (buf, Format, Arg1);                \
+     obstack_grow (Obs, buf, strlen (buf));      \
  } while (0)
  
 -# define obstack_fgrow2(Obs, Format, Arg1, Arg2)        \
 -  do {                                                  \
 -    char buf[4096];                                     \
 -    sprintf (buf, Format, Arg1, Arg2);                  \
 -    obstack_grow (Obs, buf, strlen (buf));              \
 +#define obstack_fgrow2(Obs, Format, Arg1, Arg2) \
- do {                                            \
-   char buf[4096];                               \
-   sprintf (buf, Format, Arg1, Arg2);            \
-   obstack_grow (Obs, buf, strlen (buf));        \
- } while (0)
++  do {                                          \
++    char buf[4096];                             \
++    sprintf (buf, Format, Arg1, Arg2);          \
++    obstack_grow (Obs, buf, strlen (buf));      \
+   } while (0)
  
 -# define obstack_fgrow3(Obs, Format, Arg1, Arg2, Arg3)  \
 +#define obstack_fgrow3(Obs, Format, Arg1, Arg2, Arg3)   \
do {                                                    \
-   char buf[4096];                                       \
-   sprintf (buf, Format, Arg1, Arg2, Arg3);              \
-   obstack_grow (Obs, buf, strlen (buf));                \
- } while (0)
  do {                                                  \
+     char buf[4096];                                     \
+     sprintf (buf, Format, Arg1, Arg2, Arg3);            \
+     obstack_grow (Obs, buf, strlen (buf));              \
  } while (0)
  
 -# define obstack_fgrow4(Obs, Format, Arg1, Arg2, Arg3, Arg4)    \
 +#define obstack_fgrow4(Obs, Format, Arg1, Arg2, Arg3, Arg4)     \
- do {                                                            \
-   char buf[4096];                                               \
-   sprintf (buf, Format, Arg1, Arg2, Arg3, Arg4);                \
-   obstack_grow (Obs, buf, strlen (buf));                        \
- } while (0)
+   do {                                                          \
+     char buf[4096];                                             \
+     sprintf (buf, Format, Arg1, Arg2, Arg3, Arg4);              \
+     obstack_grow (Obs, buf, strlen (buf));                      \
+   } while (0)
+ /* Output Str escaped for our postprocessing (i.e., escape M4 special
+    characters).
+    For instance "[foo]" -> "@{foo@}", "$$" -> "$][$][". */
+ # define obstack_escape(Obs, Str)                       \
+   do {                                                  \
 -    char const *p;                                      \
 -    for (p = Str; *p; p++)                              \
 -      switch (*p)                                       \
++    char const *p__;                                    \
++    for (p__ = Str; *p__; p__++)                        \
++      switch (*p__)                                     \
+         {                                               \
+         case '$': obstack_sgrow (Obs, "$]["); break;    \
+         case '@': obstack_sgrow (Obs, "@@" ); break;    \
+         case '[': obstack_sgrow (Obs, "@{" ); break;    \
+         case ']': obstack_sgrow (Obs, "@}" ); break;    \
 -        default:  obstack_1grow (Obs, *p   ); break;    \
++        default:  obstack_1grow (Obs, *p__ ); break;    \
+         }                                               \
+   } while (0)
+ /* Output Str both quoted for M4 (i.e., embed in [[...]]), and escaped
+    for our postprocessing (i.e., escape M4 special characters).  If
+    Str is empty (or NULL), output "[]" instead of "[[]]" as it make M4
+    programming easier (m4_ifval can be used).
+    For instance "[foo]" -> "[[@{foo@}]]", "$$" -> "[[$][$][]]". */
+ # define obstack_quote(Obs, Str)                \
+   do {                                          \
+     char const* obstack_quote_p = Str;          \
+     if (obstack_quote_p && obstack_quote_p[0])  \
+       {                                         \
+         obstack_sgrow (Obs, "[[");              \
+         obstack_escape (Obs, obstack_quote_p);  \
+         obstack_sgrow (Obs, "]]");              \
+       }                                         \
+     else                                        \
+       obstack_sgrow (Obs, "[]");                \
+   } while (0)
  
  
  
  | Extensions to use for the output files.  |
  `-----------------------------------------*/
  
 -# ifndef OUTPUT_EXT
 -#  define OUTPUT_EXT ".output"
 -# endif
 +#ifndef OUTPUT_EXT
 +# define OUTPUT_EXT ".output"
 +#endif
  
 -# ifndef TAB_EXT
 -#  define TAB_EXT ".tab"
 -# endif
 +#ifndef TAB_EXT
 +# define TAB_EXT ".tab"
 +#endif
  
- #ifndef DEFAULT_TMPDIR
- # define DEFAULT_TMPDIR "/tmp"
- #endif
  
  
  /*---------------------.
  | Free a linked list.  |
  `---------------------*/
  
 -# define LIST_FREE(Type, List)                  \
 -  do {                                          \
 -    Type *_node, *_next;                        \
 -    for (_node = List; _node; _node = _next)    \
 -      {                                         \
 -        _next = _node->next;                    \
 -        free (_node);                           \
 -      }                                         \
 -  } while (0)
 +#define LIST_FREE(Type, List)                   \
 +do {                                            \
 +  Type *_node, *_next;                          \
 +  for (_node = List; _node; _node = _next)      \
 +    {                                           \
 +      _next = _node->next;                      \
 +      free (_node);                             \
 +    }                                           \
 +} while (0)
  
  
  /*---------------------------------------------.
diff --combined tests/actions.at
index 120c40126da422d9e00a65519a28541345ad91ac,8232a00780284ddd523eb1ee6d104836ce391b0c..bde0961ba2e90333b967403f604ba0fe8415ddfc
@@@ -1,4 -1,4 +1,4 @@@
 -# Executing Actions.                               -*- Autotest -*-
 +e# Executing Actions.                               -*- Autotest -*-
  
  # Copyright (C) 2001-2012 Free Software Foundation, Inc.
  
@@@ -30,7 -30,7 +30,7 @@@ AT_SETUP([Mid-rule actions]
  
  AT_BISON_OPTION_PUSHDEFS
  AT_DATA_GRAMMAR([[input.y]],
 -[[%error-verbose
 +[[%define parse.error verbose
  %debug
  %{
  ]AT_YYERROR_DECLARE[
@@@ -80,7 -80,7 +80,7 @@@ AT_SETUP([Exotic Dollars]
  
  AT_BISON_OPTION_PUSHDEFS
  AT_DATA_GRAMMAR([[input.y]],
 -[[%error-verbose
 +[[%define parse.error verbose
  %debug
  %{
  ]AT_YYERROR_DECLARE[
@@@ -136,7 -136,7 +136,7 @@@ AT_PARSER_CHECK([./input], 0
  AT_DATA_GRAMMAR([[input.y]],
  [[
  %{
 -#include <stdio.h>
 +# include <stdio.h>
  ]AT_YYERROR_DECLARE[
  ]AT_YYLEX_DECLARE[
    typedef struct { int val; } stype;
@@@ -264,7 -264,7 +264,7 @@@ input
        V(input, $$, @$, ": /* Nothing */\n");
      }
  | line input /* Right recursive to load the stack so that popping at
 -              END can be exercised.  */
 +                END can be exercised.  */
      {
        $$ = 2;
        V(input, $$, @$, ": ");
@@@ -561,7 -561,7 +561,7 @@@ m4_define([AT_CHECK_PRINTER_AND_DESTRUC
  
  $3
  _AT_CHECK_PRINTER_AND_DESTRUCTOR($[1], $[2], $[3], $[4],
 -[%error-verbose
 +[%define parse.error verbose
  %debug
  %verbose
  %locations
@@@ -592,7 -592,7 +592,7 @@@ AT_CHECK_PRINTER_AND_DESTRUCTOR([%glr-p
  AT_SETUP([Default tagless %printer and %destructor])
  AT_BISON_OPTION_PUSHDEFS([%locations])
  AT_DATA_GRAMMAR([[input.y]],
 -[[%error-verbose
 +[[%define parse.error verbose
  %debug
  %locations
  %initial-action {
@@@ -646,10 -646,7 +646,10 @@@ main (void
  }
  ]])
  
 -AT_BISON_CHECK([-o input.c input.y])
 +AT_BISON_CHECK([-o input.c input.y], [], [],
 +[[input.y:27.3-5: warning: useless %destructor for type <*> [-Wother]
 +input.y:27.3-5: warning: useless %printer for type <*> [-Wother]
 +]])
  AT_COMPILE([input])
  AT_PARSER_CHECK([./input], 1,
  [[<> destructor for 'd' @ 4.
@@@ -697,7 -694,7 +697,7 @@@ AT_CLEANU
  AT_SETUP([Default tagged and per-type %printer and %destructor])
  AT_BISON_OPTION_PUSHDEFS
  AT_DATA_GRAMMAR([[input.y]],
 -[[%error-verbose
 +[[%define parse.error verbose
  %debug
  
  %{
@@@ -761,10 -758,7 +761,10 @@@ main (void
  }
  ]])
  
 -AT_BISON_CHECK([-o input.c input.y])
 +AT_BISON_CHECK([-o input.c input.y], [], [],
 +[[input.y:22.3-4: warning: useless %destructor for type <> [-Wother]
 +input.y:22.3-4: warning: useless %printer for type <> [-Wother]
 +]])
  AT_COMPILE([input])
  AT_PARSER_CHECK([./input], 1,
  [[<*>/<field2>/e destructor.
@@@ -823,16 -817,16 +823,16 @@@ AT_CLEANU
  
  AT_SETUP([Default %printer and %destructor for user-defined end token])
  
 -# _AT_CHECK_DEFAULT_PRINTER_AND_DESTRUCTOR_FOR_END_TOKEN(TYPED)
 -# -------------------------------------------------------------
 -m4_define([_AT_CHECK_DEFAULT_PRINTER_AND_DESTRUCTOR_FOR_END_TOKEN],
 +# AT_TEST(TYPED)
 +# --------------
 +m4_pushdef([AT_TEST],
  [m4_if($1, 0,
    [m4_pushdef([kind], []) m4_pushdef([not_kind], [*])],
    [m4_pushdef([kind], [*]) m4_pushdef([not_kind], [])])
  
  AT_BISON_OPTION_PUSHDEFS([%locations])
  AT_DATA_GRAMMAR([[input]]$1[[.y]],
 -[[%error-verbose
 +[[%define parse.error verbose
  %debug
  %locations
  %initial-action {
@@@ -897,17 -891,8 +897,17 @@@ main (void
  ]])
  AT_BISON_OPTION_POPDEFS
  
 -AT_BISON_CHECK([-o input$1.c input$1.y])
 +AT_BISON_CHECK([-o input$1.c input$1.y], [], [],
 +[m4_if([$1], [0],
 +[[input0.y:27.3-5: warning: useless %destructor for type <*> [-Wother]
 +input0.y:27.3-5: warning: useless %printer for type <*> [-Wother]
 +]],
 +[[input1.y:27.3-4: warning: useless %destructor for type <> [-Wother]
 +input1.y:27.3-4: warning: useless %printer for type <> [-Wother]
 +]])])
 +
  AT_COMPILE([input$1])
 +
  AT_PARSER_CHECK([./input$1], 0,
  [[<]]kind[[> for 'E' @ 1.
  <]]kind[[> for 'S' @ 1.
@@@ -930,10 -915,8 +930,10 @@@ m4_popdef([kind]
  m4_popdef([not_kind])
  ])
  
 -_AT_CHECK_DEFAULT_PRINTER_AND_DESTRUCTOR_FOR_END_TOKEN(0)
 -_AT_CHECK_DEFAULT_PRINTER_AND_DESTRUCTOR_FOR_END_TOKEN(1)
 +AT_TEST(0)
 +AT_TEST(1)
 +
 +m4_popdef([AT_TEST])
  
  AT_CLEANUP
  
@@@ -993,10 -976,7 +993,10 @@@ main (void
  ]])
  AT_BISON_OPTION_POPDEFS
  
 -AT_BISON_CHECK([-o input.c input.y])
 +AT_BISON_CHECK([-o input.c input.y], [], [],
 +[[input.y:21.6-8: warning: useless %destructor for type <*> [-Wother]
 +input.y:21.6-8: warning: useless %printer for type <*> [-Wother]
 +]])
  AT_COMPILE([input])
  AT_PARSER_CHECK([./input], [1], [],
  [[Starting parse
@@@ -1095,10 -1075,7 +1095,10 @@@ main (void
  ]])
  AT_BISON_OPTION_POPDEFS
  
 -AT_BISON_CHECK([-o input.c input.y])
 +AT_BISON_CHECK([-o input.c input.y], [], [],
 +[[input.y:22.3-4: warning: useless %destructor for type <> [-Wother]
 +input.y:22.3-4: warning: useless %printer for type <> [-Wother]
 +]])
  AT_COMPILE([input])
  
  AT_CLEANUP
@@@ -1155,10 -1132,8 +1155,10 @@@ main (void
  AT_BISON_OPTION_POPDEFS
  
  AT_BISON_CHECK([-o input.c input.y], 0,,
 -[[input.y:33.3-23: warning: unset value: $$
 -input.y:30.3-35.37: warning: unused value: $3
 +[[input.y:24.70-72: warning: useless %destructor for type <*> [-Wother]
 +input.y:24.70-72: warning: useless %printer for type <*> [-Wother]
 +input.y:33.3-23: warning: unset value: $$ [-Wother]
 +input.y:30.3-35.37: warning: unused value: $3 [-Wother]
  ]])
  
  AT_COMPILE([input])
@@@ -1255,6 -1230,143 +1255,143 @@@ AT_CHECK_ACTION_LOCATIONS([[%destructor
  AT_CHECK_ACTION_LOCATIONS([[%printer]])
  
  
+ ## ------------------------- ##
+ ## Qualified $$ in actions.  ##
+ ## ------------------------- ##
+ # Check that we can used qualified $$ (v.g., $<type>$) not only in
+ # rule actions, but also where $$ is valid: %printer and %destructor.
+ #
+ # FIXME: Not actually checking %desctructor, but it's the same code as
+ # %printer...
+ #
+ # To do that, use a semantic value that has two fields (sem_type),
+ # declare symbols to have only one of these types (INT, float), and
+ # use $<type>$ to get the other one.  Including for symbols that are
+ # not typed (UNTYPED).
+ m4_pushdef([AT_TEST],
+ [AT_SETUP([[Qualified $$ in actions: $1]])
+ AT_BISON_OPTION_PUSHDEFS([%locations %skeleton "$1"])
+ AT_DATA_GRAMMAR([[input.y]],
+ [[%skeleton "$1"
+ %defines   // FIXME: Mandated by lalr1.cc in Bison 2.6.
+ %locations // FIXME: Mandated by lalr1.cc in Bison 2.6.
+ %debug
+ %code requires
+ {
+ # include <stdio.h>
+   typedef struct sem_type
+   {
+     int ival;
+     float fval;
+   } sem_type;
+ # define YYSTYPE sem_type
+ #ifdef __cplusplus
+ # include <iostream>
+   static void
+   report (std::ostream& yyo, int ival, float fval)
+   {
+     yyo << "ival: " << ival << ", fval: " <<  fval;
+   }
+ #else
+   static void
+   report (FILE* yyo, int ival, float fval)
+   {
+     fprintf (yyo, "ival: %d, fval: %1.1f", ival, fval);
+   }
+ #endif
+ }
+ %code
+ {
+   ]AT_YYERROR_DECLARE[
+   ]AT_YYLEX_DECLARE[
+ }
+ %token UNTYPED
+ %token <ival> INT
+ %type <fval> float
+ %printer { report (yyo, $$,       $<fval>$); } <ival>;
+ %printer { report (yyo, $<ival>$, $$      ); } <fval>;
+ %printer { report (yyo, $<ival>$, $<fval>$); } <>;
+ ]AT_SKEL_CC_IF([[
+ /* The lalr1.cc skeleton, for backward compatibility, defines
+    a constructor for position that initializes the filename.  The
+    glr.cc skeleton does not (and in fact cannot: location/position
+    are stored in a union, from which objects with constructors are
+    excluded in C++). */
+ %initial-action {
+   @$.initialize ();
+ }
+ ]])[
+ %initial-action
+ {
+   $<ival>$ = 42;
+   $<fval>$ = 4.2;
+ }
+ %%
+ float: UNTYPED INT
+ {
+   $$       = $<fval>1 + $<fval>2;
+   $<ival>$ = $<ival>1 + $][2;
+ };
+ %%
+ ]AT_YYERROR_DEFINE[
+ ]AT_YYLEX_DEFINE(AT_SKEL_CC_IF([[{yy::parser::token::UNTYPED,
+                                  yy::parser::token::INT,
+                                   EOF}]],
+                                [[{UNTYPED, INT, EOF}]]),
+                  [AT_VAL.ival = toknum * 10; AT_VAL.fval = toknum / 10.0;])[
+ int
+ main (void)
+ {]AT_SKEL_CC_IF([[
+   yy::parser p;
+   p.set_debug_level(1);
+   return p.parse ();]], [[
+   yydebug = 1;
+   return yyparse ();]])[
+ }
+ ]])
+ AT_FULL_COMPILE([[input]])
+ AT_PARSER_CHECK([./input], 0, [], [stderr])
+ # Don't be too picky on the traces, GLR is not exactly the same.  Keep
+ # only the lines from the printer.
+ #
+ # Don't care about locations.  FIXME: remove their removal when Bison
+ # supports C++ without locations.
+ AT_CHECK([[sed -ne 's/([-0-9.]*: /(/;/ival:/p' stderr]], 0,
+ [[Reading a token: Next token is token UNTYPED (ival: 10, fval: 0.1)
+ Shifting token UNTYPED (ival: 10, fval: 0.1)
+ Reading a token: Next token is token INT (ival: 20, fval: 0.2)
+ Shifting token INT (ival: 20, fval: 0.2)
+    $][1 = token UNTYPED (ival: 10, fval: 0.1)
+    $][2 = token INT (ival: 20, fval: 0.2)
+ -> $$ = nterm float (ival: 30, fval: 0.3)
+ Cleanup: popping nterm float (ival: 30, fval: 0.3)
+ ]])
+ AT_BISON_OPTION_POPDEFS
+ AT_CLEANUP
+ ])
+ AT_TEST([yacc.c])
+ AT_TEST([glr.c])
+ AT_TEST([lalr1.cc])
+ AT_TEST([glr.cc])
+ m4_popdef([AT_TEST])
  ## ----------------------------------------------- ##
  ## Fix user actions without a trailing semicolon.  ##
  ## ----------------------------------------------- ##
@@@ -1270,37 -1382,37 +1407,37 @@@ AT_DATA([input.y]
  start: test2 test1 test0 testc;
  
  test2
 -: 'a' { semi;                 /* TEST:N:2 */ }
 -| 'b' { if (0) {no_semi}      /* TEST:N:2 */ }
 -| 'c' { if (0) {semi;}                /* TEST:N:2 */ }
 -| 'd' { semi;   no_semi               /* TEST:Y:2 */ }
 -| 'e' { semi(); no_semi()     /* TEST:Y:2 */ }
 -| 'f' { semi[]; no_semi[]     /* TEST:Y:2 */ }
 -| 'g' { semi++; no_semi++     /* TEST:Y:2 */ }
 -| 'h' { {no_semi} no_semi     /* TEST:Y:2 */ }
 -| 'i' { {semi;}   no_semi     /* TEST:Y:2 */ }
 +: 'a' { semi;                   /* TEST:N:2 */ }
 +| 'b' { if (0) {no_semi}        /* TEST:N:2 */ }
 +| 'c' { if (0) {semi;}          /* TEST:N:2 */ }
 +| 'd' { semi;   no_semi         /* TEST:Y:2 */ }
 +| 'e' { semi(); no_semi()       /* TEST:Y:2 */ }
 +| 'f' { semi[]; no_semi[]       /* TEST:Y:2 */ }
 +| 'g' { semi++; no_semi++       /* TEST:Y:2 */ }
 +| 'h' { {no_semi} no_semi       /* TEST:Y:2 */ }
 +| 'i' { {semi;}   no_semi       /* TEST:Y:2 */ }
  ;
  test1
 -  : 'a' { semi;                       // TEST:N:1 ;
 -} | 'b' { if (0) {no_semi}    // TEST:N:1 ;
 -} | 'c' { if (0) {semi;}      // TEST:N:1 ;
 -} | 'd' { semi;   no_semi     // TEST:Y:1 ;
 -} | 'e' { semi(); no_semi()   // TEST:Y:1 ;
 -} | 'f' { semi[]; no_semi[]   // TEST:Y:1 ;
 -} | 'g' { semi++; no_semi++   // TEST:Y:1 ;
 -} | 'h' { {no_semi} no_semi   // TEST:Y:1 ;
 -} | 'i' { {semi;}   no_semi   // TEST:Y:1 ;
 +  : 'a' { semi;                 // TEST:N:1 ;
 +} | 'b' { if (0) {no_semi}      // TEST:N:1 ;
 +} | 'c' { if (0) {semi;}        // TEST:N:1 ;
 +} | 'd' { semi;   no_semi       // TEST:Y:1 ;
 +} | 'e' { semi(); no_semi()     // TEST:Y:1 ;
 +} | 'f' { semi[]; no_semi[]     // TEST:Y:1 ;
 +} | 'g' { semi++; no_semi++     // TEST:Y:1 ;
 +} | 'h' { {no_semi} no_semi     // TEST:Y:1 ;
 +} | 'i' { {semi;}   no_semi     // TEST:Y:1 ;
  } ;
  test0
 -  : 'a' { semi;                       // TEST:N:1 {}
 -} | 'b' { if (0) {no_semi}    // TEST:N:1 {}
 -} | 'c' { if (0) {semi;}      // TEST:N:1 {}
 -} | 'd' { semi;   no_semi     // TEST:Y:1 {}
 -} | 'e' { semi(); no_semi()   // TEST:Y:1 {}
 -} | 'f' { semi[]; no_semi[]   // TEST:Y:1 {}
 -} | 'g' { semi++; no_semi++   // TEST:Y:1 {}
 -} | 'h' { {no_semi} no_semi   // TEST:Y:1 {}
 -} | 'i' { {semi;}   no_semi   // TEST:Y:1 {}
 +  : 'a' { semi;                 // TEST:N:1 {}
 +} | 'b' { if (0) {no_semi}      // TEST:N:1 {}
 +} | 'c' { if (0) {semi;}        // TEST:N:1 {}
 +} | 'd' { semi;   no_semi       // TEST:Y:1 {}
 +} | 'e' { semi(); no_semi()     // TEST:Y:1 {}
 +} | 'f' { semi[]; no_semi[]     // TEST:Y:1 {}
 +} | 'g' { semi++; no_semi++     // TEST:Y:1 {}
 +} | 'h' { {no_semi} no_semi     // TEST:Y:1 {}
 +} | 'i' { {semi;}   no_semi     // TEST:Y:1 {}
  } ;
  
  testc
@@@ -1317,42 -1429,42 +1454,42 @@@ string;"
  AT_BISON_OPTION_POPDEFS
  
  AT_BISON_CHECK([[-o input.c input.y]], [0], [],
 -[[input.y:8.48: warning: a ';' might be needed at the end of action code
 -input.y:8.48: warning: future versions of Bison will not add the ';'
 -input.y:9.48: warning: a ';' might be needed at the end of action code
 -input.y:9.48: warning: future versions of Bison will not add the ';'
 -input.y:10.48: warning: a ';' might be needed at the end of action code
 -input.y:10.48: warning: future versions of Bison will not add the ';'
 -input.y:11.48: warning: a ';' might be needed at the end of action code
 -input.y:11.48: warning: future versions of Bison will not add the ';'
 -input.y:12.48: warning: a ';' might be needed at the end of action code
 -input.y:12.48: warning: future versions of Bison will not add the ';'
 -input.y:13.48: warning: a ';' might be needed at the end of action code
 -input.y:13.48: warning: future versions of Bison will not add the ';'
 -input.y:20.1: warning: a ';' might be needed at the end of action code
 -input.y:20.1: warning: future versions of Bison will not add the ';'
 -input.y:21.1: warning: a ';' might be needed at the end of action code
 -input.y:21.1: warning: future versions of Bison will not add the ';'
 -input.y:22.1: warning: a ';' might be needed at the end of action code
 -input.y:22.1: warning: future versions of Bison will not add the ';'
 -input.y:23.1: warning: a ';' might be needed at the end of action code
 -input.y:23.1: warning: future versions of Bison will not add the ';'
 -input.y:24.1: warning: a ';' might be needed at the end of action code
 -input.y:24.1: warning: future versions of Bison will not add the ';'
 -input.y:25.1: warning: a ';' might be needed at the end of action code
 -input.y:25.1: warning: future versions of Bison will not add the ';'
 -input.y:31.1: warning: a ';' might be needed at the end of action code
 -input.y:31.1: warning: future versions of Bison will not add the ';'
 -input.y:32.1: warning: a ';' might be needed at the end of action code
 -input.y:32.1: warning: future versions of Bison will not add the ';'
 -input.y:33.1: warning: a ';' might be needed at the end of action code
 -input.y:33.1: warning: future versions of Bison will not add the ';'
 -input.y:34.1: warning: a ';' might be needed at the end of action code
 -input.y:34.1: warning: future versions of Bison will not add the ';'
 -input.y:35.1: warning: a ';' might be needed at the end of action code
 -input.y:35.1: warning: future versions of Bison will not add the ';'
 -input.y:36.1: warning: a ';' might be needed at the end of action code
 -input.y:36.1: warning: future versions of Bison will not add the ';'
 +[[input.y:8.48: warning: a ';' might be needed at the end of action code [-Wother]
 +input.y:8.48: warning: future versions of Bison will not add the ';' [-Wother]
 +input.y:9.48: warning: a ';' might be needed at the end of action code [-Wother]
 +input.y:9.48: warning: future versions of Bison will not add the ';' [-Wother]
 +input.y:10.48: warning: a ';' might be needed at the end of action code [-Wother]
 +input.y:10.48: warning: future versions of Bison will not add the ';' [-Wother]
 +input.y:11.48: warning: a ';' might be needed at the end of action code [-Wother]
 +input.y:11.48: warning: future versions of Bison will not add the ';' [-Wother]
 +input.y:12.48: warning: a ';' might be needed at the end of action code [-Wother]
 +input.y:12.48: warning: future versions of Bison will not add the ';' [-Wother]
 +input.y:13.48: warning: a ';' might be needed at the end of action code [-Wother]
 +input.y:13.48: warning: future versions of Bison will not add the ';' [-Wother]
 +input.y:20.1: warning: a ';' might be needed at the end of action code [-Wother]
 +input.y:20.1: warning: future versions of Bison will not add the ';' [-Wother]
 +input.y:21.1: warning: a ';' might be needed at the end of action code [-Wother]
 +input.y:21.1: warning: future versions of Bison will not add the ';' [-Wother]
 +input.y:22.1: warning: a ';' might be needed at the end of action code [-Wother]
 +input.y:22.1: warning: future versions of Bison will not add the ';' [-Wother]
 +input.y:23.1: warning: a ';' might be needed at the end of action code [-Wother]
 +input.y:23.1: warning: future versions of Bison will not add the ';' [-Wother]
 +input.y:24.1: warning: a ';' might be needed at the end of action code [-Wother]
 +input.y:24.1: warning: future versions of Bison will not add the ';' [-Wother]
 +input.y:25.1: warning: a ';' might be needed at the end of action code [-Wother]
 +input.y:25.1: warning: future versions of Bison will not add the ';' [-Wother]
 +input.y:31.1: warning: a ';' might be needed at the end of action code [-Wother]
 +input.y:31.1: warning: future versions of Bison will not add the ';' [-Wother]
 +input.y:32.1: warning: a ';' might be needed at the end of action code [-Wother]
 +input.y:32.1: warning: future versions of Bison will not add the ';' [-Wother]
 +input.y:33.1: warning: a ';' might be needed at the end of action code [-Wother]
 +input.y:33.1: warning: future versions of Bison will not add the ';' [-Wother]
 +input.y:34.1: warning: a ';' might be needed at the end of action code [-Wother]
 +input.y:34.1: warning: future versions of Bison will not add the ';' [-Wother]
 +input.y:35.1: warning: a ';' might be needed at the end of action code [-Wother]
 +input.y:35.1: warning: future versions of Bison will not add the ';' [-Wother]
 +input.y:36.1: warning: a ';' might be needed at the end of action code [-Wother]
 +input.y:36.1: warning: future versions of Bison will not add the ';' [-Wother]
  ]])
  
  AT_MATCHES_CHECK([input.c], [[/\* TEST:N:2 \*/ \}$]],       [[3]])
diff --combined tests/input.at
index 71505cf81b004b1a72feb60f309546b61b3176fd,ff1d3924d907f62413e2aa1e3f9cf23a77c8b285..d6f2084a3a43f8280da559ae7aad1cc89657fb34
@@@ -60,9 -60,9 +60,9 @@@ exp: foo { $$; } foo { $2; } fo
  AT_BISON_CHECK([input.y], [1], [],
  [[input.y:5.12-13: $$ for the midrule at $2 of 'exp' has no declared type
  input.y:5.24-25: $2 of 'exp' has no declared type
 -input.y:5.6-32: warning: type clash on default action: <bar> != <>
 -input.y:6.6-8: warning: type clash on default action: <bar> != <>
 -input.y:7.5: warning: empty rule for typed nonterminal, and no action
 +input.y:5.6-32: warning: type clash on default action: <bar> != <> [-Wother]
 +input.y:6.6-8: warning: type clash on default action: <bar> != <> [-Wother]
 +input.y:7.5: warning: empty rule for typed nonterminal, and no action [-Wother]
  ]])
  
  AT_CLEANUP
@@@ -72,6 -72,7 +72,6 @@@
  # --------------------------------
  # Generate the token, type, and destructor
  # declarations for the unused values tests.
 -
  m4_define([_AT_UNUSED_VALUES_DECLARATIONS],
  [[[%token <integer> INT;
  %type <integer> a b c d e f g h i j k l;
  
  
  # AT_CHECK_UNUSED_VALUES(DECLARATIONS_AFTER, CHECK_MIDRULE_VALUES)
 -# ------------------------------------------------------------------
 -# Generate a grammar to test unused values,
 -# compile it, run it.  If DECLARATIONS_AFTER
 -# is set, then the token, type, and destructor
 -# declarations are generated after the rules
 -# rather than before.  If CHECK_MIDRULE_VALUES
 -# is set, then --warnings=midrule-values is
 -# set.
 -
 +# ----------------------------------------------------------------
 +# Generate a grammar to test unused values, compile it, run it.  If
 +# DECLARATIONS_AFTER is set, then the token, type, and destructor
 +# declarations are generated after the rules rather than before.  If
 +# CHECK_MIDRULE_VALUES is set, then --warnings=midrule-values is set.
  m4_define([AT_CHECK_UNUSED_VALUES],
  [AT_DATA([input.y],
  m4_ifval($1, [
@@@ -113,39 -118,39 +113,39 @@@ _AT_UNUSED_VALUES_DECLARATIONS]
  )
  
  AT_BISON_CHECK(m4_ifval($2, [ --warnings=midrule-values ])[ input.y], [0], [],
 -[[input.y:11.10-32: warning: unset value: $]$[
 -input.y:11.10-32: warning: unused value: $]1[
 -input.y:11.10-32: warning: unused value: $]3[
 -input.y:11.10-32: warning: unused value: $]5[
 -input.y:12.9: warning: empty rule for typed nonterminal, and no action
 -]]m4_ifval($2, [[[input.y:13.14-20: warning: unset value: $$
 -input.y:13.26-41: warning: unset value: $$
 -]]])[[input.y:13.10-62: warning: unset value: $]$[
 -input.y:13.10-62: warning: unused value: $]3[
 -input.y:13.10-62: warning: unused value: $]5[
 -]]m4_ifval($2, [[[input.y:14.14-16: warning: unset value: $$
 -]]])[[input.y:14.10-49: warning: unset value: $]$[
 -input.y:14.10-49: warning: unused value: $]3[
 -input.y:14.10-49: warning: unused value: $]5[
 -input.y:15.10-37: warning: unset value: $]$[
 -input.y:15.10-37: warning: unused value: $]3[
 -input.y:15.10-37: warning: unused value: $]5[
 -input.y:17.10-58: warning: unset value: $]$[
 -input.y:17.10-58: warning: unused value: $]1[
 -]]m4_ifval($2, [[[input.y:17.10-58: warning: unused value: $]2[
 -]]])[[input.y:17.10-58: warning: unused value: $]3[
 -]]m4_ifval($2, [[[input.y:17.10-58: warning: unused value: $]4[
 -]]])[[input.y:17.10-58: warning: unused value: $]5[
 -input.y:18.10-72: warning: unset value: $]$[
 -input.y:18.10-72: warning: unused value: $]1[
 -input.y:18.10-72: warning: unused value: $]3[
 -]]m4_ifval($2, [[[input.y:18.10-72: warning: unused value: $]4[
 -]]])[[input.y:18.10-72: warning: unused value: $]5[
 -]]m4_ifval($2, [[[input.y:20.10-55: warning: unused value: $]3[
 -]]])[[input.y:21.10-68: warning: unset value: $]$[
 -input.y:21.10-68: warning: unused value: $]1[
 -input.y:21.10-68: warning: unused value: $]2[
 -]]m4_ifval($2, [[[input.y:21.10-68: warning: unused value: $]4[
 +[[input.y:11.10-32: warning: unset value: $]$[ [-Wother]
 +input.y:11.10-32: warning: unused value: $]1[ [-Wother]
 +input.y:11.10-32: warning: unused value: $]3[ [-Wother]
 +input.y:11.10-32: warning: unused value: $]5[ [-Wother]
 +input.y:12.9: warning: empty rule for typed nonterminal, and no action [-Wother]
 +]]m4_ifval($2, [[[input.y:13.14-20: warning: unset value: $$ [-Wmidrule-values]
 +input.y:13.26-41: warning: unset value: $$ [-Wmidrule-values]
 +]]])[[input.y:13.10-62: warning: unset value: $]$[ [-Wother]
 +input.y:13.10-62: warning: unused value: $]3[ [-Wother]
 +input.y:13.10-62: warning: unused value: $]5[ [-Wother]
 +]]m4_ifval($2, [[[input.y:14.14-16: warning: unset value: $$ [-Wmidrule-values]
 +]]])[[input.y:14.10-49: warning: unset value: $]$[ [-Wother]
 +input.y:14.10-49: warning: unused value: $]3[ [-Wother]
 +input.y:14.10-49: warning: unused value: $]5[ [-Wother]
 +input.y:15.10-37: warning: unset value: $]$[ [-Wother]
 +input.y:15.10-37: warning: unused value: $]3[ [-Wother]
 +input.y:15.10-37: warning: unused value: $]5[ [-Wother]
 +input.y:17.10-58: warning: unset value: $]$[ [-Wother]
 +input.y:17.10-58: warning: unused value: $]1[ [-Wother]
 +]]m4_ifval($2, [[[input.y:17.10-58: warning: unused value: $]2[ [-Wmidrule-values]
 +]]])[[input.y:17.10-58: warning: unused value: $]3[ [-Wother]
 +]]m4_ifval($2, [[[input.y:17.10-58: warning: unused value: $]4[ [-Wmidrule-values]
 +]]])[[input.y:17.10-58: warning: unused value: $]5[ [-Wother]
 +input.y:18.10-72: warning: unset value: $]$[ [-Wother]
 +input.y:18.10-72: warning: unused value: $]1[ [-Wother]
 +input.y:18.10-72: warning: unused value: $]3[ [-Wother]
 +]]m4_ifval($2, [[[input.y:18.10-72: warning: unused value: $]4[ [-Wmidrule-values]
 +]]])[[input.y:18.10-72: warning: unused value: $]5[ [-Wother]
 +]]m4_ifval($2, [[[input.y:20.10-55: warning: unused value: $]3[ [-Wmidrule-values]
 +]]])[[input.y:21.10-68: warning: unset value: $]$[ [-Wother]
 +input.y:21.10-68: warning: unused value: $]1[ [-Wother]
 +input.y:21.10-68: warning: unused value: $]2[ [-Wother]
 +]]m4_ifval($2, [[[input.y:21.10-68: warning: unused value: $]4[ [-Wmidrule-values]
  ]]]))])
  
  
@@@ -200,29 -205,29 +200,29 @@@ start: 
  ]])
  
  AT_BISON_CHECK([input.y], [1], [],
 -[[input.y:1.13-29: redeclaration for default tagged %destructor
 +[[input.y:1.13-29: %destructor redeclaration for <*>
  input.y:1.13-29: previous declaration
 -input.y:2.10-24: redeclaration for default tagged %printer
 +input.y:2.10-24: %printer redeclaration for <*>
  input.y:2.10-24: previous declaration
 -input.y:4.13-29: redeclaration for default tagged %destructor
 +input.y:4.13-29: %destructor redeclaration for <*>
  input.y:1.13-29: previous declaration
 -input.y:5.10-24: redeclaration for default tagged %printer
 +input.y:5.10-24: %printer redeclaration for <*>
  input.y:2.10-24: previous declaration
 -input.y:7.13-29: redeclaration for default tagless %destructor
 +input.y:7.13-29: %destructor redeclaration for <>
  input.y:7.13-29: previous declaration
 -input.y:8.10-24: redeclaration for default tagless %printer
 +input.y:8.10-24: %printer redeclaration for <>
  input.y:8.10-24: previous declaration
 -input.y:10.13-29: redeclaration for default tagless %destructor
 +input.y:10.13-29: %destructor redeclaration for <>
  input.y:7.13-29: previous declaration
 -input.y:11.10-24: redeclaration for default tagless %printer
 +input.y:11.10-24: %printer redeclaration for <>
  input.y:8.10-24: previous declaration
 -input.y:17.13-29: redeclaration for default tagged %destructor
 +input.y:17.13-29: %destructor redeclaration for <*>
  input.y:4.13-29: previous declaration
 -input.y:18.10-24: redeclaration for default tagged %printer
 +input.y:18.10-24: %printer redeclaration for <*>
  input.y:5.10-24: previous declaration
 -input.y:20.13-29: redeclaration for default tagless %destructor
 +input.y:20.13-29: %destructor redeclaration for <>
  input.y:10.13-29: previous declaration
 -input.y:21.10-24: redeclaration for default tagless %printer
 +input.y:21.10-24: %printer redeclaration for <>
  input.y:11.10-24: previous declaration
  ]])
  
@@@ -271,122 -276,6 +271,122 @@@ input.y:5.10-24: previous declaratio
  
  AT_CLEANUP
  
 +## ----------------------------------------------------- ##
 +## Undeclared symbols used for a printer or destructor.  ##
 +## ----------------------------------------------------- ##
 +
 +AT_SETUP([Undeclared symbols used for a printer or destructor])
 +
 +AT_DATA([[input.y]],
 +[[%printer {} foo baz
 +%destructor {} bar
 +
 +%%
 +exp: bar;
 +]])
 +
 +AT_BISON_CHECK([input.y], [1], [],
 +[[input.y:2.16-18: symbol bar is used, but is not defined as a token and has no rules
 +input.y:1.17-19: warning: symbol baz is used, but is not defined as a token and has no rules [-Wother]
 +input.y:1.13-15: warning: symbol foo is used, but is not defined as a token and has no rules [-Wother]
 +]])
 +
 +AT_CLEANUP
 +
 +
 +## ----------------------------------------------------- ##
 +## Unassociated types used for a printer or destructor.  ##
 +## ----------------------------------------------------- ##
 +
 +AT_SETUP([Unassociated types used for a printer or destructor])
 +
 +AT_DATA([[input.y]],
 +[[%token <type1> tag1
 +%type <type2> tag2
 +
 +%printer { } <type1> <type3>
 +%destructor { } <type2> <type4>
 +
 +%%
 +
 +exp: tag1 { $1; }
 +   | tag2 { $1; }
 +
 +tag2: "a" { $$; }
 +]])
 +
 +AT_BISON_CHECK([input.y], [0], [],
 +[[input.y:4.22-28: warning: type <type3> is used, but is not associated to any symbol [-Wother]
 +input.y:5.25-31: warning: type <type4> is used, but is not associated to any symbol [-Wother]
 +]])
 +
 +AT_CLEANUP
 +
 +
 +## --------------------------------- ##
 +## Useless printers or destructors.  ##
 +## --------------------------------- ##
 +
 +AT_SETUP([Useless printers or destructors])
 +
 +# AT_TEST([INPUT], [STDERR])
 +# --------------------------
 +m4_pushdef([AT_TEST],
 +[AT_DATA([[input.y]],
 +[$1
 +])
 +AT_BISON_CHECK([input.y], [0], [], [$2
 +])])
 +
 +AT_TEST([[%token <type1> token1
 +%token <type2> token2
 +%token <type3> token3
 +%token <type4> token4
 +%token <type5> token51 token52
 +%token <type6> token61 token62
 +%token <type7> token7
 +
 +%printer {} token1
 +%destructor {} token2
 +%printer {} token51
 +%destructor {} token61
 +
 +%printer {} token7
 +
 +%printer {} <type1>
 +%destructor {} <type2>
 +%printer {} <type3>
 +%destructor {} <type4>
 +
 +%printer {} <type5>
 +%destructor {} <type6>
 +
 +%destructor {} <type7>
 +
 +%%
 +exp: "a";]],
 +[[input.y:16.13-19: warning: useless %printer for type <type1> [-Wother]
 +input.y:17.16-22: warning: useless %destructor for type <type2> [-Wother]]])
 +
 +# If everybody is typed, <> is useless.
 +AT_TEST([[%type <type> exp
 +%token <type> a
 +%printer {} <> <*>
 +%%
 +exp: a;]],
 +[[input.y:3.13-14: warning: useless %printer for type <> [-Wother]]])
 +
 +# If nobody is is typed, <*> is useless.
 +AT_TEST([[%token a
 +%printer {} <> <*>
 +%%
 +exp: a;]],
 +[[input.y:2.16-18: warning: useless %printer for type <*> [-Wother]]])
 +
 +m4_popdef([AT_TEST])
 +
 +AT_CLEANUP
 +
  
  ## ---------------------------------------- ##
  ## Unused values with default %destructor.  ##
@@@ -406,9 -295,9 +406,9 @@@ tagged: { } 
  ]])
  
  AT_BISON_CHECK([input.y], [0], [],
 -[[input.y:6.8-45: warning: unset value: $$
 -input.y:6.8-45: warning: unused value: $2
 -input.y:7.6-8: warning: unset value: $$
 +[[input.y:6.8-45: warning: unset value: $$ [-Wother]
 +input.y:6.8-45: warning: unused value: $2 [-Wother]
 +input.y:7.6-8: warning: unset value: $$ [-Wother]
  ]])
  
  AT_DATA([[input.y]],
@@@ -423,8 -312,8 +423,8 @@@ tagged: { } 
  ]])
  
  AT_BISON_CHECK([input.y], [0], [],
 -[[input.y:6.8-45: warning: unused value: $4
 -input.y:8.9-11: warning: unset value: $$
 +[[input.y:6.8-45: warning: unused value: $4 [-Wother]
 +input.y:8.9-11: warning: unset value: $$ [-Wother]
  ]])
  
  AT_CLEANUP
@@@ -447,9 -336,9 +447,9 @@@ end: { }  
  ]])
  
  AT_BISON_CHECK([input.y], [0], [],
 -[[input.y:6.8-22: warning: unset value: $$
 -input.y:6.8-22: warning: unused value: $2
 -input.y:7.6-8: warning: unset value: $$
 +[[input.y:6.8-22: warning: unset value: $$ [-Wother]
 +input.y:6.8-22: warning: unused value: $2 [-Wother]
 +input.y:7.6-8: warning: unset value: $$ [-Wother]
  ]])
  
  AT_CLEANUP
@@@ -627,7 -516,7 +627,7 @@@ yylex (void
  }
  ]])
  
 -# Pacify Emacs' font-lock-mode: "
 +# Pacify Emacs'font-lock-mode: "
  
  AT_DATA([main.c],
  [[typedef int value;
@@@ -706,8 -595,8 +706,8 @@@ AT_CHECK_REQUIRE(100.0, 63
  
  AT_SETUP([String aliases for character tokens])
  
 -# Bison once thought a character token and its alias were different symbols
 -# with the same user token number.
 +# Bison once thought a character token and its alias were different
 +# symbols with the same user token number.
  
  AT_DATA_GRAMMAR([input.y],
  [[%token 'a' "a"
@@@ -751,14 -640,14 +751,14 @@@ AT_BISON_OPTION_POPDEF
  
  # POSIX Yacc accept periods, but not dashes.
  AT_BISON_CHECK([--yacc input.y], [1], [],
 -[[input.y:9.8-16: POSIX Yacc forbids dashes in symbol names: WITH-DASH
 -input.y:18.8-16: POSIX Yacc forbids dashes in symbol names: with-dash
 +[[input.y:9.8-16: POSIX Yacc forbids dashes in symbol names: WITH-DASH [-Wyacc]
 +input.y:18.8-16: POSIX Yacc forbids dashes in symbol names: with-dash [-Wyacc]
  ]])
  
  # So warn about them.
  AT_BISON_CHECK([-Wyacc input.y], [], [],
 -[[input.y:9.8-16: warning: POSIX Yacc forbids dashes in symbol names: WITH-DASH
 -input.y:18.8-16: warning: POSIX Yacc forbids dashes in symbol names: with-dash
 +[[input.y:9.8-16: warning: POSIX Yacc forbids dashes in symbol names: WITH-DASH [-Wyacc]
 +input.y:18.8-16: warning: POSIX Yacc forbids dashes in symbol names: with-dash [-Wyacc]
  ]])
  
  # Dashes are fine for GNU Bison.
@@@ -831,10 -720,10 +831,10 @@@ AT_CLEANU
  
  AT_SETUP([Unclosed constructs])
  
 -# Bison's scan-gram.l once forgot to STRING_FINISH some unclosed constructs, so
 -# they were prepended to whatever it STRING_GROW'ed next.  It also threw them
 -# away rather than returning them to the parser.  The effect was confusing
 -# subsequent error messages.
 +# Bison's scan-gram.l once forgot to STRING_FINISH some unclosed
 +# constructs, so they were prepended to whatever it STRING_GROW'ed
 +# next.  It also threw them away rather than returning them to the
 +# parser.  The effect was confusing subsequent error messages.
  
  AT_DATA([input.y],
  [[%token A "a
@@@ -876,8 -765,8 +876,8 @@@ AT_CLEANU
  
  AT_SETUP([%start after first rule])
  
 -# Bison once complained that a %start after the first rule was a redeclaration
 -# of the start symbol.
 +# Bison once complained that a %start after the first rule was a
 +# redeclaration of the start symbol.
  
  AT_DATA([input.y],
  [[%%
@@@ -926,7 -815,7 +926,7 @@@ start: %prec PREC 
  ]])
  
  AT_BISON_CHECK([[input.y]], [[0]], [],
 -[[input.y:2.8-17: warning: token for %prec is not defined: PREC
 +[[input.y:2.8-17: warning: token for %prec is not defined: PREC [-Wother]
  ]])
  
  AT_CLEANUP
@@@ -1194,17 -1083,6 +1194,17 @@@ AT_BISON_CHECK([[input.y]], [1], []
  [[input.y:1.9-34: invalid value for %define Boolean variable 'lr.keep-unreachable-states'
  ]])
  
 +AT_DATA([[input.y]],
 +[[%define namespace "foo"
 +%define api.namespace "foo"
 +%%
 +start: ;
 +]])
 +AT_BISON_CHECK([[input.y]], [1], [],
 +[[input.y:2.9-21: %define variable 'api.namespace' redefined
 +input.y:1.9-17: previous definition
 +]])
 +
  AT_DATA([[input.y]],
  [[%define foo_bar "baz"
  %%
@@@ -1263,14 -1141,14 +1263,14 @@@ m4_define([AT_CHECK_NAMESPACE_ERROR]
  AT_DATA([[input.y]],
  [[%language "C++"
  %defines
 -%define namespace "]$1["
 +%define api.namespace "]$1["
  %%
  start: ;
  ]])
  
  AT_BISON_CHECK([[input.y]], [1], [],
  [m4_foreach([b4_arg], m4_dquote(m4_shift($@)),
 -[[input.y:3.9-17: ]b4_arg[
 +[[input.y:3.9-21: ]b4_arg[
  ]])])
  ])
  
@@@ -1319,10 -1197,10 +1319,10 @@@ start: 
  AT_CHECK([[perl -e "print 'start: \'';" >> empty.y || exit 77]])
  
  AT_BISON_CHECK([empty.y], [1], [],
 -[[empty.y:2.8-9: warning: empty character literal
 -empty.y:3.8-4.0: warning: empty character literal
 +[[empty.y:2.8-9: warning: empty character literal [-Wother]
 +empty.y:3.8-4.0: warning: empty character literal [-Wother]
  empty.y:3.8-4.0: missing "'" at end of line
 -empty.y:4.8: warning: empty character literal
 +empty.y:4.8: warning: empty character literal [-Wother]
  empty.y:4.8: missing "'" at end of file
  ]])
  
@@@ -1334,10 -1212,10 +1334,10 @@@ start: 'a
  AT_CHECK([[perl -e "print 'start: \'ab';" >> two.y || exit 77]])
  
  AT_BISON_CHECK([two.y], [1], [],
 -[[two.y:2.8-11: warning: extra characters in character literal
 -two.y:3.8-4.0: warning: extra characters in character literal
 +[[two.y:2.8-11: warning: extra characters in character literal [-Wother]
 +two.y:3.8-4.0: warning: extra characters in character literal [-Wother]
  two.y:3.8-4.0: missing "'" at end of line
 -two.y:4.8-10: warning: extra characters in character literal
 +two.y:4.8-10: warning: extra characters in character literal [-Wother]
  two.y:4.8-10: missing "'" at end of file
  ]])
  
@@@ -1349,10 -1227,10 +1349,10 @@@ start: 'ab
  AT_CHECK([[perl -e "print 'start: \'abc';" >> three.y || exit 77]])
  
  AT_BISON_CHECK([three.y], [1], [],
 -[[three.y:2.8-12: warning: extra characters in character literal
 -three.y:3.8-4.0: warning: extra characters in character literal
 +[[three.y:2.8-12: warning: extra characters in character literal [-Wother]
 +three.y:3.8-4.0: warning: extra characters in character literal [-Wother]
  three.y:3.8-4.0: missing "'" at end of line
 -three.y:4.8-11: warning: extra characters in character literal
 +three.y:4.8-11: warning: extra characters in character literal [-Wother]
  three.y:4.8-11: missing "'" at end of file
  ]])
  
@@@ -1380,25 -1258,25 +1380,25 @@@ AT_CHECK([[perl -e 'print "start: \"\\\
  
  AT_BISON_CHECK([input.y], [1], [],
  [[input.y:2.9-12: invalid number after \-escape: 777
 -input.y:2.8-13: warning: empty character literal
 +input.y:2.8-13: warning: empty character literal [-Wother]
  input.y:2.16-17: invalid number after \-escape: 0
 -input.y:2.15-18: warning: empty character literal
 +input.y:2.15-18: warning: empty character literal [-Wother]
  input.y:2.21-25: invalid number after \-escape: xfff
 -input.y:2.20-26: warning: empty character literal
 +input.y:2.20-26: warning: empty character literal [-Wother]
  input.y:2.29-31: invalid number after \-escape: x0
 -input.y:2.28-32: warning: empty character literal
 +input.y:2.28-32: warning: empty character literal [-Wother]
  input.y:3.9-14: invalid number after \-escape: uffff
 -input.y:3.8-15: warning: empty character literal
 +input.y:3.8-15: warning: empty character literal [-Wother]
  input.y:3.18-23: invalid number after \-escape: u0000
 -input.y:3.17-24: warning: empty character literal
 +input.y:3.17-24: warning: empty character literal [-Wother]
  input.y:3.27-36: invalid number after \-escape: Uffffffff
 -input.y:3.26-37: warning: empty character literal
 +input.y:3.26-37: warning: empty character literal [-Wother]
  input.y:3.40-49: invalid number after \-escape: U00000000
 -input.y:3.39-50: warning: empty character literal
 +input.y:3.39-50: warning: empty character literal [-Wother]
  input.y:4.9-10: invalid character after \-escape: ' '
 -input.y:4.8-11: warning: empty character literal
 +input.y:4.8-11: warning: empty character literal [-Wother]
  input.y:4.14-15: invalid character after \-escape: A
 -input.y:4.13-16: warning: empty character literal
 +input.y:4.13-16: warning: empty character literal [-Wother]
  input.y:5.9-16: invalid character after \-escape: \t
  input.y:5.17: invalid character after \-escape: \f
  input.y:5.18: invalid character after \-escape: \0
@@@ -1443,20 -1321,20 +1443,20 @@@ foo-bar: 
  
  # -Werror is not enabled by -Wall or equivalent.
  AT_BISON_CHECK([[-Wall input.y]], [[0]], [[]],
 -[[input.y:2.1-7: warning: POSIX Yacc forbids dashes in symbol names: foo-bar
 +[[input.y:2.1-7: warning: POSIX Yacc forbids dashes in symbol names: foo-bar [-Wyacc]
  ]])
  AT_BISON_CHECK([[-W input.y]], [[0]], [[]],
 -[[input.y:2.1-7: warning: POSIX Yacc forbids dashes in symbol names: foo-bar
 +[[input.y:2.1-7: warning: POSIX Yacc forbids dashes in symbol names: foo-bar [-Wyacc]
  ]])
  AT_BISON_CHECK([[-Wno-none input.y]], [[0]], [[]],
 -[[input.y:2.1-7: warning: POSIX Yacc forbids dashes in symbol names: foo-bar
 +[[input.y:2.1-7: warning: POSIX Yacc forbids dashes in symbol names: foo-bar [-Wyacc]
  ]])
  
  # -Werror is not disabled by -Wnone or equivalent.
  AT_BISON_CHECK([[-Werror,none,yacc input.y]], [[1]], [[]], [[stderr]])
  AT_CHECK([[sed 's/^.*bison:/bison:/' stderr]], [[0]],
  [[bison: warnings being treated as errors
 -input.y:2.1-7: warning: POSIX Yacc forbids dashes in symbol names: foo-bar
 +input.y:2.1-7: warning: POSIX Yacc forbids dashes in symbol names: foo-bar [-Wyacc]
  ]])
  [mv stderr experr]
  AT_BISON_CHECK([[-Werror,no-all,yacc input.y]], [[1]], [[]], [[experr]])
@@@ -1491,3 -1369,100 +1491,102 @@@ AT_TEST([%define api.prefix foo], [-p b
  m4_popdef([AT_TEST])
  
  AT_CLEANUP
 -[[%token TOK
+ ## -------------- ##
+ ## Stray $ or @.  ##
+ ## -------------- ##
+ AT_SETUP([[Stray $ or @]])
+ # Give %printer and %destructor "<*> exp TOK" instead of "<*>" to
+ # check that the warnings are reported once, not three times.
+ AT_DATA_GRAMMAR([[input.y]],
 -[[input.y:10.19: warning: stray '$'
 -input.y:10.23: warning: stray '@'
 -input.y:11.19: warning: stray '$'
 -input.y:11.23: warning: stray '@'
 -input.y:12.19: warning: stray '$'
 -input.y:12.23: warning: stray '@'
 -input.y:14.19: warning: stray '$'
 -input.y:14.23: warning: stray '@'
++[[%type <TYPE> exp
++%token <TYPE> TOK TOK2
+ %destructor     { $%; @%; } <*> exp TOK;
+ %initial-action { $%; @%; };
+ %printer        { $%; @%; } <*> exp TOK;
+ %%
+ exp: TOK        { $%; @%; $$ = $1; };
+ ]])
+ AT_BISON_CHECK([[input.y]], 0, [],
 -  a a[last]
++[[input.y:11.19: warning: stray '$' [-Wother]
++input.y:11.23: warning: stray '@' [-Wother]
++input.y:12.19: warning: stray '$' [-Wother]
++input.y:12.23: warning: stray '@' [-Wother]
++input.y:13.19: warning: stray '$' [-Wother]
++input.y:13.23: warning: stray '@' [-Wother]
++input.y:15.19: warning: stray '$' [-Wother]
++input.y:15.23: warning: stray '@' [-Wother]
+ ]])
+ AT_CLEANUP
+ ## ---------------- ##
+ ## Code injection.  ##
+ ## ---------------- ##
+ AT_SETUP([[Code injection]])
+ m4_pattern_allow([^m4_errprintn$])
+ # AT_TEST([MACRO])
+ # ----------------
+ # Try to have MACRO be run by bison.
+ m4_pushdef([AT_TEST],
+ [AT_DATA([[input.y]],
+ [[%type <$1(DEAD %type)> exp
+ %token <$1(DEAD %token)> a
++%token b
+ %initial-action
+ {
+   $$;
+   $<$1(DEAD %initial-action)>$
+ };
+ %printer
+ {
+   $$
+   $<$1(DEAD %printer)>$
+ } <> <*>;
+ %lex-param
+ {
+   $1(DEAD %lex-param)
+ };
+ %parse-param
+ {
+   $1(DEAD %parse-param)
+ };
+ %%
+ exp:
 -    $<$1(DEAD action 3)>last
++  a a[name] b
+   {
+     $$;
+     $][1;
+     $<$1(DEAD action 1)>$
+     $<$1(DEAD action 2)>1
++    $<$1(DEAD action 3)>name
+     $<$1(DEAD action 4)>0
+     ;
+   };
+ ]])
+ # FIXME: Provide a means to iterate over all the skeletons.
+ AT_BISON_CHECK([[-d               input.y]])
+ AT_BISON_CHECK([[-d -S glr.c      input.y]])
+ AT_BISON_CHECK([[-d -S lalr1.cc   input.y]])
+ AT_BISON_CHECK([[-d -S glr.cc     input.y]])
+ AT_BISON_CHECK([[   -S lalr1.java input.y]])
+ ])
+ AT_TEST([m4_errprintn])
+ AT_TEST([@:>@m4_errprintn])
+ m4_popdef([AT_TEST])
+ AT_CLEANUP
diff --combined tests/local.at
index c79fc08e2c4fba35d00c3c6452cfbe14b22b718f,5c9b865eeacb7dda652d3b1b60f6ca4a1e0f782d..4499e13f41dee5c3428180fb4075a4e5aee4c488
@@@ -109,7 -109,7 +109,7 @@@ m4_define([AT_BISON_OPTION_PUSHDEFS]
  # --------------------------------------------------
  # This macro works around the impossibility to define macros
  # inside macros, because issuing `[$1]' is not possible in M4 :(.
 -# This sucks hard, GNU M4 should really provide M5 like $$1.
 +# This sucks hard, GNU M4 should really provide M5-like $$1.
  m4_define([_AT_BISON_OPTION_PUSHDEFS],
  [m4_if([$1$2], $[1]$[2], [],
         [m4_fatal([$0: Invalid arguments: $@])])dnl
@@@ -152,9 -152,6 +152,9 @@@ m4_pushdef([AT_NAME_PREFIX]
  [m4_bmatch([$3], [\(%define api\.prefix\|%name-prefix\) ".*"],
             [m4_bregexp([$3], [\(%define api\.prefix\|%name-prefix\) "\([^""]*\)"], [\2])],
             [yy])])
 +m4_pushdef([AT_TOKEN_PREFIX],
 +[m4_bmatch([$3], [%define api.tokens.prefix ".*"],
 +           [m4_bregexp([$3], [%define api.tokens.prefix "\(.*\)"], [\1])])])
  m4_pushdef([AT_API_prefix],
  [m4_bmatch([$3], [%define api\.prefix ".*"],
             [m4_bregexp([$3], [%define api\.prefix "\([^""]*\)"], [\1])],
@@@ -164,20 -161,20 +164,20 @@@ m4_pushdef([AT_API_PREFIX]
  # yyerror receives the location if %location & %pure & (%glr or %parse-param).
  m4_pushdef([AT_YYERROR_ARG_LOC_IF],
  [AT_GLR_OR_PARAM_IF([AT_PURE_AND_LOC_IF([$1], [$2])],
 -                  [$2])])
 +                    [$2])])
  # yyerror always sees the locations (when activated), except if
  # (yacc & pure & !param).  FIXME: This is wrong.  See the manual.
  m4_pushdef([AT_YYERROR_SEES_LOC_IF],
  [AT_LOCATION_IF([AT_YACC_IF([AT_PURE_IF([AT_PARAM_IF([$1], [$2])],
 -                                      [$1])],
 -                          [$1])],
 -              [$2])])
 +                                        [$1])],
 +                            [$1])],
 +                [$2])])
  
  # The interface is pure: either because %define api.pure, or because we
  # are using the C++ parsers.
  m4_pushdef([AT_PURE_LEX_IF],
  [AT_PURE_IF([$1],
 -          [AT_SKEL_CC_IF([$1], [$2])])])
 +            [AT_SKEL_CC_IF([$1], [$2])])])
  
  m4_pushdef([AT_YYSTYPE],
  [AT_SKEL_CC_IF([AT_NAME_PREFIX[::parser::semantic_type]],
@@@ -191,15 -188,15 +191,15 @@@ AT_PURE_LEX_IF
  [m4_pushdef([AT_LOC], [(*llocp)])
   m4_pushdef([AT_VAL], [(*lvalp)])
   m4_pushdef([AT_YYLEX_FORMALS],
 -          [AT_YYSTYPE *lvalp[]AT_LOCATION_IF([, AT_YYLTYPE *llocp])])
 +            [AT_YYSTYPE *lvalp[]AT_LOCATION_IF([, AT_YYLTYPE *llocp])])
   m4_pushdef([AT_YYLEX_ARGS],
 -          [lvalp[]AT_LOCATION_IF([, llocp])])
 +            [lvalp[]AT_LOCATION_IF([, llocp])])
   m4_pushdef([AT_USE_LEX_ARGS],
 -          [(void) lvalp;AT_LOCATION_IF([(void) llocp])])
 +            [(void) lvalp;AT_LOCATION_IF([(void) llocp])])
   m4_pushdef([AT_YYLEX_PRE_FORMALS],
 -          [AT_YYLEX_FORMALS, ])
 +            [AT_YYLEX_FORMALS, ])
   m4_pushdef([AT_YYLEX_PRE_ARGS],
 -          [AT_YYLEX_ARGS, ])
 +            [AT_YYLEX_ARGS, ])
  ],
  [m4_pushdef([AT_LOC], [[(]AT_NAME_PREFIX[lloc)]])
   m4_pushdef([AT_VAL], [[(]AT_NAME_PREFIX[lval)]])
@@@ -218,8 -215,6 +218,8 @@@ AT_SKEL_CC_IF
      [AT_LOC_PUSHDEF([begin.line], [begin.column], [end.line], [end.column])])],
    [AT_LOC_PUSHDEF([first_line], [first_column], [last_line], [last_column])])
  
 +
 +AT_GLR_IF([AT_KEYWORDS([glr])])
  ])# _AT_BISON_OPTION_PUSHDEFS
  
  
@@@ -338,7 -333,7 +338,7 @@@ stati
    static size_t toknum = 0;
    int res;
    ]AT_USE_LEX_ARGS[;
-   assert (toknum < sizeof input);
+   assert (toknum < sizeof input / sizeof input[0]);
    res = input[toknum++];
    ]$2[;]AT_LOCATION_IF([[
    ]AT_LOC_FIRST_LINE[ = ]AT_LOC_LAST_LINE[ = 1;
@@@ -394,11 -389,13 +394,11 @@@ stati
  }]],
  [c++], [[/* A C++ error reporting function.  */
  void
 -]AT_NAME_PREFIX[::parser::error (const location_type& l, const std::string& m)
 -{
 -  (void) l;
 -  std::cerr << ]AT_LOCATION_IF([l << ": " << ])[m << std::endl;
 +]AT_NAME_PREFIX[::parser::error (]AT_LOCATION_IF([[const location_type& l, ]])[const std::string& m)
 +{  std::cerr << ]AT_LOCATION_IF([l << ": " << ])[m << std::endl;
  }]],
  [java], [AT_LOCATION_IF([[public void yyerror (Calc.Location l, String s)
 -  {
 +{
      if (l == null)
        System.err.println (s);
      else
    public void yyerror (String s)
    {
      System.err.println (s);
 -  }]])])dnl
 +}]])])dnl
  ])
  
  
@@@ -465,58 -462,58 +465,58 @@@ m4_define([AT_BISON_CHECK_WARNINGS]
  
  m4_define([AT_BISON_CHECK_WARNINGS_],
  [[# Defining POSIXLY_CORRECT causes bison to complain if options
 -# are added after the grammar file name, so skip these checks
 -# in that case.
 -if test -z "${POSIXLY_CORRECT+set}"; then
 -  ]AT_SAVE_SPECIAL_FILES[
 +        # are added after the grammar file name, so skip these checks
 +        # in that case.
 +        if test -z "${POSIXLY_CORRECT+set}"; then
 +          ]AT_SAVE_SPECIAL_FILES[
  
 -  # To avoid expanding it repeatedly, store specified stdout.
 -  ]AT_DATA([expout], [$3])[
 +          # To avoid expanding it repeatedly, store specified stdout.
 +          ]AT_DATA([expout], [$3])[
  
 -  # Run with -Werror.
 +          # Run with -Werror.
    ]AT_BISON_CHECK_([$1[ -Werror]], [[1]], [expout], [stderr])[
  
 -  # Build expected stderr up to and including the "warnings being
 -  # treated as errors" message.
 -  ]AT_DATA([[at-bison-check-warnings]], [$4])[
 -  at_bison_check_first=`sed -n \
 -    '/: warning: /{=;q;}' at-bison-check-warnings`
 -  : ${at_bison_check_first:=1}
 -  at_bison_check_first_tmp=`sed -n \
 -    '/conflicts: [0-9].*reduce$/{=;q;}' at-bison-check-warnings`
 -  : ${at_bison_check_first_tmp:=1}
 -  if test $at_bison_check_first_tmp -lt $at_bison_check_first; then
 -    at_bison_check_first=$at_bison_check_first_tmp
 -  fi
 -  if test $at_bison_check_first -gt 1; then
 -    sed -n "1,`expr $at_bison_check_first - 1`"p \
 -      at-bison-check-warnings > experr
 -  fi
 -  echo ']AT_BISON_WERROR_MSG[' >> experr
 -
 -  # Finish building expected stderr and check.  Unlike warnings,
 -  # complaints cause bison to exit early.  Thus, with -Werror, bison
 -  # does not necessarily report all warnings that it does without
 -  # -Werror, but it at least reports one.
 -  at_bison_check_last=`sed -n '$=' stderr`
 -  : ${at_bison_check_last:=1}
 -  at_bison_check_last=`expr $at_bison_check_last - 1`
 -  sed -n "$at_bison_check_first,$at_bison_check_last"p \
 -    at-bison-check-warnings >> experr
 -  ]AT_CHECK([[sed 's,.*/\(]AT_BISON_WERROR_MSG[\)$,\1,' \
 -              stderr 1>&2]], [[0]], [[]], [experr])[
 -
 -  # Now check --warnings=error.
 -  cp stderr experr
 +          # Build expected stderr up to and including the "warnings being
 +          # treated as errors" message.
 +          ]AT_DATA([[at-bison-check-warnings]], [$4])[
 +          at_bison_check_first=`sed -n \
 +            '/: warning: /{=;q;}' at-bison-check-warnings`
 +          : ${at_bison_check_first:=1}
 +          at_bison_check_first_tmp=`sed -n \
 +            '/conflicts: [0-9].*reduce$/{=;q;}' at-bison-check-warnings`
 +          : ${at_bison_check_first_tmp:=1}
 +          if test $at_bison_check_first_tmp -lt $at_bison_check_first; then
 +            at_bison_check_first=$at_bison_check_first_tmp
 +          fi
 +          if test $at_bison_check_first -gt 1; then
 +            sed -n "1,`expr $at_bison_check_first - 1`"p \
 +              at-bison-check-warnings > experr
 +          fi
 +          echo ']AT_BISON_WERROR_MSG[' >> experr
 +
 +          # Finish building expected stderr and check.  Unlike warnings,
 +          # complaints cause bison to exit early.  Thus, with -Werror, bison
 +          # does not necessarily report all warnings that it does without
 +          # -Werror, but it at least reports one.
 +          at_bison_check_last=`sed -n '$=' stderr`
 +          : ${at_bison_check_last:=1}
 +          at_bison_check_last=`expr $at_bison_check_last - 1`
 +          sed -n "$at_bison_check_first,$at_bison_check_last"p \
 +            at-bison-check-warnings >> experr
 +          ]AT_CHECK([[sed 's,.*/\(]AT_BISON_WERROR_MSG[\)$,\1,' \
 +                      stderr 1>&2]], [[0]], [[]], [experr])[
 +
 +          # Now check --warnings=error.
 +          cp stderr experr
    ]AT_BISON_CHECK_([$1[ --warnings=error]], [[1]], [expout], [experr])[
  
 -  # Now check -Wnone and --warnings=none by making sure that
 -  # -Werror doesn't change the exit status when -Wnone or
 -  # --warnings=none is specified.
 +          # Now check -Wnone and --warnings=none by making sure that
 +          # -Werror doesn't change the exit status when -Wnone or
 +          # --warnings=none is specified.
    ]AT_BISON_CHECK_([$1[ -Wnone -Werror]], [[0]], [expout])[
    ]AT_BISON_CHECK_([$1[ --warnings=none -Werror]], [[0]], [expout])[
  
 -  ]AT_RESTORE_SPECIAL_FILES[
 +          ]AT_RESTORE_SPECIAL_FILES[
  fi]dnl
  ])
  
@@@ -546,10 -543,10 +546,10 @@@ m4_define([AT_BISON_CHECK_XML]
    # Don't combine these Bison invocations since we want to be sure that
    # --report=all isn't required to get the full XML file.
    AT_BISON_CHECK_([[--report=all --report-file=xml-tests/test.output \
 -                  --graph=xml-tests/test.dot ]]AT_BISON_ARGS,
 -                  [[0]], [ignore], [ignore])
 +             --graph=xml-tests/test.dot ]]AT_BISON_ARGS,
 +           [[0]], [ignore], [ignore])
    AT_BISON_CHECK_([[--xml=xml-tests/test.xml ]]AT_BISON_ARGS,
 -                 [[0]], [ignore], [ignore])
 +           [[0]], [ignore], [ignore])
    m4_popdef([AT_BISON_ARGS])dnl
    [cp xml-tests/test.output expout]
    AT_CHECK([[$XSLTPROC \
@@@ -598,7 -595,7 +598,7 @@@ m4_define([AT_COMPILE]
                    [-o $1],
                    [m4_default([$2], [m4_bpatsubst([$1], [\.o$]).c])],
                    [m4_bmatch([$1], [[.]], [], [$LIBS])]),
 -         0, [ignore], [ignore])])
 +           0, [ignore], [ignore])])
  
  # AT_COMPILE_CXX(OUTPUT, [SOURCES = OUTPUT.cc])
  # ---------------------------------------------
@@@ -617,7 -614,7 +617,7 @@@ AT_CHECK(m4_join([ ]
                   [-o $1],
                   [m4_default([$2], [m4_bpatsubst([$1], [\.o$]).cc])],
                   [m4_bmatch([$1], [[.]], [], [$LIBS])]),
 -       0, [ignore], [ignore])])
 +         0, [ignore], [ignore])])
  
  # AT_JAVA_COMPILE(SOURCES)
  # ------------------------
@@@ -657,23 -654,23 +657,23 @@@ m4_define([AT_FULL_COMPILE]
  [java],
    [AT_BISON_CHECK([-o $1.java $1.y])
     AT_LANG_COMPILE([$1],
 -                   m4_join([ ],
 -                           [$1.java],
 -                           m4_ifval($2, [[$1-$2.java]]),
 +                    m4_join([ ],
 +                            [$1.java],
 +                            m4_ifval($2, [[$1-$2.java]]),
                             m4_ifval($3, [[$1-$3.java]])))],
  [c++],
    [AT_BISON_CHECK([-o $1.cc $1.y])
     AT_LANG_COMPILE([$1],
 -                   m4_join([ ],
 -                           [$1.cc],
 -                           m4_ifval($2, [[$1-$2.cc]]),
 +                     m4_join([ ],
 +                             [$1.cc],
 +                             m4_ifval($2, [[$1-$2.cc]]),
                             m4_ifval($3, [[$1-$3.cc]])))],
  [c],
    [AT_BISON_CHECK([-o $1.c $1.y])
     AT_LANG_COMPILE([$1],
 -                   m4_join([ ],
 -                           [$1.c],
 -                           m4_ifval($2, [[$1-$2.c]]),
 +                  m4_join([ ],
 +                          [$1.c],
 +                          m4_ifval($2, [[$1-$2.c]]),
                             m4_ifval($3, [[$1-$3.c]])))])
  ])