]> git.saurik.com Git - bison.git/commitdiff
Merge remote-tracking branch 'origin/maint'
authorAkim Demaille <akim@lrde.epita.fr>
Wed, 10 Apr 2013 07:23:20 +0000 (09:23 +0200)
committerAkim Demaille <akim@lrde.epita.fr>
Wed, 10 Apr 2013 08:24:56 +0000 (10:24 +0200)
* origin/maint:
  glr.cc: fix a clang warning
  maint: update copyright years
  build: fix VPATH issue
  build: avoid clang's colored diagnostics in the test suite
  tests: please clang and use ".cc", not ".c", for C++ input
  gnulib: update
  skeletons: avoid empty switch constructs
  lalr1.cc: fix compiler warnings
  yacc.c: do not use __attribute__ unprotected
  tests: style changes

180 files changed:
ChangeLog-2012
Makefile.am
NEWS
README
README-hacking
REFERENCES
THANKS
TODO
bootstrap.conf
build-aux/.gitignore
build-aux/Makefile.am [deleted file]
build-aux/cross-options.pl
build-aux/local.mk [new file with mode: 0644]
build-aux/move-if-change [new symlink]
cfg.mk
configure.ac
data/.cvsignore [deleted file]
data/.gitignore [deleted file]
data/Makefile.am [deleted file]
data/README
data/bison.m4
data/c++.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 [new file with mode: 0644]
data/location.cc
data/stack.hh
data/variant.hh [new file with mode: 0644]
data/xslt/xml2dot.xsl
data/xslt/xml2text.xsl
data/xslt/xml2xhtml.xsl
data/yacc.c
djgpp/local.mk [new file with mode: 0644]
doc/.gitignore
doc/Doxyfile.in
doc/Makefile.am [deleted file]
doc/bison.texi
doc/bison.x
doc/common.x [deleted file]
doc/local.mk [new file with mode: 0644]
etc/.gitignore
etc/Makefile.am [deleted file]
etc/bench.pl.in
etc/local.mk [new file with mode: 0644]
examples/.cvsignore [deleted file]
examples/.gitignore [deleted file]
examples/Makefile.am [deleted file]
examples/calc++/.gitignore
examples/calc++/Makefile.am [deleted file]
examples/calc++/calc++.test [new file with mode: 0755]
examples/calc++/local.mk [new file with mode: 0644]
examples/calc++/test [deleted file]
examples/calc++/y.tab.h [new file with mode: 0644]
examples/extexi [changed mode: 0644->0755]
examples/local.mk [new file with mode: 0644]
examples/mfcalc/.gitignore [new file with mode: 0644]
examples/mfcalc/local.mk [new file with mode: 0644]
examples/mfcalc/mfcalc.test [new file with mode: 0755]
examples/rpcalc/.gitignore [new file with mode: 0644]
examples/rpcalc/local.mk [new file with mode: 0644]
examples/rpcalc/rpcalc.test [new file with mode: 0755]
examples/test [new file with mode: 0755]
examples/variant.yy [new file with mode: 0644]
lib/.gitignore
lib/Makefile.am [deleted file]
lib/abitset.c
lib/bbitset.h
lib/bitset.c
lib/bitset.h
lib/bitset_stats.c
lib/bitsetv-print.c
lib/bitsetv.c
lib/ebitset.c
lib/lbitset.c
lib/libiberty.h
lib/local.mk [new file with mode: 0644]
lib/main.c
lib/timevar.c
lib/timevar.h
lib/vbitset.c
m4/.gitignore
m4/c-working.m4
m4/cxx.m4
m4/flex.m4
po/.gitignore
runtime-po/.gitignore
src/.gitignore
src/AnnotationList.h
src/InadequacyList.h
src/LR0.c
src/Makefile.am [deleted file]
src/Sbitset.h
src/assoc.c
src/assoc.h
src/closure.c
src/closure.h
src/complain.c
src/complain.h
src/conflicts.c
src/derives.c
src/files.c
src/files.h
src/flex-scanner.h
src/getargs.c
src/getargs.h
src/gram.c
src/gram.h
src/graphviz.h
src/ielr.c
src/ielr.h
src/lalr.c
src/local.mk [new file with mode: 0644]
src/location.c
src/location.h
src/main.c
src/muscle-tab.c
src/muscle-tab.h
src/named-ref.h
src/nullable.c
src/output.c
src/output.h
src/parse-gram.c
src/parse-gram.h
src/parse-gram.y
src/print-xml.c
src/print.c
src/print_graph.c
src/reader.c
src/reader.h
src/reduce.c
src/relation.c
src/relation.h
src/scan-code-c.c
src/scan-code.h
src/scan-code.l
src/scan-gram-c.c
src/scan-gram.l
src/scan-skel-c.c
src/scan-skel.l
src/state.c
src/state.h
src/symlist.c
src/symlist.h
src/symtab.c
src/symtab.h
src/system.h
src/tables.c
src/uniqstr.c
src/uniqstr.h
submodules/autoconf
tests/.gitignore
tests/Makefile.am [deleted file]
tests/actions.at
tests/atlocal.in
tests/bison.in
tests/c++.at
tests/calc.at
tests/conflicts.at
tests/existing.at
tests/glr-regression.at
tests/headers.at
tests/input.at
tests/java.at
tests/local.at
tests/local.mk [new file with mode: 0644]
tests/named-refs.at
tests/output.at
tests/reduce.at
tests/regression.at
tests/sets.at
tests/skeletons.at
tests/synclines.at
tests/testsuite.at
tests/torture.at
tests/types.at [new file with mode: 0644]

index 6981c55489d0d06e0c487565cfbb2abb73fb74c8..458a9e55e2deefdf860e1e1a0d299a861beb6819 100644 (file)
@@ -1,30 +1,32 @@
-2012-01-15  Jim Meyering  <meyering@redhat.com>
+2012-01-15  Akim Demaille  <demaille@gostai.com>
+
+       java: fix reduction traces.
+       * data/lalr1.java (yy_reduce_print): Fix state index.
+       Reported by Tim Landscheidt.
+
+2012-01-12  Jim Meyering  <meyering@redhat.com>
+
+       build: avoid warning from coverity about lbitset_elt_find
+       * lib/lbitset.c (lbitset_elt_find): Remove unnecessary test of "elt",
+       at a point where we know it is non-NULL, due to prior dereference.
+
+2012-01-13  Jim Meyering  <meyering@redhat.com>
 
        maint: get fdl.texi from gnulib
        * bootstrap.conf (gnulib_modules): Add fdl.
        * doc/fdl.texi: Remove file.
        * doc/.gitignore: Add it here.
 
-2012-01-15  Jim Meyering  <meyering@redhat.com>
-
        maint: spell "file system" as two separate words
        * doc/Doxyfile.in: Spell it "file system", to avoid a
        "make syntax-check" failure.
 
-2012-01-15  Jim Meyering  <meyering@redhat.com>
-
        maint: avoid "the the"
        * djgpp/README.in: s/the the/the/
        * src/parse-gram.c (lloc_default): Likewise.
        * src/parse-gram.y (lloc_default): Likewise, and remove a
        trailing space.
 
-2012-01-13  Jim Meyering  <meyering@redhat.com>
-
-       build: avoid warning from coverity about lbitset_elt_find
-       * lib/lbitset.c (lbitset_elt_find): Remove unnecessary test of "elt",
-       at a point where we know it is non-NULL, due to prior dereference.
-
 2012-01-13  Akim Demaille  <akim@lrde.epita.fr>
 
        maint: factor copyright year.
        * lib/ebitset.c (ebitset_init): Likewise, for "size".
        * lib/lbitset.c (lbitset_not): Likewise, for "elt".
 
+2011-08-21  Joel E. Denny  <joeldenny@joeldenny.org>
+
+       lalr1.cc: remove trailing comma from enumerator list.
+       * data/lalr1.cc (yy::parser): Here.  This suppresses a -pedantic
+       warning.
+
 2011-08-21  Joel E. Denny  <joeldenny@joeldenny.org>
 
        tests: add -pedantic for --enable-gcc-warnings.
        * tests/existing.at (GNU Cim Grammar)
        (GNU pic (Groff 1.18.1) Grammar.): Remove empty %union.
 
+2011-07-24  Joel E. Denny  <joeldenny@joeldenny.org>
+
+       global: remove unnecessary horizontal tabs.
+       This change was made by applying emacs' untabify function to
+       nearly all files in Bison's repository.  Required tabs in make
+       files, ChangeLog, regexps, and test code were manually skipped.
+       Other notable exceptions and changes are listed below.
+       * bootstrap: Skip because we sync this with gnulib.
+       * data/m4sugar/foreach.m4
+       * data/m4sugar/m4sugar.m4: Skip because we sync these with
+       Autoconf.
+       * djgpp: Skip because I don't know how to test djgpp properly, and
+       this code appears to be unmaintained anyway.
+       * README-hacking (Hacking): Specify that tabs should be avoided
+       where not required.
+
 2011-07-10  Joel E. Denny  <joeldenny@joeldenny.org>
 
        build: avoid YACC typo inherited from Autoconf.
        * tests/regression.at (Token number in precedence declaration):
        Extend.
 
-2011-05-01  Joel E. Denny  <joeldenny@joeldenny.org>
-
-       Prepare for 2.5 release.
-       * NEWS (2.5_rc1): Rename back to...
-       (2.5): ... this, and unset date.
-
-2011-05-01  Joel E. Denny  <joeldenny@joeldenny.org>
-
-       Version 2.5_rc1.
-       * NEWS (2.5): Rename to...
-       (2.5_rc1): ... this, and set date.
-
 2011-05-01  Joel E. Denny  <joeldenny@joeldenny.org>
 
        Pacify -DGNULIB_POSIXCHECK.
        * src/files.c (file_name_split)
        * src/getargs.c (getargs)
        * src/location.c (boundary_set_from_string)
-       * src/output.c (token_definitions_output, output_skeleton)
+       * src/output.c (output_skeleton)
        * src/parse-gram.y (prologue_declaration)
        * src/scan-gram.l (handle_syncline)
        * src/symtab.c (symbol_new): Use mbschr and mbsrchr instead of
 
        * NEWS (2.5): Document fix for -Wno-CATEGORY.
 
-2008-11-21  Di-an Jan  <dianj@freeshell.org>
-
-       Implement no-XXX arguments for --warnings, --report, --trace.
-       * src/getargs.c (flags_argmatch): Handles no-XXX.
-       Fix typo in doxygen comment.
-
 2011-03-20  Joel E. Denny  <joeldenny@joeldenny.org>
 
        doc: fix confusing citation of LAC publication.
        lr.keep-unreachable-states, lr.type, and parse.lac into brief
        summaries, and cross-reference the appropriate subsections of
        Tuning LR.  For parse.lac, mention that it's only implemented for
-       deterministic parsers in C.
-       (Error Reporting): When mentioning %error-verbose, mention LAC,
+       deterministic parsers in C.  In parse.error entry, mention LAC,
        and add cross-reference to the LAC section.
+       (Error Reporting): When mentioning parse.error, mention LAC, and
+       add cross-reference to the LAC section.
        (Tuning LR): New section with an extended version of the
        documentation removed from %define Summary.  Change all
        cross-references in the manual to point here instead of there.
-       (Calc++ Parser): When mentioning %error-verbose, mention LAC, and
-       add cross-reference to the LAC section.
-       (Table of Symbols): In %error-verbose and YYERROR_VERBOSE entries,
-       add cross-references to Error Reporting.
+       (Calc++ Parser): When mentioning parse.error, mention LAC, and add
+       cross-reference to the LAC section.
+       (Table of Symbols): In %error-verbose entry, add cross-reference
+       to Error Reporting.
        (Glossary): Capitalize entry titles consistently.  Add definitions
        for "defaulted state" and "unreachable state".  Expand IELR
        acronym in IELR's entry.
        reversed access to location stack.
        * THANKS (Bernd Kiefer): Add.
 
-2010-05-11  Akim Demaille  <demaille@gostai.com>
+2011-02-13  Joel E. Denny  <joeldenny@joeldenny.org>
 
-       doc: please Emacs.
-       * doc/bison.texinfo (Local Variables): Move this after the
-       LocalWords, since the latter are looked for in the whole document,
-       while the former are looked for only at its end.
-       Require american spell checking.
+       doc: fix some minor inconsistencies.
+       * doc/bison.texinfo (%define Summary): Fix mislabeled entry for
+       lex_symbol.
+       (%code Summary): For consistency with the variable list in the
+       %define Summary, enclose the list of %code qualifiers in a table
+       instead of an itemize.
 
 2011-02-06  Joel E. Denny  <joeldenny@joeldenny.org>
 
        is requested.
        * tests/conflicts.at (%nonassoc and eof): Extend to check the
        effect of each of -Dlr.type=canonical-lr and -Dparse.lac=full.
-       (%error-verbose and consistent errors): Likewise.
+       (parse.error=verbose and consistent errors): Likewise.
        (LAC: %nonassoc requires splitting canonical LR states): New test
        group demonstrating how LAC can fix canonical LR.
        * tests/input.at (LAC: Errors for %define): New test group.
        * bootstrap.conf (bootstrap_sync): Set to true.
        * gnulib: Update to latest so bootstrap is in sync now.
 
-2010-11-07  Joel E. Denny  <joeldenny@joeldenny.org>
-
-       yysyntax_error: adjust prior fixes for branch-2.5's lalr1.cc.
-       On master, there is no yychar in lalr1.cc, but there is on
-       branch-2.5, and the prior cherry-pick of "Fix handling of yychar
-       manipulation in user semantic actions" wasn't adjusted for that
-       difference.
-       * data/lalr1.cc (yy::parser::parse): Translate yychar before
-       every use of yytoken, and add comments explaining this approach.
-       * tests/conflicts.at (%error-verbose and consistent errors):
-       Extend to test yychar manipulation with lalr1.cc.
-
 2010-11-07  Joel E. Denny  <joeldenny@joeldenny.org>
 
        yysyntax_error: fix for consistent error with lookahead.
        * data/glr.c (yyreportSyntaxError): As in yacc.c, don't drop the
        unexpected token unless there actually is no lookahead.
        * data/lalr1.cc (yy::parser::parse): If there's no lookahead,
-       set yytoken to yyempty_ before invoking yysyntax_error_.
+       pass yyempty_ not yyla.type to yysyntax_error_.
        (yy::parser::yysyntax_error_): Again, don't drop the unexpected
        token unless there actually is no lookahead.
        * data/lalr1.java (YYParser::parse): If there's no lookahead,
        set yytoken to yyempty_ before invoking yysyntax_error.
        (YYParser::yysyntax_error): Again, don't drop the unexpected
        token unless there actually is no lookahead.
-       * tests/conflicts.at (%error-verbose and consistent
+       * tests/conflicts.at (parse.error=verbose and consistent
        errors): Extend test group to further reveal how the previous
        use of the simple "syntax error" message was too general.  Test
        yacc.c, glr.c, lalr1.cc, and lalr1.java.  No longer an expected
        There are no behavioral changes here.
        * data/glr.c (yyreportSyntaxError): Reorganize.
        * data/lalr1.cc (yy::parser::yysyntax_error_): Reorganize.
-       * tests/conflicts.at (%error-verbose and consistent errors):
+       * tests/conflicts.at (parse.error=verbose and consistent errors):
        Reorganize.
 
 2010-11-07  Joel E. Denny  <joeldenny@joeldenny.org>
        * data/lalr1.java (YYParser::yysyntax_error): Reindent.
        * data/yacc.c (yysyntax_error): Reindent.
 
+2010-10-31  Joel E. Denny  <joeldenny@joeldenny.org>
+
+       Fix memory leak.
+       * src/output.c (prepare_rules): Free temporary array.
+
 2010-10-31  Joel E. Denny  <joeldenny@joeldenny.org>
 
        yysyntax_error: improve invocation readability.
        out of storage?  If not, we can omit malloc-gnu; but for now I left
        it in to be safe.
        (vc_ignore): Remove.
+       (gnulib_mk_hook): New function.
        * README-hacking: Renamed from HACKING, since gnulib bootstrap now
        uses that convention.
 
+2010-09-09  Paul Hilfinger  <hilfinger@cs.berkeley.edu>
+
+       * data/glr.c (yySymbol): Define as int to avoid compiler warnings about
+       possible change of value.
+
+2010-09-08  Paul Hilfinger  <hilfinger@cs.berkeley.edu>
+
+       * data/glr.c (yy_reduce_print): Change yyrhsVals to yyvsp to remove
+       compiler errors when using %debug.
+       Add declaration of yylow when locations in use to avoid compilation
+       error.
+       (yyglrReduce): Conditionalize message "Parse ... rejected by rule..."
+       on whether we are in split mode, for consistency with behavior of
+       non-GLR parsing.
+
+2010-09-01  Akim Demaille  <demaille@gostai.com>
+
+       Address GCC warnings about shadowed local variables (yyflag).
+       * data/glr.c (YYCHK): Rename yyflag as yychk_flag.
+       (yyprocessOneStack): Reduce the scope of yyaction, yyconflicts,
+       yyrule, and yyflag.
+
 2010-08-05  Joel E. Denny  <joeldenny@joeldenny.org>
 
        Version 2.4.3.
        * po/POTFILES.in: Add remaining gnulib files that have
        translatable strings.
 
+2010-07-25  Joel E. Denny  <joeldenny@joeldenny.org>
+
+       build: fix our adjustments for gnulib files in lib.
+       * configure.ac: For prepending lib/ to the values of config
+       variables, fix detection of empty values.  Also, due to recent
+       gnulib changes, add LIBUNISTRING_UNITYPES_H and
+       LIBUNISTRING_UNIWIDTH_H to the list of those variables.
+
 2010-07-25  Joel E. Denny  <joeldenny@joeldenny.org>
 
        maint: use announce-gen's new --mail-headers.
        (Output files: -dv >&-): Skip test group if running
        maintainer-check-valgrind.
 
+2010-07-23  Paul Hilfinger  <hilfingr@EECS.Berkeley.EDU>
+
+       * NEWS: Describe new semantic-predicate feature.
+       * data/c.m4 (b4_predicate_case): New definition.
+       * data/java.m4 (b4_predicate_case): New definition.
+       * data/glr.c (yyimmediate): Add definition.
+       (yydoAction): Remove comment, now obsolete.
+       Do YY_REDUCE_PRINT here.
+       (yyglrReduce): Alter comment to indicate that semantic values
+       need not be deferred.
+       Remove YY_REDUCE_PRINT from here; done in yydoAction.
+       (yyprocessOneStack): Pass immediate flag.
+       Delete stacks rejected by predicates in newly split-off parsers.
+       Change handling of yyerr so that only current stack gets deleted
+       when semantic predicate fails.
+       (yyfillin): Don't crash if a semantic value is unresolved (as may
+       happen in predicate rules).
+       Copy lr state as well in debugging mode.
+       Update comment on setting of yysval to include yyloc as well.
+       (yy_reduce_print): Add yynormal argument.  Perform fillin properly.
+       Report unresolved RHS values.
+       (yyimmediate): New table.
+       * src/gram.h (struct rule): Add is_predicate field.
+       * src/output.c (user_actions_output): Use b4_predicate_case for
+       predicates.
+       (prepare_symbols): Output yyimmediate.
+       * src/scan-gram.l: Add %? token, SC_PREDICATE state.
+       * src/scan-code.l (code_props_rule_action_init): Add is_predicate
+       argument.
+       * src/scan-code.h (struct code_props): Add is_predicate field.
+       (code_props_rule_action_init): New interface.
+       * src/parse-gram.y (%?{...}): New token.
+       (rhs): Add %?{...} rule.
+       * src/parse-gram.c: Regenerate.
+       * src/parse-gram.h: Regenerate.
+       * src/reader.c (grammar_current_rule_action_append): Add
+       immediate argument.
+       (grammar_midrule_action): Use new interface for
+       code_props_rule_action_init.
+       (grammar_current_rule_action_append): Ditto.
+       (packgram): Transfer is_predicate value.
+       * src/reader.h (grammar_current_rule_action_append): New interface.
+       * doc/bison.texinfo: Document semantic predicates (%?).
+
+       * data/glr.c (yylhsNonterm, yyisDefaultedState,yyDefaultAction)
+       (yygetLRActions,yynewGLRStackItem,yyaddDeferredAction,yyinitStateSet)
+       (yyinitGLRStack,yyexpandGLRStack,yyupdateSplit,yymarkStackDeleted)
+       (yyundeleteLastStack,yyglrShift,yyglrShiftDefer,yydoAction,yyglrReduce)
+       (yyidenticalOptions,yymergeOptionSets,yyresolveStates,yyresolveAction)
+       (yyresolveLocations,yyresolveValue,yyreducePrint): Update parameter
+       names in comments and mention all parameters.
+       (struct yyGLRState): Fix description of yyposn field.
+       (yyresolveLocations): Correct comment so as not to imply action when
+       yyn1==0.
+
 2010-06-17  Paul Eggert  <eggert@cs.ucla.edu>
 
        Update from GFDL GFDL 1.2 to 1.3.
        * doc/fdl.texi: Update to version 1.3, taken from:
        http://www.gnu.org/licenses/fdl.texi
 
-2010-06-17  Paul Eggert  <eggert@cs.ucla.edu>
-
        Do not use date ranges in copyright notices.
        See http://www.gnu.org/prep/maintain/maintain.html#Copyright-Notices
 
        * data/README, data/bison.m4, data/c++-skel.m4, data/c++.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/xslt/bison.xsl:
+       * data/lalr1.java, data/local.mk, data/location.cc:
+       * data/stack.hh, data/variant.hh, data/xslt/bison.xsl:
        * data/xslt/xml2dot.xsl, data/xslt/xml2text.xsl:
        * data/xslt/xml2xhtml.xsl, data/yacc.c, djgpp/Makefile.maint:
        * djgpp/README.in, djgpp/config.bat, djgpp/config.sed:
        * djgpp/config.site, djgpp/config_h.sed, djgpp/djunpack.bat:
-       * djgpp/subpipe.c, djgpp/subpipe.h:
-       * djgpp/testsuite.sed, doc/bison.texinfo:
-       * doc/refcard.tex, etc/README, etc/bench.pl.in:
+       * djgpp/local.mk, djgpp/subpipe.c, djgpp/subpipe.h:
+       * djgpp/testsuite.sed, doc/bison.texinfo, doc/local.mk:
+       * doc/refcard.tex, etc/README, etc/bench.pl.in, etc/local.mk:
        * examples/calc++/Makefile.am, examples/extexi:
-       * lib/abitset.c, lib/abitset.h:
+       * examples/local.mk, lib/abitset.c, lib/abitset.h:
        * lib/bbitset.h, lib/bitset.c, lib/bitset.h:
        * lib/bitset_stats.c, lib/bitset_stats.h, lib/bitsetv-print.c:
        * lib/bitsetv-print.h, lib/bitsetv.c, lib/bitsetv.h:
        * lib/ebitset.c, lib/ebitset.h, lib/get-errno.c:
        * lib/get-errno.h, lib/lbitset.c, lib/lbitset.h:
-       * lib/libiberty.h, lib/main.c, lib/timevar.c:
+       * lib/libiberty.h, lib/local.mk, lib/main.c, lib/timevar.c:
        * lib/timevar.def, lib/timevar.h, lib/vbitset.c:
        * lib/vbitset.h, lib/yyerror.c, m4/bison-i18n.m4:
        * m4/c-working.m4, m4/cxx.m4, m4/subpipe.m4, m4/timevar.m4:
        * src/derives.c, src/derives.h, src/files.c, src/files.h:
        * src/flex-scanner.h, src/getargs.c, src/getargs.h:
        * src/gram.c, src/gram.h, src/graphviz.c, src/ielr.c:
-       * src/ielr.h, src/lalr.c, src/lalr.h:
+       * src/ielr.h, src/lalr.c, src/lalr.h, src/local.mk:
        * src/location.c, src/location.h, src/main.c:
        * src/muscle-tab.c, src/muscle-tab.h, src/named-ref.c:
        * src/named-ref.h, src/nullable.c, src/nullable.h:
        * tests/calc.at, tests/conflicts.at, tests/cxx-type.at:
        * tests/existing.at, tests/glr-regression.at:
        * tests/headers.at, tests/input.at, tests/java.at:
-       * tests/local.at, tests/named-refs.at:
+       * tests/local.at, tests/local.mk, tests/named-refs.at:
        * tests/output.at, tests/push.at, tests/reduce.at:
        * tests/regression.at, tests/sets.at, tests/skeletons.at:
        * tests/synclines.at, tests/testsuite.at, tests/torture.at:
-       * data/Makefile.am, data/location.cc, doc/Makefile.am, src/Makefile.am:
-       * tests/Makefile.am, lib/Makefile.am, examples/Makefile.am:
-       * etc/Makefile.am:
        Don't use date ranges in copyright notices.
 
 2010-05-11  Akim Demaille  <demaille@gostai.com>
        sections.
        * NEWS (2.5): Document this.
 
-2010-05-07  Akim Demaille  <demaille@gostai.com>
+2010-05-11  Akim Demaille  <demaille@gostai.com>
+
+       doc: please Emacs.
+       * doc/bison.texinfo (Local Variables): Move this after the
+       LocalWords, since the latter are looked for in the whole document,
+       while the former are looked for only at its end.
+       Require american spell checking.
+
+2010-05-10  Akim Demaille  <demaille@gostai.com>
+
+       doc: fix lalr1.cc documentation.
+       * doc/bison.texinfo (C++ Scanner Interface): Fix yylex signature.
+       (C++ Bison Interface): Fix lalr1.cc skeleton name.
+       (C++ Parser Interface): Fix semantic_type and location_type names.
+       Document yy::parser::token.
+       Reported by Jerry Quinn.
+
+2010-05-10  Akim Demaille  <demaille@gostai.com>
 
        c++: use YYRHSLOC.
        * data/lalr1.cc (YYRHSLOC): New.
        Check that glr.cc supports user defined location_type.
        * NEWS: Document this.
 
-2010-05-10  Akim Demaille  <demaille@gostai.com>
+2010-05-07  Akim Demaille  <demaille@gostai.com>
 
-       doc: fix lalr1.cc documentation.
-       * doc/bison.texinfo (C++ Scanner Interface): Fix yylex signature.
-       (C++ Bison Interface): Fix lalr1.cc skeleton name.
-       (C++ Parser Interface): Fix semantic_type and location_type names.
-       Document yy::parser::token.
-       Reported by Jerry Quinn.
+       doc: fix typo.
+       * tests/synclines.at: here.
+
+2010-05-04  Akim Demaille  <demaille@gostai.com>
+
+       tests: enhance AT_SYNCLINES_COMPILE.
+       * tests/synclines.at (AT_SYNCLINES_COMPILE): More distcc patterns.
+       (AT_TEST_SYNCLINE): Remove GCC 4.5 protection which is already
+       taken care of in AT_SYNCLINES_COMPILE.
 
 2010-05-04  Akim Demaille  <demaille@gostai.com>
 
        lalr1.cc: don't generate location.hh when location_type is defined
-       * data/bison.m4 (b4_percent_define_use): New.
-       (b4_percent_define_get): Use it.
-       Accept a default value.
+       * data/bison.m4 (b4_percent_define_get): Accept a default value.
        * data/c++.m4: Do not provide a default value for the %define
        variable location_type, rather, use b4_percent_define_get with a
        default argument where its value is needed.
        * data/lalr1.cc: Do not load location.cc (which outputs both
        location.hh and position.hh) if the user defined location_type.
        Do not include location.hh either.
-       * data/glr.cc: Likewise.
+
+2010-05-04  Akim Demaille  <demaille@gostai.com>
+
+       lalr1.cc: minor refactoring.
+       * data/lalr1.cc: Don't issue empty namespaces.
+
+2010-05-04  Akim Demaille  <demaille@gostai.com>
+
+       tests: fix %printer.
+       Currently, there is no check that %printer ... <foo> (nor
+       %destructor) is about an existing <foo> type.  This C++ test had
+       it wrong (<::std::string> vs. <std::string>).
+
+       * tests/c++.at (AT_CHECK_VARIANTS): In list.yy, redefine the
+       pretty-printing of lists into something better for parser traces.
+       Update the expected output.
+       Fix correspondance between %type/%token and %printer.
 
 2010-05-04  Akim Demaille  <demaille@gostai.com>
 
        * tests/local.at (_AT_BISON_OPTION_PUSHDEFS): Adjust to the
        location_type changes.
 
-2010-05-04  Akim Demaille  <demaille@gostai.com>
-
-       tests: enhance AT_SYNCLINES_COMPILE.
-       * tests/synclines.at (AT_TEST_SYNCLINE): Move GCC 4.5 protection
-       into...
-       (AT_SYNCLINES_COMPILE): here.
-       Add more distcc patterns.
-
 2010-05-01  Joel E. Denny  <joeldenny@joeldenny.org>
 
        tests: fix maintainer-xml-check.
        portability: fix for BSD make.
        Reported by Johan van Selst at
        <http://lists.gnu.org/archive/html/bug-bison/2010-03/msg00016.html>.
-       * tests/Makefile.am ($(TESTSUITE)): Qualify package.m4 in
+       * tests/local.mk ($(TESTSUITE)): Qualify package.m4 in
        this dependency list as in package.m4's target rule.
 
 2010-03-23  Joel E. Denny  <jdenny@ces.clemson.edu>
        <http://lists.gnu.org/archive/html/bug-bison/2010-03/msg00014.html>.
        * NEWS (2.4.3): New.
        * THANKS (Johan van Selst): Add.
+       * etc/prefix-gnulib-mk (prefix): Adjust regex for makefile
+       targets so that gnulib's new c++defs.h is matched.
        * gnulib: Update to latest.
 
 2010-03-20  Joel E. Denny  <jdenny@ces.clemson.edu>
        * bootstrap.conf (gnulib_modules): Add pipe.
        * gnulib: Update to latest to make sure we have all the latest
        fixes.
-       * lib/Makefile.am (libbison_a_SOURCES): Remove subpipe.h and
+       * lib/local.mk (lib_libbison_a_SOURCES): Remove subpipe.h and
        subpipe.c.
        * po/POTFILES.in (lib/subpipe.c): Remove.
        * src/files.c (compute_output_file_names): Update invocations
        * tests/atlocal.in (abs_top_srcdir): Remove shell variable,
        which is already defined in atconfig.
 
+2010-01-22  Joel E. Denny  <jdenny@clemson.edu>
+
+       tests: fix missing include caught by g++ 4.4.1.
+       Reported by Tys Lefering.
+       * HACKING (Release checks): Add note about trying a recent GCC.
+       * tests/regression.at (_AT_DATA_DANCER_Y): For C++, include
+       cstdlib for abort.
+       (_AT_DATA_EXPECT2_Y): Likewise.
+
 2010-01-21  Joel E. Denny  <jdenny@clemson.edu>
 
        * cfg.mk (gnulib_dir): Assume gnulib is a subdirectory.
 
        * HACKING (Release Procedure): Recommend a secure automake.
 
-2008-12-11  Akim Demaille  <demaille@gostai.com>
-
-       Propagate i18n changes into glr.c.
-       * data/glr.c (yyreportSyntaxError): Use "switch" instead of
-       building the error message format dynamically.
-       * data/lalr1.java: Formatting changes.
-
-2009-12-22  Joel E. Denny  <jdenny@clemson.edu>
-
-       Port small part of master's 11707b2b so future ports are easier.
-       * data/lalr1.java (YYParser::yysyntax_error): Untabify.
-
-2008-12-11  Akim Demaille  <demaille@gostai.com>
-
-       Simplify the i18n of the error messages.
-       * data/lalr1.cc: Comment changes.
-
-2008-11-11  Akim Demaille  <demaille@gostai.com>
-
-       Prefer M4 to CPP.
-       * data/lalr1.cc: Use b4_error_verbose_if instead of #if
-       YYERROR_VERBOSE.
-
-2008-11-11  Akim Demaille  <demaille@gostai.com>
-
-       Support i18n of the parse error messages.
-       * TODO (lalr1.cc/I18n): Remove.
-       * data/lalr1.cc (yysyntax_error_): Support the translation of the
-       error messages, as done in yacc.c.
-       Stay within the yy* pseudo namespace.
-
-2009-12-22  Joel E. Denny  <jdenny@clemson.edu>
-
-       Port small part of master's 8901f32e so future ports are easier.
-       * data/lalr1.cc (yy::parser::yysyntax_error_): Always add second
-       argument, but name it in the function definition only when
-       verbose error messages are enabled and it'll thus be used.
-       (yy::parser::parse): Update use of yysyntax_error_.
-
 2009-12-29  Joel E. Denny  <jdenny@clemson.edu>
 
        portability: `<' and `>' are not always defined on addresses.
        action): New test group checking that translation happens before
        lookahead destructor calls at parser return.  Previously,
        incorrect destructors were called.
-       * tests/conflicts.at (%error-verbose and consistent
+       * tests/conflicts.at (parse.error=verbose and consistent
        errors): New test group checking that translation happens at
        syntax error detection before the associated verbose error
        message and the associated lookahead destructor calls.  While
        documentation.
        (LocalWords): Remove YYFAIL.
 
+2009-12-20  Joel E. Denny  <jdenny@clemson.edu>
+
+       tests: cleanup.
+       * tests/c++.at (Syntax error discarding no lookahead): Don't
+       ignore stderr.  Instead, eliminate remaining warnings.
+
+2009-12-18  Joel E. Denny  <jdenny@clemson.edu>
+
+       lalr1.cc: don't discard non-existent lookahead on syntax error.
+       * data/lalr1.cc (yy::parser::parse): Check yyempty first.
+       * tests/c++.at (Syntax error discarding no lookahead): New test
+       group.
+
 2009-12-17  Joel E. Denny  <jdenny@clemson.edu>
 
        Code cleanup.
        * tests/atlocal.in (LIBS): As for LDADD in src/local.mk, add
        lib/libbison.a so gnulib libraries can be linked.
 
+2009-12-15  Joel E. Denny  <jdenny@clemson.edu>
+
+       gnulib: update for fix of fprintf-posix, which we'll use soon.
+       * etc/prefix-gnulib-mk (prefix): Adjust regex for make file
+       targets so that gnulib's new arg-nonnull.h and link-warning.h
+       are matched.
+       * gnulib: Update.
+
 2009-12-14  Joel E. Denny  <jdenny@clemson.edu>
 
        Enable assertion output and --disable-assert for configure.
 
        * data/bison.m4: Update comments for rename to muscle-tab.h.
 
-2009-10-08  Joel E. Denny  <jdenny@clemson.edu>
-
-       Rename muscle_tab.* to muscle-tab.* for consistency with master.
-       * src/Makefile.am (bison_SOURCES): Update.
-       * src/getargs.c, src/ielr.c, src/lalr.c, src/main.c,
-       src/output.c, src/parse-gram.y, src/print.c, src/reader.c,
-       src/tables.c: Update include.
-       * src/muscle_tab.c, src/muscle_tab.h: Rename to...
-       * src/muscle-tab.c, src/muscle-tab.h: ... these and update
-       include.
-
 2009-10-07  Joel E. Denny  <jdenny@clemson.edu>
 
        Minor code cleanup.
-       * src/muscle_tab.c (MUSCLE_USER_NAME_CONVERT): Remove macro and
+       * src/muscle-tab.c (MUSCLE_USER_NAME_CONVERT): Remove macro and
        replace all uses with UNIQSTR_CONCAT.
        * src/uniqstr.c (uniqstr_vsprintf): New function.
        * src/uniqstr.h (uniqstr_vsprintf): Add prototype.
        (UNIQSTR_CONCAT, UNIQSTR_GEN_FORMAT, UNIQSTR_GEN_FORMAT_): New
        macros.
 
+2009-10-06  Joel E. Denny  <jdenny@clemson.edu>
+
+       * TODO (Complaint submessage indentation): New.
+
 2009-10-04  Joel E. Denny  <jdenny@clemson.edu>
 
        Minor code cleanup.
        message buffer, import and clean up memory management code
        from...
        (yyparse, yypush_parse): ... here.
-       * tests/regression.at (%error-verbose overflow): No longer an
-       expected failure.
+       * tests/regression.at (parse.error=verbose overflow): No longer
+       an expected failure.
 
 2009-09-23  Joel E. Denny  <jdenny@clemson.edu>
 
        yysyntax_error: test memory management more.
        * tests/atlocal.in (NO_WERROR_CFLAGS): New cpp macro.
-       * tests/regression.at (%error-verbose and YYSTACK_USE_ALLOCA):
-       New test group.
-       (%error-verbose overflow): New test group that reveals an
+       * tests/regression.at (parse.error=verbose and
+       YYSTACK_USE_ALLOCA): New test group.
+       (parse.error=verbose overflow): New test group that reveals an
        obscure bug.  Expected fail for now.
 
-2008-12-11  Akim Demaille  <demaille@gostai.com>
-
-       Pass the token type to yysyntax_error.
-       * data/yacc.c (yysyntax_error): Take the transated token instead
-       of the raw number.
-       Adjust callers.
-
-2008-12-11  Akim Demaille  <demaille@gostai.com>
+2009-10-04  Joel E. Denny  <jdenny@clemson.edu>
 
-       Simplify the i18n of the error messages.
-       * data/yacc.c (yysyntax_error): Rewrite, using a switch instead
-       of building dynamically the format string.
+       benchmarks: use %debug consistently among grammars.
+       * etc/bench.pl.in (generate_grammar_triangular): Do not activate
+       %debug by default.  It can affect the timings even if yydebug=0.
+       (generate_grammar_calc): For consistency with other grammars,
+       use YYDEBUG environment variable to set yydebug.
 
 2009-10-03  Joel E. Denny  <jdenny@clemson.edu>
 
        * tests/regression.at (parse-gram.y: LALR = IELR): New test
        group.
 
-2009-09-16  Akim Demaille  <demaille@gostai.com>
-
-       doc: comment changes.
-       * doc/bison.texinfo: Comment changes.
-
-2009-09-16  Akim Demaille  <demaille@gostai.com>
-
-       doc: spell checking.
-       * doc/bison.texinfo: here.
-
 2009-09-19  Alex Rozenman  <rozenman@gmail.com>
 
        Keep sub-messages aligned. Fix strings for translation.
        * tests/named-ref.at: Adjust test-cases.
        * NEWS (2.5): Add an announcement about named references.
 
+2009-09-17  Akim Demaille  <demaille@gostai.com>
+
+       doc: fixes.
+       * doc/bison.texinfo: here.
+       Reported by Alex Rozenman.
+
+2009-09-16  Akim Demaille  <demaille@gostai.com>
+
+       doc: lalr1.cc and variants.
+       * doc/bison.texinfo (Decl Summary): Document the "lex_symbol" and
+       "variant" %define variables.
+       (C++ Semantic Values): Split into...
+       (C++ Unions, C++ Variants): these.
+       The latter is new.
+       (C++ Parser Interface): Fix type names.
+       Document parser::syntax_error.
+       Document the fact that locations are not mandatory.
+       (C++ Scanner Interface): Split into...
+       (Split Symbols, Complete Symbols): these.
+       The later is new.
+       (Calc++ Parsing Driver): Use variants.
+       Add more comments.
+       Adjust style.
+       (Calc++ Parser): Declare all the tokens, no
+       longer accept raw characters.
+       Remove %union.
+       Adjust types and printers.
+       Remove destructors.
+       (Calc++ Scanner): Use make_<SYMBOL> functions.
+       Use strerror in error message.
+
+2009-09-16  Akim Demaille  <demaille@gostai.com>
+
+       doc: spell checking.
+       * doc/bison.texinfo: here.
+
+2009-09-16  Akim Demaille  <demaille@gostai.com>
+
+       doc: comment changes.
+       * doc/bison.texinfo: Comment changes.
+
+2009-09-16  Akim Demaille  <demaille@gostai.com>
+
+       lalr1.cc: factor the yytranslate_ invocation in make_SYMBOLS.
+       * data/c++.m4, data/lalr1.cc (parser::symbol_type): Change the
+       constructor to take a token_type instead of the (internal) symbol
+       number.
+       Call yytranslate_.
+       * data/variant.hh (b4_symbol_constructor_define_): Therefore,
+       don't call yytranslate_ here.
+
+2009-09-16  Akim Demaille  <demaille@gostai.com>
+
+       TODO: statistics.
+       * TODO (Figures): New.
+
 2009-09-13  Joel E. Denny  <jdenny@clemson.edu>
 
        tests: clean up push.at test group titles.
        comment, instead of saying "yyparse or yypush_parse", say either
        "yyparse" or "yypush_parse" depending on which it actually is.
 
-2009-09-03  Joel E. Denny  <jdenny@clemson.edu>
+2009-09-10  Joel E. Denny  <jdenny@clemson.edu>
 
-       Complain about unused %define variables and %code qualifiers.
-       * NEWS (2.5): Document.
-       * data/bison.m4 (b4_check_user_names): Complain instead of warn.
-       * doc/bison.texinfo (Decl Summary): Document complaint, and
-       improve %define documentation a little otherwise.
-       * tests/input.at (Reject unused %code qualifiers): Update.
-       (%define errors): Update.
-       (%define, --define, --force-define): Update.
-       (%define backward compatibility): Update.
-       (Unused %define api.pure): Update.
-       * tests/push.at (Push Parsing: Unsupported Skeletons): Update.
+       Fix --enable-gcc-warnings.
+       * src/parse-gram.y (%printer <param>): Handle param_none.
+
+2009-09-09  Akim Demaille  <demaille@gostai.com>
+
+       lalr1.cc: syntax_error as exceptions.
+       It is common to use sort of factories in the user actions.  These
+       factories may check some "syntactic" constraints that are not
+       enforced by the grammar itself.  This is possible using YYERROR
+       within the action itself.  Provide the user with a means to throw
+       a syntax_error exception.
+
+       * data/c++.m4 (b4_public_types_declare, b4_public_types_define):
+       Declare and define yy::parser::syntax_error.
+       * data/lalr1.cc: Include stdexcept.
+       (yy::parser::parse): Wrap the user action within a try/catch.
+       * data/glr.cc: Include stdexcept.
+
+2009-09-09  Akim Demaille  <demaille@gostai.com>
+
+       lalr1.cc: add missing "inline".
+       * data/c++.m4 (b4_public_types_define): Add missing inline to
+       implementations provided in headers.
+
+2009-09-09  Akim Demaille  <demaille@gostai.com>
+
+       %param: documentation.
+       * NEWS (2.6): Document %param, %lex-param, and %parse-param
+       changes.
+       * doc/bison.texinfo: Document that %lex-param and %parse-param
+       are n-ary.
+       Changes some examples to demonstrate it.
+       (Calc++ Parser): Use %param.
+
+2009-09-09  Akim Demaille  <demaille@gostai.com>
+
+       Regen.
+
+2009-09-09  Akim Demaille  <demaille@gostai.com>
+
+       style changes.
+       * src/parse-gram.y (add_param): Scope changes.
+
+2009-09-09  Akim Demaille  <demaille@gostai.com>
+
+       %parse: support several arguments.
+       * src/parse-gram.y (current_param): New.
+       (param_type): Add param_none.
+       (params): New nonterminal.
+       Use it.
+
+2009-09-09  Akim Demaille  <demaille@gostai.com>
+
+       Regen.
+
+2009-09-09  Akim Demaille  <demaille@gostai.com>
+
+       %param.
+       Provide a means to factor lex-param and parse-param common
+       declarations.
+
+       * src/parse-gram.y (param_type): New.
+       Define a %printer for it.
+       (add_param): Use it.
+       (%parse-param, %lex-param): Merge into...
+       (%parse): this new token.
+       Adjust the grammar to use it.
+       * src/scan-gram.l (RETURN_VALUE): New.
+       (RETURN_PERCENT_FLAG): Use it.
+       (RETURN_PERCENT_PARAM): New.
+       Use it to support %parse-param, %lex-param and %param.
 
 2009-09-03  Joel E. Denny  <jdenny@clemson.edu>
 
        rename variable "exact_mode" to "explicit_bracketing".
        * tests/named-ref.at: Adjust existing tests and add a new one.
 
+2009-09-04  Akim Demaille  <demaille@gostai.com>
+
+       Adjust synclines in src/parse-gram.[ch].
+       * tests/bison.in: Do some magic (including working around issues
+       with ylwrap) when this wrapper is used to compile
+       src/parse-gram.y.
+
+2009-09-03  Joel E. Denny  <jdenny@clemson.edu>
+
+       Complain about unused %define variables and %code qualifiers.
+       * NEWS (2.5): Document.
+       * data/bison.m4 (b4_check_user_names): Complain instead of warn.
+       * doc/bison.texinfo (Decl Summary): Document complaint, and
+       improve %define documentation a little otherwise.
+       * tests/input.at (Reject unused %code qualifiers): Update.
+       (%define errors): Update.
+       (%define, --define, --force-define): Update.
+       (%define backward compatibility): Update.
+       (Unused %define api.pure): Update.
+       * tests/push.at (Push Parsing: Unsupported Skeletons): Update.
+
+2009-09-03  Joel E. Denny  <jdenny@clemson.edu>
+
+       Don't suppress warnings about unused parse.error.
+       * data/bison.m4 (b4_error_verbose_flag): Don't examine value of
+       %define variable parse.error unless b4_error_verbose_flag is
+       actually expanded in a skeleton.
+
 2009-09-03  Akim Demaille  <demaille@gostai.com>
 
        * NEWS (2.4.2): Add "Internationalization" item.
        (Table of Symbols): Likewise.
        * src/ielr.c (LrType): Update documentation.
        * src/parse-gram.y (content.opt): Add production for ID.
-       * tests/calc.at: Remove quotes in most tests.
+       * tests/actions.at: Remove quotes in most tests.
+       * tests/calc.at: Likewise.
        * tests/existing.at: Likewise.
        * tests/input.at: Likewise.
        * tests/local.at: Likewise.
 2009-08-26  Joel E. Denny  <jdenny@clemson.edu>
 
        Actually handle the yytable zero value correctly this time.
-       * data/glr.c, data/lalr1.cc, data/lalr1.java, data/yacc.c: Don't
-       mention zero values in the YYTABLE comments.
+       * data/bison.m4 (b4_integral_parser_tables_map): Don't mention
+       zero values in the YYTABLE comments.
        * data/glr.c (yytable_value_is_error): Don't check for zero
        value.
        * data/lalr1.cc (yy_table_value_is_error_): Likewise.
 2009-08-25  Joel E. Denny  <jdenny@clemson.edu>
 
        More fixes related to last two patches.
+       * data/bison.m4 (b4_integral_parser_tables_map): Fix YYTABLE
+       comments: zero indicates syntax error not default action.
        * data/c.m4 (b4_table_value_equals): Comment that YYID must be
        defined.
-       * data/glr.c, data/lalr1.cc, data/lalr1.java, data/yacc.c: Fix
-       yytable comments: zero indicates syntax error not default
-       action.
        * data/glr.c (yyis_pact_ninf): Rename to...
        (yypact_value_is_default): ... this.
        (yyisDefaultedState): Update for rename.
 
 2009-08-19  Akim Demaille  <demaille@gostai.com>
 
-       doc: %initial-action to initialize yylloc.
+       tests: distcc compliance.
+       * tests/synclines.at (AT_SYNCLINES_COMPILE): Discard distcc's
+       error messages from the output.
+
+2009-08-19  Akim Demaille  <demaille@gostai.com>
+
+       variables: simplify the upgrade of namespace into api.namespace.
+
+       This patch simplifies "variables: rename namespace as
+       api.namespace", commit 67501061076ba46355cfd9f9361c7eed861b389c.
+       Suggested by Joel E. Denny in
+       http://lists.gnu.org/archive/html/bison-patches/2009-07/msg00006.html
+
+       * src/muscle-tab.c (muscle_percent_variable_update): New.
+       (muscle_percent_define_insert): Use it in replacement of the
+       previous tr invocation.
+       Remove variable_tr, no longer needed.
+       * data/bison.m4 (b4_percent_define_copy_, b4_percent_define_copy):
+       Remove.
+       * data/c++.m4: No longer handle namespace -> api.namespace.
+       * tests/input.at (%define backward compatibility): Check that
+       namespace is treated as api.namespace.
+
+2009-08-19  Akim Demaille  <demaille@gostai.com>
+
+       doc: %initial-action to initialize yylloc.
        Reported by Bill Allombert.
        * doc/bison.texinfo: Set fill-column to 76.
        (Location Type): Document the use of %initial-action to initialize
        yylloc.
 
+2009-08-19  Akim Demaille  <demaille@gostai.com>
+
+       lalr1.cc: use state_type.
+       * data/lalr1.cc (yysyntax_error_): Use state_type.
+       Move argument names into yy*.
+
+2009-08-19  Akim Demaille  <demaille@gostai.com>
+
+       lalr1.cc: get rid of yyparse's yystate.
+       yystate and yystack_[0].state are equal, keep only the latter.
+       The former was also used as a temporary variable to compute the
+       post-reduction state.  Move this computation into an auxiliary
+       function.
+
+       * data/glr.c (yyLRgotoState): Fuse variable definition and first
+       assignment.
+       * data/lalr1.cc (yy_lr_goto_state_): New.
+       (yyparse): Use it.
+       Replace remaining uses of yystate by yystate_[0].state.
+       Remove the former.
+
+2009-08-19  Akim Demaille  <demaille@gostai.com>
+
+       lalr1.cc: destroy $$ when YYERROR is called.
+       * data/lalr1.cc (yyreduce): Compute the resulting state before
+       running the user action so that yylhs is a valid symbol.
+       (yyerrorlab): Since yylhs is complete (it knows its type), we can
+       simply call yy_destroy_ to destroy $$ on YYERROR invocations.
+       * tests/c++.at (AT_CHECK_VARIANTS): Test YYERROR with variants.
+
 2009-08-18  Joel E. Denny  <jdenny@clemson.edu>
 
        maint: update for gnulib's recent update-copyright changes
        * tests/input.at (Numbered tokens): Recombine tests now that the
        output should be deterministic across multiple numbers.
 
+2009-08-12  Akim Demaille  <demaille@gostai.com>
+
+       tests: GCC 4.5 compliance.
+       * tests/synclines.at (AT_SYNCLINES_COMPILE): Adjust to GCC 4.5's
+       messages about #error.
+
+2009-08-12  Akim Demaille  <demaille@gostai.com>
+
+       build: fix the generation of the documentation.
+       Some of our targets use "bison --help", but they can't depend on
+       "bison" itself (to avoid additional requirements on the user), so
+       they used to call "make src/bison" in the commands.  Then
+       concurrent builds may fail: one make might be aiming one of its
+       jobs at compiling src/bison, and another job at generating the man
+       page.  If the latter is faster than the former, then we have two
+       makes that concurrently try to compile src/bison.
+
+       This might also be a more convincing explanation for the failure
+       described in the patch "build: fix paths".
+
+       * Makefile.am (SUFFIXES): Initialize.
+       * build-aux/move-if-change: New, symlink to gnulib's.
+       * build-aux/local.mk: Ship it.
+       * doc/common.x: Remove, merged into...
+       * doc/bison.x: here.
+       * doc/local.mk (doc/bison.help): New.
+       ($(CROSS_OPTIONS_TEXI)): Depend on it.
+       Use src/bison.
+       (.x.1): Replace with...
+       (doc/bison.1): this explicit, simpler, target.
+       (common_dep): Remove, inlined where appropriate.
+       (SUFFIXES, PREPATH): Remove, unused.
+
+2009-08-12  Akim Demaille  <demaille@gostai.com>
+
+       gnulib: improve prefixing.
+       * configure.ac (gl_PREFIXED_LIBOBJS): Don't rename it, rather,
+       change the value of...
+       (gl_LIBOBJS): this.
+       Adjust more variables.
+       * etc/prefix-gnulib-mk (prefix_assignment): Don't rename
+       gl_LIBOBJS.
+       (prefix): Also transform rules whose targets have slashes.
+       Use $prefix liberally.
+       Map @MKDIR_P@ to $(MKDIR_P).
+       Prefix directories that are mkdir'd.
+
+2009-08-12  Akim Demaille  <demaille@gostai.com>
+
+       build: fix paths.
+       When using $(top_builddir) inconsistently, Make (including GNU
+       Make) is sometimes confused.  As a result it may want to build
+       lib/libbison.la and $(top_builddir)/lib/libbison.la (the same
+       file, different names) concurrently, which, amusingly enough,
+       might end with:
+
+         ranlib lib/libbison.a
+         ranlib lib/libbison.a
+         make[2]: *** [lib/libbison.a] Segmentation fault
+
+       on OS X.
+
+       * doc/local.mk, src/local.mk: Do not use $(top_builddir) when not
+       needed.
+
 2009-08-12  Akim Demaille  <demaille@gostai.com>
 
        distcheck: fix.
 
 2009-08-10  Joel E. Denny  <jdenny@clemson.edu>
 
-       * tests/Makefile.am (TESTSUITE_AT): Add named-refs.at.
+       * tests/local.mk (TESTSUITE_AT): Add named-refs.at.
 
 2009-08-10  Joel E. Denny  <jdenny@clemson.edu>
 
 
        maint: automate b4_copyright updates.
        * Makefile.am (update-b4-copyright): New target rule.
-       * build-aux/Makefile.am (EXTRA_DIST): Add update-b4-copyright.
+       * build-aux/local.mk (EXTRA_DIST): Add update-b4-copyright.
        * build-aux/update-b4-copyright: New.
        * data/yacc.c: Remove stray characters around b4_copyright
        invocations.
        * src/scan-gram.l (SC_ESCAPED_CHARACTER): Actually use length
        variable.
 
-2009-07-24  Alex Rozenman  <rozenman@gmail.com>
-
-       Fix some memory leaks.
-       * src/named-ref.c: Add a pointer check (named_ref_free).
-       * src/scan-code.l: New function (variant_table_free). Called in
-       code_scanner_free.
-       * src/symlist.c: Call to named_ref_free (symbol_list_free).
-
 2009-07-24  Joel E. Denny  <jdenny@ces.clemson.edu>
 
        Warn about character literals not of length one.
        (SC_ESCAPED_CHARACTER): Warn if length is wrong.
        * tests/input.at (Bad character literals): New test group.
 
+2009-07-24  Alex Rozenman  <rozenman@gmail.com>
+
+       Fix some memory leaks.
+       * src/named-ref.c: Add a pointer check (named_ref_free).
+       * src/scan-code.l: New function (variant_table_free). Called in
+       code_scanner_free.
+       * src/symlist.c: Call to named_ref_free (symbol_list_free).
+
 2009-07-24  Joel E. Denny  <jdenny@ces.clemson.edu>
 
        * src/lalr.c (state_lookahead_tokens_count): Correct comment.
        do not distinguish between a missing value and an empty string
        value.
 
-2009-07-21  Joel E. Denny  <jdenny@ces.clemson.edu>
-
-       * m4/m4.m4: Make it a sym link to submodules/autoconf/m4/m4.m4.
-
 2009-07-15  Joel E. Denny  <jdenny@ces.clemson.edu>
 
        Revert unnecessary column realignment in --help output.
 
 2009-07-04  Alex Rozenman  <rozenman@gmail.com>
 
-       Alphabetical order in src/Makefile.am.
-       * src/Makefile.am: Adjust.
+       Alphabetical order in src/local.mk.
+       * src/local.mk: Adjust.
 
 2009-07-04  Alex Rozenman  <rozenman@gmail.com>
 
        Not only this is inefficient, this also builds incorrect sources
        with several extractions mixed together.
 
+2009-06-29  Akim Demaille  <demaille@gostai.com>
+
+       parse.error: fix.
+       * data/bison.m4: Move code related to specific variables after the
+       definition of the variable-maintaining macros so that we don't
+       "invoke" b4_percent_define_check_values before it is defined.
+
+2009-06-29  Akim Demaille  <demaille@gostai.com>
+
+       variables: parse.error
+
+       Implement, document, and test the replacement of %error-verbose
+       by %define parse.error "verbose".
+       * data/bison.m4 (b4_error_verbose_if): Reimplement to track the
+       values of the parse.error variable.
+       Make "simple" its default value.
+       Check the valid values.
+       * src/parse-gram.y: Use %define parse.error.
+       (PERCENT_ERROR_VERBOSE): New token.
+       Support it.
+       * src/scan-gram.l: Support %error-verbose.
+
+       * doc/bison.texinfo (Decl Summary): Replace the documentation of
+       %define error-verbose by that of %define parse.error.
+       * NEWS: Document it.
+
+       * tests/actions.at, tests/calc.at: Use parse.error instead of
+       %error-verbose.
+
 2009-06-27  Alex Rozenman  <rozenman@gmail.com>
 
        Implement support for named symbol references.
        hash: check insertion for memory exhaustion.
        * src/uniqstr.c (uniqstr_new): New.
 
+2009-06-24  Akim Demaille  <demaille@gostai.com>
+
+       variables: rename namespace as api.namespace.
+       Discussed in
+       http://lists.gnu.org/archive/html/bison-patches/2009-04/msg00033.html
+
+       * data/bison.m4 (b4_percent_define_copy_, b4_percent_define_copy):
+       New.
+       (b4_percent_define_use): New.
+       Use it where applicable.
+       * data/c++.m4: Replace uses of the variable "namespace" by
+       "api.namespace".
+       Default the latter to the former.
+       * doc/bison.texinfo (Decl Summary): Document "namespace" as
+       obsolete.
+       Document api.namespace.
+       Use @samp to document %define uses, keep @code for identifiers.
+       * NEWS: Likewise.
+       * tests/c++.at, tests/input.at: Test api.namespace instead of
+       namespace. (The tests passed with namespace.)
+
 2009-06-11  Akim Demaille  <demaille@gostai.com>
 
        style changes.
        * src/state.c (state_hash_insert): Check the return value of
        hash_insert.
 
+2009-06-11  Akim Demaille  <demaille@gostai.com>
+
+       tests: honor TESTSUITEFLAGS in every check target.
+       * tests/local.mk (RUN_TESTSUITE): New.
+       (check-local, installcheck-local, maintainer-check-g++)
+       (maintainer-check-posix, maintainer-check-valgrind): Use it.
+
 2009-06-10  Akim Demaille  <demaille@gostai.com>
 
        deterministic test suite.
        Use different file names for the three tests to make the
        maintenance easier.
 
+2009-06-10  Akim Demaille  <demaille@gostai.com>
+
+       gnulib: update.
+       * gnulib: Update to latest.
+       * lib/.cvsignore, lib/.gitignore, m4/.cvsignore,
+       * m4/.gitignore: Regen.
+       * src/symtab.c (symbol_from_uniqstr, semantic_type_from_uniqstr):
+       Call xalloc_die on hash_insert failures.
+       Requested by the new __warn_unused_result__ attribute of
+       hash_insert.
+
 2009-06-10  Akim Demaille  <demaille@gostai.com>
 
        deterministic user-token-number redeclaration errors.
 
 2009-05-25  Akim Demaille  <demaille@gostai.com>
 
-       gnulib: update.
-       * gnulib: Update to latest.
-       * lib/.cvsignore, lib/.gitignore, m4/.cvsignore,
-       * m4/.gitignore: Regen.
-       * src/symtab.c (symbol_from_uniqstr, semantic_type_from_uniqstr):
-       Call xalloc_die on hash_insert failures.
-       Requested by the new __warn_unused_result__ attribute of
-       hash_insert.
+       build: avoid ignored errors.
+       * doc/local.mk ($(CROSS_OPTIONS_TEXI)): Don't generate ignored
+       errors, they pollute the output.
 
 2009-05-22  Joel E. Denny  <jdenny@ces.clemson.edu>
 
        * NEWS (2.5): Add a new entry for that change.
        * doc/bison.texinfo (Decl Summary): Update %define entry.
        (Bison Options): Update -D/--define/-F/--force-define entry.
-       * src/muscle_tab.c (muscle_percent_define_insert): Implement.
-       * src/muscle_tab.h (muscle_percent_define_insert): Update
+       * src/muscle-tab.c (muscle_percent_define_insert): Implement.
+       * src/muscle-tab.h (muscle_percent_define_insert): Update
        comments.
        * tests/input.at (`%define errors'): Update.
        (`%define, --define, --force-define'): Update.
        * src/getargs.c (usage): Document -F/--force-define.  Realign
        options in output.
        (short_options, long_options, getargs): Parse -F/--force-define,
-       and update muscle_percent_define_insert invocation.
-       * src/muscle_tab.h (muscle_percent_define_how): New enum type.
+       and update muscle_percent_define_insert invocations.
+       * src/muscle-tab.h (muscle_percent_define_how): New enum type.
        (muscle_percent_define_insert): Add argument with that type.
-       * src/muscle_tab.c (muscle_percent_define_insert): Implement
+       * src/muscle-tab.c (muscle_percent_define_insert): Implement
        -F/--force-define behavior and priorities.
+       (muscle_percent_define_ensure): Update
+       muscle_percent_define_insert invocation.
        * src/parse-gram.y (prologue_declaration): Update
        muscle_percent_define_insert invocations.
        * tests/input.at (`%define, --define'): Rename to...
        Update some comments to make sense for -D.
        * data/bison.m4 (b4_check_user_names): In header comments, say
        "user occurrence" instead of "grammar occurrence".
-       * src/muscle_tab.h (muscle_percent_define_insert): Likewise.
+       * src/muscle-tab.h (muscle_percent_define_insert): Likewise.
        (muscle_percent_code_grow): Likewise just for consistency.
 
-2009-05-22  Joel E. Denny  <jdenny@ces.clemson.edu>
-
-       * data/c++.m4: Update copyright year.
-
 2009-05-20  Joel E. Denny  <jdenny@ces.clemson.edu>
 
        * data/c++.m4 (b4_namespace_close): Simplify slightly.
        * src/getargs.c (skeleton_arg): Remove now useless variable.
        Should help the compiler see that this printf-like call is sane.
 
+2009-05-15  Akim Demaille  <demaille@gostai.com>
+
+       Rename token.prefix as api.tokens.prefix.
+       Discussed here.
+       http://lists.gnu.org/archive/html/bison-patches/2009-05/msg00024.html.
+
+       * NEWS, data/bison.m4, data/c.m4, data/java.m4, doc/bison.texinfo,
+       * tests/c++.at, tests/calc.at, tests/java.at, tests/local.at
+       (token.prefix): Rename as...
+       (api.tokens.prefix): this.
+
 2009-05-11  Akim Demaille  <demaille@gostai.com>
 
        doc: use C++ headers.
        * doc/bison.texinfo (Calc++ Scanner): Prefer C++ headers to C
        headers.
 
-2009-05-05  Akim Demaille  <demaille@gostai.com>
-
-       fix hexadecimal token number support.
-       * src/scan-gram.l: Catch incorrect ids after hexadecimal numbers.
-
-2009-05-05  Akim Demaille  <demaille@gostai.com>
+2009-05-11  Akim Demaille  <demaille@gostai.com>
 
-       tests: check token numbers.
-       * tests/input.at (Numbered tokens): New.
+       doc: token.prefix
+       * doc/bison.simple (Decl Summary): Document token.prefix.
+       (Calc++ Parser): Various fixes.
+       Formatting changes.
+       Use token.prefix.
+       Introduce a macro TOKEN to shorten the code and make it more
+       readable.
+       (Calc++ Scanner): Adjust.
+       * NEWS (Variable token.prefix): New.
 
 2009-05-04  Akim Demaille  <demaille@gostai.com>
 
        * src/scan-gram.l({int}{id}): Report as an invalid identifier.
        * tests/input.at: Adjust.
 
-2009-05-04  Akim Demaille  <demaille@gostai.com>
-
-       space changes.
-       * src/scan-gram.l: Untabify to be robust to zealous editors.
-
 2009-05-04  Akim Demaille  <demaille@gostai.com>
 
        identifiers: dashes are letters.
        * data/c.m4 (b4_identification): Update comment.
        * data/yacc.c: Update access.
        * doc/bison.texinfo: Update.
-       * etc/bench.pl.in (bench_grammar): Update use.
+       * etc/bench.pl.in (bench_push_parser): Update use.
        * src/files.c (tr): Move to...
        * src/getargs.c, src/getargs.h (tr): ... here because I can't
        think of a better place to expose it.  My logic is that, for all
        Pacify ./configure --enable-gcc-warnings.
        * tests/input.at (Symbols): Prototype yyerror and yylex.
 
-2009-04-21  Akim Demaille  <demaille@gostai.com>
-
-       tests: check the use of dashes and periods in symbols.
-       * tests/input.at (Symbol): New test group.
-
 2009-04-29  Joel E. Denny  <jdenny@ces.clemson.edu>
 
        Document how `%define "var" "value"' is not M4-friendly.
        * src/parse-gram.y (variable): In comments here.
 
-2009-04-29  Joel E. Denny  <jdenny@ces.clemson.edu>
-
-       Add copyright updates missed during previous cherry pick.
-       * src/output.c: Here.
-       * src/parse-gram.y: Here.
-       * src/scan-gram.l: Here.
-
-2009-04-20  Akim Demaille  <demaille@gostai.com>
-
-       variables: accept dashes.
-       * src/scan-gram.l ({id}): Also accept dashes after the initial
-       letter.
-       ({directive}): Use {id}.
-       * src/parse-gram.y: Comment and formatting changes.
-       * doc/bison.texinfo (Symbols): Adjust the lexical definitions of
-       symbols.
-       * src/complain.h, src/complain.c (yacc_at): New.
-       * src/symtab.c (symbol_new): Use yacc_at to report inappropriate
-       symbol names.
-       * src/output.c (token_definitions_output): Do not #define token
-       names with dashes.
-
 2009-04-24  Joel E. Denny  <jdenny@ces.clemson.edu>
 
        Clean up recent patches a little.
        Suggested by Akim Demaille at
        <http://lists.gnu.org/archive/html/bison-patches/2009-04/msg00082.html>.
        * data/bison.m4 (_b4_percent_define_check_values): Implement.
-       * src/muscle_tab.c (muscle_percent_define_check_values): Implement.
+       * src/muscle-tab.c (muscle_percent_define_check_values): Implement.
        * tests/input.at (%define lr.default_reductions invalid values): Merge
        into...
        (%define enum variables): ... here, and update output.
        comments, and renaming %define lr.default_rules to %define
        lr.default_reductions.
        * NEWS (2.5): Update IELR documentation.
-       * data/glr.c, data/lalr1.cc, data/lalr1.java, data/yacc.c:
-       Adjust YYDEFACT and yydefact_ documentation.
+       * data/bison.m4 (b4_integral_parser_tables_map): Adjust YYDEFACT
+       documentation.
+       * data/glr.c, data/lalr1.java: Sync copyright dates.
        * doc/bison.texinfo (Decl Summary): Adjust lr.default_reductions
        and lr.type documentation.  Make some other wording
        improvements.
        * tests/reduce.at (AT_TEST_LR_DEFAULT_RULES): Rename to...
        (AT_TEST_LR_DEFAULT_REDUCTIONS): ... this, and update.
 
+2009-04-21  Akim Demaille  <demaille@gostai.com>
+
+       tests: check the use of dashes and periods in symbols.
+       * tests/input.at (Symbol): New test group.
+
 2009-04-21  Joel E. Denny  <jdenny@ces.clemson.edu>
 
        Document %define lr.type and lr.default_rules.
        (`%define lr.default_rules "consistent"'): Likewise.
        (`%define lr.default_rules "accepting"'): Likewise.
 
+2009-04-20  Akim Demaille  <demaille@gostai.com>
+
+       Formatting change.
+
+2009-04-20  Akim Demaille  <demaille@gostai.com>
+
+       bison: factoring.
+       * src/output.c (token_definitions_output): Use symbol_id_get
+       instead of duplicating its logic.
+       * TODO (YYERRCODE): Extend.
+
+2009-04-20  Akim Demaille  <demaille@gostai.com>
+
+       variables: prefer error-verbose to error_verbose.
+       * data/bison.m4 (b4_error_verbose_if): Based on error-verbose
+       instead of error_verbose.
+       * src/scan-gram.l (%error-verbose): Map to the error-verbose
+       variable.
+       * doc/bison.texinfo: Promote %define error-verbose instead of
+       %error-verbose.
+       * tests/actions.at: Prefer %define error-verbose to %error-verbose.
+
+2009-04-15  Akim Demaille  <demaille@gostai.com>
+
+       variables: accept dashes.
+       * data/bison.m4 (b4_percent_define_if_define_): Also map dashes to
+       underscores.
+       * src/scan-gram.l ({id}): Also accept dashes after the initial
+       letter.
+       ({directive}): Use {id}.
+       * src/parse-gram.y: Comment and formatting changes.
+       * doc/bison.texinfo (Symbols): Adjust the lexical definitions of
+       symbols.
+       * src/complain.h, src/complain.c (yacc_at): New.
+       * src/symtab.c (symbol_new): Use yacc_at to report inappropriate
+       symbol names.
+       * src/output.c (token_definitions_output): Do not #define token
+       names with dashes.
+
 2009-04-20  Akim Demaille  <demaille@gostai.com>
 
        Consistently refer to Yacc, not YACC.
        Document semicolon warnings.
        * NEWS (2.5): Here.
 
-2008-12-08  Akim Demaille  <demaille@gostai.com>
+2009-04-14  Akim Demaille  <demaille@gostai.com>
 
-       Fix portability issue in the test suite.
-       * tests/local.at (AT_MATCHES_CHECK): New.
-       Based on Perl instead of Sed.  Sed has too many portability
-       pitfalls, not ever Sed is GNU Sed.
-       * tests/actions.at (Fix user actions without a trailing semicolon):
-       Use it.
+       variables: use `parse.assert' instead of `assert'.
+       * TODO (assert): Remove.
+       * data/bison.m4 (b4_assert_if): Replace with...
+       (b4_parse_assert_if): this.
+       * data/lalr1.cc, data/variant.hh, tests/c++.at: Adjust.
+       * doc/bison.texinfo (Decl Summary): Document parse.assert.
 
-2008-12-07  Di-an Jan  <dianj@freeshell.org>
+2009-04-14  Akim Demaille  <demaille@gostai.com>
 
-       Implement the FIXME that ends an user action with a semicolon
-       if it seems necessary.
-       * src/scan-code.l (flex rules section): Flag cpp directive from
-       any `#' to the first unescaped end-of-line.  Semicolon is not
-       needed after `;', `{', '}', or cpp directives and is needed after
-       any other token (whitespaces and comments have no effect).
-       * tests/actions.at (Fix user actions without a trailing semicolon):
-       New test.
-       * tests/input.at (AT_CHECK_UNUSED_VALUES): Add semicolons to
-       to make user actions complete statements.
-       Adjust column numbers in error messages.
-       * tests/regression.at (Fix user actions without a trailing semicolon):
-       Remove.  Covered by new test.
+       variables: use `parse.trace' instead of `debug'.
+       * src/getargs.c (getargs): Map -t to %define trace.parse.
+       * src/scan-gram.l (%debug): Map to %define trace.parse.
+       * data/bison.m4 (b4_percent_define_if_define): Map `.' in variable
+       names to `_' in macro names.
+       (b4_debug_if): Replace with...
+       (b4_parse_trace_if): this.
+       * data/glr.c, data/glr.cc, data/lalr1.cc, data/lalr1.java,
+       * data/yacc.c: Adjust.
+       * doc/bison.texinfo (Decl Summary): Document %debug as obsoleted.
+       Use @code to label the variable list.
+       Document the variable parse.trace.
+       (Tracing): Promote the parse.trace variable.
+       * TODO: %printer is not documented.
 
 2009-04-14  Akim Demaille  <demaille@gostai.com>
 
 
 2009-04-06  Joel E. Denny  <jdenny@ces.clemson.edu>
 
-       * NEWS (2.5): Describe new -D/--define feature.
-
-2008-11-10  Akim Demaille  <demaille@gostai.com>
-
-       --trace=muscles
-       * src/getargs.h, src/getargs.c (trace_muscle): New.
-       (trace_types, trace_args): Support it.
-       * src/output.c (output_skeleton): Use it.
+       * NEWS (2.5): New section.  Describe new -D/--define feature.
 
-2008-11-10  Akim Demaille  <demaille@gostai.com>
+2009-04-06  Akim Demaille  <demaille@gostai.com>
 
-       muscles_output.
-       * src/output.c (muscles_output): New, extracted from...
-       (output_skeleton): here.
-       Adjust.
+       Regen.
+       * src/parse-gram.h, src/parse-gram.c: Regen.
 
-2008-11-21  Akim Demaille  <demaille@gostai.com>
+2009-04-06  Akim Demaille  <demaille@gostai.com>
 
-       Display the changes in cross-options.texi.
-       * build-aux/cross-options.pl ($sep): New, to separate items.
-       * doc/Makefile.am ($(srcdir)/cross-options.texi): Use diff to display
-       the changes.
+       rename muscle_tab.* as muscle-tab.* for consistency.
+       * src/muscle_tab.h, src/muscle_tab.c: Rename as...
+       * src/muscle-tab.h, src/muscle-tab.c: these.
+       * src/getargs.c, src/local.mk, src/main.c, src/output.c,
+       * src/parse-gram.y, src/reader.c, src/scan-code.l: Adjust.
 
-2008-11-20  Di-an Jan  <dianj@freeshell.org>
+2009-04-06  Akim Demaille  <demaille@gostai.com>
 
-       Improves options in the manual.
-       * doc/bison.texinfo (-g, -x): Add space before argument.
-       (Option Cross Key): Implement FIXME: listing directives also.
-       * build-aux/cross-options.pl:  Read from <STDIN> rather than <>.
-       (Short Option): Special case -d.  Put arguments inside @option.
-       (Bison Directive): Add column, automatically extracted from
-       src/scan-gram.l (actual name passed as the first argument)
-       with special case for %define.
-       * doc/Makefile.am (doc/cross-options.texi): Pass src/scan-gram.l
-       to build-aux/cross-options.pl.
-       * src/getargs.c (usage): Document limitations of cross-options.pl.
-       * src/scan-gram.l: Likewise.
+       Makefile: introduce $(BISON).
+       * src/local.mk (BISON): New.
+       (YACC): Use it.
 
-2009-02-25  Akim Demaille  <demaille@gostai.com>
+2009-04-06  Akim Demaille  <demaille@gostai.com>
 
-       Copyright years.
-       * data/glr.c: Add 2007 and 2008 here, consistenly with the comments.
+       parser: handle %locations as %define locations.
+       * src/getargs.h, src/getargs.c (locations_flag): Remove.
+       * src/getargs.c, src/scan-code.l: Use muscle_percent_define_ensure
+       to set "locations" to true.
+       * src/output.c (prepare): Don't output "locations".
+       * src/scan-gram.l (%locations): Handle it as a %<flag>.
+       * src/parse-gram.y: It's no longer a token.
+       Don't handle it.
+       * data/bison.m4 (b4_locations_if): Define it with
+       b4_percent_define_if_define.
+       * data/c.m4, data/glr.cc: Adjust.
 
-2008-12-08  Akim Demaille  <demaille@gostai.com>
+2009-04-06  Akim Demaille  <demaille@gostai.com>
 
-       Install autoconf as a submodule to get m4sugar.
-       * .gitmodules: Add submodules/autoconf.
-       * data/m4sugar/foreach.m4, data/m4sugar/m4sugar.m4: Now links into
-       submodules/autoconf.
+       Regen.
+       * src/parse-gram.c: Regen.
 
-2008-11-17  Joel E. Denny  <jdenny@ces.clemson.edu>
+2009-04-06  Akim Demaille  <demaille@gostai.com>
 
-       Simplify last patch slightly.
-       * src/getargs.c (getargs): Here.
+       muscle: factor the handling of obsolete of obsolete directives.
+       Suggested by Joel E. Denny.
 
-2008-11-17  Joel E. Denny  <jdenny@ces.clemson.edu>
+       * src/muscle_tab.h, src/muscle_tab.c (muscle_percent_define_ensure):
+       New, extracted from...
+       * src/parse-gram.y (prologue_declaration: pure-parser): here.
+       Remove it.
+       (prologue_declaration: "%<flag>"): Use
+       muscle_percent_define_ensure.
+       (%error-verbose, %pure-parser): No longer tokens.
+       * src/scan-gram.l (pure-parser): Return as a %<flag>.
 
-       Fix last warning from --enable-gcc-warnings.
-       * src/getargs.c (getargs): Don't assign const address to non-const
-       pointer.
+2009-04-06  Joel E. Denny  <jdenny@ces.clemson.edu>
 
-2008-11-17  Di-an Jan  <dianj@freeshell.org>
+       Fix options documentation.
+       * build-aux/cross-options.pl: As in --help output, write optional
+       arguments as [=ARG] not =[ARG].
+       * doc/bison.texinfo (Bison Options): Add -W/--warnings argument.
 
-       Handle --enable-gcc-warnings.
-       * src/getargs.c (command_line_location): Set parameters to void.
+2009-04-04  Joel E. Denny  <jdenny@ces.clemson.edu>
 
-2008-11-11  Akim Demaille  <demaille@gostai.com>
+       Replace BISON_PROG_GNU_M4 with Autoconf's AC_PROG_GNU_M4.
+       If the first m4 in $PATH is wrong, it keeps looking.  Moreover, its
+       requirements for a correct m4 are stricter.
+       * m4/m4.m4: Make it a symbolic link to submodules/autoconf/m4/m4.m4.
+       * configure.ac: Update to use AC_PROG_GNU_M4.
+       Reported by Eric Blake.
 
-       AT_FULL_COMPILE.
-       * tests/actions.at, tests/regression.at: Use it.
+2009-04-03  Joel E. Denny  <jdenny@ces.clemson.edu>
 
-2008-11-07  Akim Demaille  <demaille@gostai.com>
+       Help with updating web manual.
+       * HACKING: Incorporate instructions from gnulib/doc/README.
+       * bootstrap.conf (gnulib_modules): Add gendocs.
 
-       Pass command line location to skeleton_arg and language_argmatch.
-       * src/getargs.h, src/getargs.c (skeleton_arg, language_argmatch):
-       The location argument is now mandatory.
-       Adjust all dependencies.
-       (getargs): Use command_line_location.
+2009-04-03  Akim Demaille  <demaille@gostai.com>
+
+       Regen.
+       * src/parse-gram.h, src/parse-gram.c: Regen.
+
+2009-04-03  Akim Demaille  <demaille@gostai.com>
+
+       Factor %FLAG at scan level.
+       * src/parse-gram.y (PERCENT_DEBUG, PERCENT_ERROR_VERBOSE): Token
+       definitions and associated rules, replaced by....
+       (PERCENT_FLAG): this new token type, and rule.
+       * src/scan-gram.l (RETURN_PERCENT_FLAG): New.
+       Use it for %debug and %error-verbose.
+
+2009-04-03  Akim Demaille  <demaille@gostai.com>
+
+       Regen.
+       * src/parse-gram.h, src/parse-gram.c: Regen.
+
+2009-04-03  Akim Demaille  <demaille@gostai.com>
+
+       Treat %debug as %define debug.
+       * data/bison.m4 (b4_debug_if): New.
+       * data/glr.c, data/glr.cc, data/lalr1.cc, data/yacc.c,
+       * data/lalr1.java: Use it instead of b4_debug_flag.
+       * src/getargs.h, src/getargs.c (debug_flag): Remove.
+       * src/output.c (prepare): Don't output it.
+       * src/parse-gram.y: Treat %debug as %define debug.
+
+2009-04-03  Akim Demaille  <demaille@gostai.com>
+
+       Treat %error-verbose as %define error_verbose.
+       This allows to pass -Derror_verbose on the command line.  Better
+       yet, it allows to pass -Derror_verbose=$(ERROR_VERBOSE), with
+       ERROR_VERBOSE being defined as false or true.
+       * data/bison.m4 (b4_percent_define_if_define): Instead of relying
+       on b4_percent_define_ifdef, for does not check the defined value,
+       but only whether the symbol is defined, rely on
+       b4_percent_define_flag_if, so that a value of "false" is processed
+       as a false.
+       If not defined, define the flag to "false".
+       (b4_error_verbose_if): New.
+       * data/glr.c, data/lalr1.cc, data/yacc.c: Use it instead of
+       b4_error_verbose_flag.
+       * src/getargs.h, src/getargs.c (error_verbose_flag): Remove.
+       * src/output.c (prepare): Don't output it.
+       * src/parse-gram.y (%error-verbose): Treat as %define error_verbose.
 
-2008-11-07  Akim Demaille  <demaille@gostai.com>
-
-       -D, --define.
-       * src/getargs.c (usage): Document -D.
-       Fix help string for --locations.
-       (command_line_location): New.
-       (short_options, long_options, getargs): Support -D, --define.
-       (getargs): Move -d support at the right place.
-       * doc/bison.texinfo (Bison Options): Update.
-       * tests/input.at (%define, --define): New.
-
-2008-11-07  Akim Demaille  <demaille@gostai.com>
-
-       Initialize the muscle table before parsing the command line.
-       * src/getargs.c (quotearg.h, muscle_tab.h): Include.
-       (getargs): Define file_name.
-       * src/main.c (main): Initialize muscle_tab before calling
-       getargs.
-       * src/muscle_tab.c (muscle_init): No longer define file_name, as
-       its value is not available yet.
-
-2008-11-09  Akim Demaille  <demaille@gostai.com>
-
-       Require the generation of parse-gram.output.
-       * src/Makefile.am (YACC): Pass --report=all.
-
-2009-04-06  Joel E. Denny  <jdenny@ces.clemson.edu>
-
-       * NEWS (2.5): New stub.
-
-2009-04-06  Joel E. Denny  <jdenny@ces.clemson.edu>
-
-       Fix options documentation.
-       * build-aux/cross-options.pl: As in --help output, write optional
-       arguments as [=ARG] not =[ARG].
-       * doc/bison.texinfo (Bison Options): Add -W/--warnings argument.
-
-2008-11-07  Akim Demaille  <demaille@gostai.com>
-
-       Fix --help.
-       * src/getargs.c (usage): Fix help string for -W.
-
-2008-11-07  Akim Demaille  <demaille@gostai.com>
-
-       Handle more general types of option arguments.
-       * build-aux/cross-options.pl: The argument ends at the first
-       space, not the first non-symbol character.
-       Use @var for each word appearing the argument description.
-
-2009-04-04  Joel E. Denny  <jdenny@ces.clemson.edu>
-
-       Remove spurious initial empty lines.
-       * data/location.cc: End the @output lines with an @.
-
-2008-11-04  Akim Demaille  <demaille@gostai.com>
-
-       Remove spurious initial empty lines.
-       * data/glr.c, data/glr.cc, data/lalr1.cc, data/lalr1.java,
-       * data/yacc.c: End the @output lines with an @.
-
-2009-04-04  Joel E. Denny  <jdenny@ces.clemson.edu>
-
-       Replace BISON_PROG_GNU_M4 with Autoconf's AC_PROG_GNU_M4.
-       If the first m4 in $PATH is wrong, it keeps looking.  Moreover, its
-       requirements for a correct m4 are stricter.
-       * m4/m4.m4: Replace with Autoconf 2.63's m4/m4.m4.
-       * configure.ac: Update to use AC_PROG_GNU_M4.
-       Reported by Eric Blake.
-
-2009-04-03  Joel E. Denny  <jdenny@ces.clemson.edu>
-
-       Help with updating web manual.
-       * HACKING: Incorporate instructions from gnulib/doc/README.
-       * bootstrap.conf (gnulib_modules): Add gendocs.
-
-2009-04-03  Joel E. Denny  <jdenny@ces.clemson.edu>
+2009-04-03  Joel E. Denny  <jdenny@ces.clemson.edu>
 
        Fix strange %define locations for default values.
        Reported by Akim Demaille at
        * tests/skeletons.at (%define Boolean variables: invalid skeleton
        defaults): Update output.
 
-2008-11-07  Akim Demaille  <demaille@gostai.com>
-
-       Locations without columns for command line arguments.
-       * src/location.c (location_print): Don't display negative columns.
-       * src/location.h: Document this.
-
-2009-02-03  Joel E. Denny  <jdenny@ces.clemson.edu>
+2009-04-03  Joel E. Denny  <jdenny@ces.clemson.edu>
 
-       Add reminder about uploading public key to keys.gnupg.net.
-       * HACKING (Release Procedure): Here.
+       Pacify ./configure --enable-gcc-warnings.
+       * Makefile.am (AM_CFLAGS): Remove $(WERROR_CFLAGS) because many files
+       in lib won't compile with it.
+       * src/local.mk (src_bison_CFLAGS): Use $(WERROR_CFLAGS) here only.
 
 2009-03-31  Akim Demaille  <demaille@gostai.com>
 
 
        gnulib: update.
        * gnulib: Update to latest.
-       * lib/Makefile.am (AM_CPPFLAGS): It is now defined by gnulib, so
-       use +=.
+       * src/local.mk (AM_CFLAGS): Move to...
+       * Makefile.am: here.
+       * etc/prefix-gnulib-mk (prefix_assignment): Also transform
+       AM_CFLAGS.
+
+2009-03-02  Akim Demaille  <demaille@gostai.com>
+
+       Comment changes.
+
+2009-03-02  Akim Demaille  <demaille@gostai.com>
+
+       Share b4_yytranslate_define.
+       * data/lalr1.cc (b4_yytranslate_define): Move to...
+       * data/c++.m4: here.
+
+2009-03-02  Akim Demaille  <demaille@gostai.com>
+
+       Use locations in the variant example.
+       Yes, this obfuscates the point of this example, variants only.
+       But glr.cc cannot work (yet?) without locations.  This change
+       makes it easier to use this example with glr.cc.
+
+       * examples/variant.yy (assert): %define it.
+       (locations): Request them.
+       (yylex): Bind the location to the stage.
+
+2009-03-02  Akim Demaille  <demaille@gostai.com>
+
+       Dub make_TOKEN as a public type interface.
+       * data/c++.m4 (b4_symbol_constructor_declare)
+       (b4_symbol_constructor_define): New empty stubs.
+       (b4_public_types_declare, b4_public_types_define): Use them.
+       * data/lalr1.cc (b4_symbol_constructor_declare)
+       (b4_symbol_constructor_declare_)
+       (b4_symbol_constructor_define_, b4_symbol_constructor_define):
+       Move to...
+       * data/variant.hh: here.
+       Remove the "b4_variant_if" parts, as variant.hh is loaded only if
+       needed.
+       * data/lalr1.cc: No longer invoke b4_symbol_constructor_define and
+       b4_symbol_constructor_declare, as it is now done by
+       b4_public_types_define and b4_public_types_declare.
+
+2009-03-02  Akim Demaille  <demaille@gostai.com>
+
+       Coding style changes.
+       * data/lalr1.cc (b4_symbol_constructor_declaration_)
+       (b4_symbol_constructor_declarations)
+       (b4_symbol_constructor_definition_)
+       (b4_symbol_constructor_definitions)
+       (b4_yytranslate_definition): Rename as...
+       (b4_symbol_constructor_declare_)
+       (b4_symbol_constructor_declare)
+       (b4_symbol_constructor_define_)
+       (b4_symbol_constructor_define)
+       (b4_yytranslate_define): these.
+       * data/variant.hh (b4_variant_definition): Rename as...
+       (b4_variant_define): this.
+
+2009-03-02  Akim Demaille  <demaille@gostai.com>
+
+       Factor b4_assert_if, b4_lex_symbol_if, and b4_variant_if.
+       * data/bison.m4 (b4_percent_define_if_define): New.
+       * data/c++.m4 (b4_variant_if): Move to...
+       * data/bison.m4: Here, using b4_percent_define_if_define.
+       * data/lalr1.cc (b4_assert_if, b4_lex_symbol_if): Move to...
+       * data/bison.m4: Here, using b4_percent_define_if_define.
+
+2009-03-02  Akim Demaille  <demaille@gostai.com>
+
+       Dub symbol_type_base as a public type.
+       * data/c++.m4 (b4_public_types_declare): Now define
+       symbol_type_base and symbol_type.
+       (b4_public_types_define): New.
+       In both cases, the definitions are taken verbatim from lalr1.cc.
+       * data/lalr1.cc: Adjust.
+
+2009-03-02  Akim Demaille  <demaille@gostai.com>
+
+       b4_public_types_declare.
+       * data/c++.m4 (b4_public_types_declare): New.
+       * data/glr.cc, data/lalr1.cc: Use it.
+
+2009-03-02  Akim Demaille  <demaille@gostai.com>
+
+       b4_semantic_type_declare.
+       * data/c++.m4 (b4_semantic_type_declare): New.
+       Factors and generalizes what was in glr.cc and lalr1.cc.
+       * data/variant.hh (b4_semantic_type_declare): Redefine it for
+       variants.
+       * data/lalr1.cc, data/glr.cc: Use it.
+
+2009-02-26  Akim Demaille  <demaille@gostai.com>
+
+       Upgrade gnulib.
+       * gnulib: Upgrade from master.
+       * lib/.cvsignore, lib/.gitignore, m4/.cvsignore, m4/.gitignore:
+       Regen.
+
+2009-02-25  Akim Demaille  <demaille@gostai.com>
+
+       Remove useless arguments.
+       * data/glr.c (yy_reduce_print): $$ and @$ are not used and not
+       relevant.
+
+2009-02-25  Akim Demaille  <demaille@gostai.com>
+
+       Comment changes.
+       * data/lalr1.cc: here.
+
+2009-02-25  Akim Demaille  <demaille@gostai.com>
+
+       Fix glr.cc's debug level handling.
+       * data/glr.cc (yydebug_): Remove, as it is actually yydebug from
+       glr.c which is used.
+       (debug_level, set_debug_level): Adjust.
+
+2009-02-25  Akim Demaille  <demaille@gostai.com>
+
+       Copyright years.
+       * data/glr.c: Add 2007 and 2008 here, consistenly with the comments.
+
+2009-02-25  Akim Demaille  <demaille@gostai.com>
+
+       Style changes.
+       * etc/bench.pl.in (generate_grammar_list): Consitently use
+       location_type, not yy::location.
+
+2009-02-25  Akim Demaille  <demaille@gostai.com>
+
+       Comment change.
+       * data/lalr1.cc: here.
+
+2009-02-19  Akim Demaille  <demaille@gostai.com>
+
+       Make yyparser::error public.
+       * data/lalr1.cc: here.
+       There is no good reason to keep it private (and it is convenient
+       to use it from the scanner for instance).  It is already public in
+       glr.cc.
+
+2009-02-19  Akim Demaille  <demaille@gostai.com>
+
+       Comment changes.
+       * data/glr.cc: here.
+
+2009-02-19  Akim Demaille  <demaille@gostai.com>
+
+       Remove trailing blanks.
+       The epilogue has its own ending \n, no need to add another.
+
+       * data/glr.c, data/lalr1.java, data/yacc.c: dnl when outputing the
+       epilogue.
+       * data/glr.cc: dnl when extending the epilogue.
+       Remove stray "private:".
+
+2009-02-19  Akim Demaille  <demaille@gostai.com>
+
+       Use b4_c_modern.
+       * data/c.m4 (b4_c_function_decl): Here.
+
+2009-02-19  Akim Demaille  <demaille@gostai.com>
+
+       Comment changes.
+       * data/lalr1.cc: here.
+
+2009-02-19  Akim Demaille  <demaille@gostai.com>
+
+       Extract variant.hh
+       * data/variant.hh: New, extracted from...
+       * data/lalr1.cc: here.
+       Adjust.
+       * data/local.mk: Adjust.
+
+2009-02-19  Akim Demaille  <demaille@gostai.com>
+
+       Extract stack.hh from lalr1.cc.
+       * data/stack.hh: New.
+       * data/lalr1.cc: Extract from here.
+       * data/local.mk: Adjust.
+
+2009-02-03  Joel E. Denny  <jdenny@ces.clemson.edu>
+
+       Add reminder about uploading public key to keys.gnupg.net.
+       * HACKING (Release Procedure): Here.
+
+2009-01-28  Akim Demaille  <demaille@gostai.com>
+
+       * NEWS: Update information about 2.4.1 and 2.4.2.
+
+2008-11-04  Akim Demaille  <demaille@gostai.com>
+
+       Reformat NEWS.
+       * NEWS: Use more outline-mode markup.
+       Suggested by Jim Meyering.
 
 2009-01-08  Akim Demaille  <demaille@gostai.com>
 
        * tests/java.at: Use $EGREP instead of egrep.
        Use AT_CHECK's ignore instead of grep's -q.
 
-2008-12-11  Joel E. Denny  <jdenny@ces.clemson.edu>
+2008-12-11  Akim Demaille  <demaille@gostai.com>
+
+       Pass the token type to yysyntax_error.
+       * data/yacc.c (yysyntax_error): Take the transated token instead
+       of the raw number.
+       Adjust callers.
+       * TODO: Update.
 
-       Version 2.4.1.
-       * NEWS: Set version and date.
-       * lib/Makefile.am: Update copyright year.
-       * tests/atlocal.in: Update copyright year.
+2008-12-11  Akim Demaille  <demaille@gostai.com>
 
-2008-12-11  Joel E. Denny  <jdenny@ces.clemson.edu>
+       Formatting changes.
+       * data/glr.c: Formatting changes.
 
-       Semicolon feature removal is not about future language support.
-       * NEWS: The semicolon feature is no longer active for newer languages,
-       so don't claim that it causes trouble for them.
+2008-12-11  Akim Demaille  <demaille@gostai.com>
 
-2008-12-11  Joel E. Denny  <jdenny@ces.clemson.edu>
+       Propagate i18n changes into glr.c.
+       * TODO: Update.
+       * data/glr.c (yyreportSyntaxError): Use "switch" instead of
+       building the error message format dynamically.
+       * data/lalr1.java: Formatting changes.
 
-       * gnulib: Update submodule to HEAD.
+2008-12-11  Akim Demaille  <demaille@gostai.com>
 
-2008-12-09  Akim Demaille  <demaille@gostai.com>
+       Use testsuite -C.
+       * tests/local.mk: Replace "cd && testsuite" by "testsuite -C".
+       Solves problems when top_srcdir is an absolute path.
+       Suggested by Eric Blake.
+       * configure.ac: Require Autoconf 2.62.
+
+2008-12-11  Akim Demaille  <demaille@gostai.com>
+
+       Simplify the i18n of the error messages.
+       * data/lalr1.cc: Comment changes.
+       * data/yacc.c (yysyntax_error): Rewrite, using a switch as in
+       lalr1.cc instead of building dynamically the format string.
+
+2008-12-08  Akim Demaille  <demaille@gostai.com>
+
+       Fix portability issue in the test suite.
+       * tests/local.at (AT_MATCHES_CHECK): New.
+       Based on Perl instead of Sed.  Sed has too many portability
+       pitfalls, not ever Sed is GNU Sed.
+       * tests/actions.at (Fix user actions without a trailing semicolon):
+       Use it.
+
+2008-12-08  Akim Demaille  <demaille@gostai.com>
 
        Update data/README.
        * data/README: Document glr.cc, lalr1.java, m4sugar and xslt.
 
+2008-12-08  Akim Demaille  <demaille@gostai.com>
+
+       Install autoconf as a submodule to get m4sugar.
+       * .gitmodules: Add submodules/autoconf.
+       * data/m4sugar/foreach.m4, data/m4sugar/m4sugar.m4: Now links into
+       submodules/autoconf.
+
+2008-12-08  Akim Demaille  <demaille@gostai.com>
+
+       Test token.prefix in all the skeletons.
+       * data/java.m4 (b4_token_enum): Use the token.prefix.
+       * tests/local.at (AT_BISON_OPTION_PUSHDEFS): Define AT_TOKEN_PREFIX.
+       * tests/calc.at (_AT_DATA_CALC_Y): Use it.
+       Add checks for yacc.c, glr.c, lalr1.cc and glr.cc.
+       * tests/java.at: Comment changes.
+       (AT_CHECK_JAVA_MINIMAL): Define the END token.
+       (Java parser class and package names): Add token.prefix check.
+
+2008-12-08  Akim Demaille  <demaille@gostai.com>
+
+       Fix regeneration of atconfig.
+       * tests/local.mk (tests/atconfig): The rule was incorrect, but
+       remove it: now that there is no tests/Makefile.am, the top-level
+       Makefile properly updates atconfig when needed.
+
+2008-12-07  Di-an Jan  <dianj@freeshell.org>
+
+       Implement the FIXME that ends an user action with a semicolon
+       if it seems necessary.
+       * src/scan-code.l (flex rules section): Flag cpp directive from
+       any `#' to the first unescaped end-of-line.  Semicolon is not
+       needed after `;', `{', '}', or cpp directives and is needed after
+       any other token (whitespaces and comments have no effect).
+       * tests/actions.at (Fix user actions without a trailing semicolon):
+       New test.
+       * tests/input.at (AT_CHECK_UNUSED_VALUES): Add semicolons to
+       to make user actions complete statements.
+       Adjust column numbers in error messages.
+       * tests/regression.at (Fix user actions without a trailing semicolon):
+       Remove.  Covered by new test.
+
+2008-12-07  Akim Demaille  <demaille@gostai.com>
+
+       Update gnulib.
+       * gnulib: Update from master.
+
 2008-12-05  Eric Blake  <ebb9@byu.net>
 
+       Avoid compiler warning.
+       * src/output.c (muscle_insert_item_number_table): Delete unused
+       function.
+
+2008-12-02  Eric Blake  <ebb9@byu.net>
+
        Build testsuite with newer autoconf.
        * tests/output.at (m4_expand): Don't override in newer autoconf,
        where the underlying implementation changed.
        (_AT_VERBOSE_GLR_STDERR): Expand to double-quoted strings,
        since some of them contain unbalanced ')'.
 
-2008-11-19  Joel E. Denny  <jdenny@ces.clemson.edu>
+2008-12-01  Akim Demaille  <demaille@gostai.com>
 
-       * NEWS: Clarify a little.
+       Use b4_symbol for printers and destructors everywhere.
+       * data/bison.m4 (b4_symbol_action_location): New.
+       * data/c.m4 (b4_symbol_actions): Remove.
+       Adjust all callers to use by b4_symbol_foreach and the corresponding
+       b4_symbol_printer/destructor macro.
+       * data/glr.cc: Adjust.
+       * data/lalr1.java: Adjust the %destructor sanity check.
+       * src/output.c (symbol_code_props_output): Remove, we no longer
+       need the b4_symbol_printers/destructors tables.
 
-2008-11-19  Joel E. Denny  <jdenny@ces.clemson.edu>
+2008-12-01  Akim Demaille  <demaille@gostai.com>
 
-       * NEWS: Update for recent changes.
+       Use b4_symbol_case_.
+       * data/lalr1.cc, data/bison.m4 (b4_symbol_action): Use
+       b4_symbol_case_.
 
-2008-11-18  Joel E. Denny  <jdenny@ces.clemson.edu>
+2008-12-01  Akim Demaille  <demaille@gostai.com>
 
-       Fix unexpanded macros in GLR defines file.
-       Reported by Csaba Raduly at
-       <http://lists.gnu.org/archive/html/bug-bison/2008-11/msg00048.html>.
-       * THANKS (Csaba Raduly): Add.
-       * data/glr.c: Fix overquoting on b4_prefix for yylval and yylloc.
-       * tests/calc.at (_AT_DATA_CALC_Y): If %defines is specified, generate
-       lexer in a separate module that includes the defines file.
-       (AT_CHECK_CALC): Use AT_FULL_COMPILE and request compilation of lexer
-       source.
-       * tests/local.at (_AT_BISON_OPTION_PUSHDEFS): Push AT_DEFINES_IF.
-       Adjust AT_LOC and AT_VAL to use AT_NAME_PREFIX.
-       (AT_BISON_OPTION_POPDEFS): Pop AT_DEFINES_IF.
-       (AT_DATA_SOURCE_PROLOGUE): New.
-       (AT_DATA_GRAMMAR_PROLOGUE): Use AT_DATA_SOURCE_PROLOGUE.
-       (AT_DATA_SOURCE): New.
-       (AT_FULL_COMPILE): New, copied from master branch and extended to
-       support an additional source file.
+       Move b4_symbol based macro to bison.m4.
+       * data/lalr1.cc (b4_symbol_, b4_symbol, b4_symbol_if)
+       (b4_symbol_action, b4_symbol_destructor, b4_symbol_printer)
+       (b4_symbol_case_, b4_symbol_foreach, b4_type_action_)
+       (b4_type_foreach): Move to...
+       * data/bison.m4: Here.
+       * data/lalr1.cc (b4_symbol_action): Specialize for C++: use
+       b4_symbol_value_template instead of b4_symbol_value.
 
-2008-11-17  Joel E. Denny  <jdenny@ces.clemson.edu>
+2008-12-01  Akim Demaille  <demaille@gostai.com>
 
-       Don't let maintainer-*-check targets force a version update.
-       * cfg.mk (_is-dist-target): Implement.  maintainer-check* was already
-       handled.
+       b4_symbol/type_foreach.
+       * data/lalr1.cc (b4_symbol_foreach, b4_type_foreach): New.
+       Use them.
 
-2008-11-17  Di-an Jan  <dianj@freeshell.org>
+2008-12-01  Akim Demaille  <demaille@gostai.com>
+
+       Use the symbol properties to output the printer/destructor for lalr1.cc.
+       Instead of defining complex list of tuples to define various
+       properties of the symbols, we now prefer to define symbols as
+       "structs" in m4: using the symbol key (its number), and the
+       property name, b4_symbol gives it value.  Use this to handle
+       destructors and printers.
+
+       * src/output.c (CODE_PROP): New.
+       (prepare_symbol_definitions): Use it to define the printer and
+       destructor related attributes of the symbols.
+       * data/lalr1.cc (b4_symbol_actions): Rename as...
+       (b4_symbol_action): this.
+       Use b4_symbol instead of 6 arguments.
+       (b4_symbol_printer, b4_symbol_destructor): New.
+       Use them instead of b4_symbol_actions.
+
+2008-12-01  Akim Demaille  <demaille@gostai.com>
+
+       Avoid capturing variables too easily.
+       * src/muscle_tab.h (MUSCLE_INSERT_BOOL, MUSCLE_OBSTACK_SGROW): Use
+       v__ and p__ instead of v and p.
+
+2008-12-01  Akim Demaille  <demaille@gostai.com>
+
+       Remove spurious empty line before syncline.
+       * data/bison.m4 (b4_syncline): Don't output an empty line before
+       the output.
+
+2008-11-26  Akim Demaille  <demaille@gostai.com>
+
+       Convert lib/Makefile.am into lib/local.mk.
+       The real problem is rather gnulib.mk, which itself is extracted
+       from a Makefile.am that gnulib expects to the "recursive".  The
+       tool prefix-gnulib-mk converts such a gnulib.mk to be
+       non-recursive.  Also, some AC_SUBST variables need to be adjusted.
+
+       * etc/prefix-gnulib-mk: New.
+       * bootstrap (slurp): Use it to convert further gnulib.mk.
+       No longer try to avoid re-creation of lib/gnulib.mk as the changes
+       are deeper.
+       * lib/Makefile.am: Rename as...
+       * lib/local.mk: this.
+       Adjust to be prefixed.
+       * Makefile.am, configure.ac: Adjust.
+       * src/local.mk (AM_CPPFLAGS): Extend it, don't define it.
+
+2008-11-26  Akim Demaille  <demaille@gostai.com>
+
+       s/_FLAGS/FLAGS/.
+       * tests/local.mk (TESTSUITE_FLAGS, AUTOTEST_FLAGS): Rename as...
+       (TESTSUITEFLAGS, AUTOTESTFLAGS): these to compy with the GCS.
+       Reported by Eric Blake.
 
-       * doc/bison.texinfo: Synchronize ``Detail Node Listing''.
-       Align menus.  Adjust word wrapping.  Use node names for menu names.
-       (Examples): Don't abbreviate node names.
-       (LocalWords): Remove abbreviations.
-       (Copying): Make description a sentence.
-       (Java Action Features): Remove period to match the rest of menu.
+2008-11-26  Akim Demaille  <demaille@gostai.com>
+
+       Use b4_parser_tables_define in glr.cc.
+       * data/glr.c: Use b4_parser_tables_define instead of defining the
+       (deterministic integral) tables by hand.
+
+2008-11-26  Akim Demaille  <demaille@gostai.com>
+
+       Use b4_parser_tables_define in Java.
+       * data/java.m4 (b4_typed_parser_table): Rename as...
+       (b4_typed_parser_table_define): this, for consistency.
+       Accept a comment as $4.
+       Move $2 into yy*_.
+       (b4_integral_parser_table): Rename as...
+       (b4_integral_parser_table_define): this.
+       * data/lalr1.java: Adjust all uses.
+       Use b4_parser_tables_define instead of generation by hand.
+
+2008-11-26  Akim Demaille  <demaille@gostai.com>
+
+       Prepare the convergence bw C style and Java table generation.
+       * data/bison.m4 (b4_tables_map, b4_tables_declare)
+       (b4_tables_define): Rename as...
+       (b4_integral_parser_tables_map, b4_parser_tables_declare)
+       (b4_parser_tables_define): these.
+       * data/c.m4 (b4_table_define): Rename as...
+       (b4_integral_parser_table_define): this.
+       * data/lalr1.cc: Adjust.
+       (b4_table_define, b4_table_declare): Rename as...
+       (b4_integral_parser_table_define)
+       (b4_integral_parser_table_declare): these.
+       (yyrline_): Move the comment where it is actually used.
+       * data/yacc.c: Adjust.
+       (yyrline): Use b4_integral_parser_table_define.
+
+2008-11-26  Akim Demaille  <demaille@gostai.com>
+
+       Regen.
+       * src/parse-gram.h, src/parse-gram.c: Regen.
+
+2008-11-26  Akim Demaille  <demaille@gostai.com>
+
+       Factor the generation of the (integral) tables bw yacc.c and lalr1.cc.
+       * data/lalr1.cc (b4_tables_map): Move to...
+       * data/bison.m4: here.
+       Update the comment for yytable during the flight.
+       (b4_tables_declare, b4_tables_define): New.
+       * data/lalr1.cc: Use them.
+       * data/c.m4 (b4_table_define): New.
+       * data/yacc.c: Use b4_tables_define instead of output the tables
+       by hand.
+       * tests/regression.at (Web2c Actions): Adjust the expected output,
+       the order of the tables changed.
+
+2008-11-26  Akim Demaille  <demaille@gostai.com>
+
+       Get rid of (yy)rhs and (yy)prhs.
+       These tables are no longer needed in the parsers, and they don't seem to
+       be useful.  They are not documented either.
+
+       * src/output.c (prepare_rules): Get rid of rhs and prhs.
+       Adjust the computation of (yy)r2.
+
+2008-11-26  Akim Demaille  <demaille@gostai.com>
+
+       Rule length is unsigned.
+       * src/gram.h, src/gram.c (rule_rhs_length): Return a size_t.
+
+2008-11-26  Akim Demaille  <demaille@gostai.com>
+
+       Get rid of lalr1-split.cc.
+       It was no longer maintainer.
+
+       * data/lalr1-split.cc: Remove.
+       * etc/bench.pl.in (bench_fusion_parser): Remove.
+       Adjust.
 
-2008-11-11  Paolo Bonzini  <bonzini@gnu.org>
+2008-11-26  Akim Demaille  <demaille@gostai.com>
 
-       * bootstrap.conf: Replace m4/warning.m4 with warnings module.
-       * configure.ac: Adjust usage.
-       * lib/Makefile.am: Replace $(WARNING_CFLAGS) with $(WARN_CFLAGS).
-       * src/Makefile.am: Replace $(WARNING_CFLAGS) with $(WARN_CFLAGS).
-       * tests/atlocal.in: Replace $(WARNING_*FLAGS) with $(WARN_*FLAGS).
+       Use yy* consistently.
+       * data/glr.c: Now that yyrhs no longer exists as a global
+       variable, rename local "rhs" variables into "yyrhs" for
+       consistency.
 
-2008-11-07  Joel E. Denny  <jdenny@ces.clemson.edu>
+2008-11-25  Akim Demaille  <demaille@gostai.com>
 
-       Don't add a semicolon to actions for %skeleton or %language.
-       It breaks Java test cases as reported by Akim Demaille.
-       * src/scan-code.l: Implement.
+       Get rid of yyrhs and yyprhs in glr.c.
+       * data/glr.c (yyrhs, yyprhs): Remove.
+       Instead, use the state stack and yystos.
 
-2008-11-07  Joel E. Denny  <jdenny@ces.clemson.edu>
+2008-11-25  Akim Demaille  <demaille@gostai.com>
 
-       Clean up %skeleton and %language priority implementation.
-       * src/getargs.c (skeleton_prio): Use default_prio rather than 2, and
-       remove static qualifier because others will soon need to see it.
-       (language_prio): Likewise.
+       Flag glr tests.
+       * tests/local.at (_AT_BISON_OPTION_PUSHDEFS): If glr, declare it
+       as an Autotest keyword.
+
+2008-11-25  Akim Demaille  <demaille@gostai.com>
+
+       Prefer TESTSUITE_FLAGS.
+       TESTSUITEFLAGS is barely readable.
+
+       * tests/local.mk (TESTSUITE_FLAGS): Default to $(TESTSUITEFLAGS)
+       for backward compatibility.
+       Use the former instead of the latter.
+
+2008-11-25  Akim Demaille  <demaille@gostai.com>
+
+       Get rid of yyrhs and yyprhs in larl1.java.
+       * data/lalr1.java (yyrhs_, yyprhs_): Remove.
+       (yy_reduce_print): Rather, use yystos_ and the state stack.
+
+2008-11-25  Akim Demaille  <demaille@gostai.com>
+
+       Formatting changes.
+
+2008-11-25  Akim Demaille  <demaille@gostai.com>
+
+       Get rid of yyrhs and yyprhs in yacc.c.
+       They were used to get the symbol types, given a rule number, when
+       displaying the top of the stack before a reduction.  But the
+       symbol type is available from the state stack.  This has two be
+       benefits: two tables less in the parser (making it smaller), and a
+       more consistent use of the three stacks which will help to fuse
+       them.
+
+       * data/yacc.c (yyprhs, yyrhs): Remove.
+       (YY_REDUCE_PRINT): Pass yyssp to yy_reduce_print.
+       (yy_reduce_print): Take yyssp as argument.
+       Use it, together with yystos, to get the symbol type.
+       * tests/regression.at (Web2c Report): Remove these tables from the
+       expected output.
+
+2008-11-25  Akim Demaille  <demaille@gostai.com>
+
+       b4_tables_map.
+       The point is to factor the generation of the tables across skeletons.
+       This is language dependant.
+
+       * data/c.m4 (b4_comment_): New.
+       Should be usable to define how to generate tables independently of
+       the language.
+       (b4_c_comment): New.
+       (b4_comment): Bounce to b4_c_comment.
+       Now support $2 = [PREFIX] for indentation.
+       * data/lalr1.cc (b4_table_declare): Don't output a comment if
+       there is no comment.
+       Indent it properly when there is one.
+       Output the ending semicolon.
+       (b4_table_define): Space changes.
+       Output the ending semicolon.
+       (b4_tables_map): New.
+       Use it twice instead of declaring and defining the (integral)
+       tables by hand.
+
+2008-11-25  Akim Demaille  <demaille@gostai.com>
+
+       b4_table_declare.
+       * data/lalr1.cc (b4_table_declare): New.
+       Use it to declare the tables defined with b4_table_define.
+       (b4_table_define): Declare a third arg to match b4_table_declare
+       signature.
+       Move all the comments around invocations of b4_table_define into
+       the invocations itselves.
+       Move things around to have the order for declarations and
+       definitions.
+
+2008-11-25  Akim Demaille  <demaille@gostai.com>
+
+       Formatting changes.
+       * data/lalr1.java: here.
+
+2008-11-25  Akim Demaille  <demaille@gostai.com>
+
+       b4_args is more general than only C++.
+       * data/lalr1.cc (b4_args, _b4_args): Move to...
+       * data/bison.m4: here.
+
+2008-11-21  Di-an Jan  <dianj@freeshell.org>
+
+       Implement no-XXX arguments for --warnings, --report, --trace.
+       * src/getargs.c (flags_argmatch): Handles no-XXX.
+       Fix typo in doxygen comment.
+
+2008-11-21  Akim Demaille  <demaille@gostai.com>
+
+       Display the changes in cross-options.texi.
+       * build-aux/cross-options.pl ($sep): New, to separate items.
+       * doc/local.mk ($(CROSS_OPTIONS_TEXI)): Use diff to display the
+       changes.
+
+2008-11-20  Di-an Jan  <dianj@freeshell.org>
+
+       Improves options in the manual.
+       * doc/bison.texinfo (-g, -x): Add space before argument.
+       (Option Cross Key): Implement FIXME: listing directives also.
+       * build-aux/cross-options.pl:  Read from <STDIN> rather than <>.
+       (Short Option): Special case -d.  Put arguments inside @option.
+       (Bison Directive): Add column, automatically extracted from
+       src/scan-gram.l (actual name passed as the first argument)
+       with special case for %define.
+       * doc/local.mk (doc/cross-options.texi): Pass src/scan-gram.l
+       to build-aux/cross-options.pl.
+       * src/getargs.c (usage): Document limitations of cross-options.pl.
+       * src/scan-gram.l: Likewise.
+
+2008-11-18  Joel E. Denny  <jdenny@ces.clemson.edu>
+
+       Fix unexpanded macros in GLR defines file.
+       Reported by Csaba Raduly at
+       <http://lists.gnu.org/archive/html/bug-bison/2008-11/msg00048.html>.
+       * THANKS (Csaba Raduly): Add.
+       * data/glr.c: Fix overquoting on b4_prefix for yylval and yylloc.
+       * tests/calc.at (_AT_DATA_CALC_Y): If %defines is specified, generate
+       lexer in a separate module that includes the defines file.
+       (AT_CHECK_CALC): From AT_FULL_COMPILE, request compilation of lexer
+       source.
+       * tests/local.at (_AT_BISON_OPTION_PUSHDEFS): Push AT_DEFINES_IF.
+       Adjust AT_LOC and AT_VAL to use AT_NAME_PREFIX.
+       (AT_BISON_OPTION_POPDEFS): Pop AT_DEFINES_IF.
+       (AT_DATA_SOURCE_PROLOGUE): New.
+       (AT_DATA_GRAMMAR_PROLOGUE): Use AT_DATA_SOURCE_PROLOGUE.
+       (AT_DATA_SOURCE): New.
+       (AT_FULL_COMPILE): Extend to support an additional source file.
+
+2008-11-18  Akim Demaille  <demaille@gostai.com>
+
+       More TODO.
+       * TODO: More short term issues.
+
+2008-11-18  Akim Demaille  <demaille@gostai.com>
+
+       Regen.
+       * src/parse-gram.h, src/parse-gram.c: Regen.
+
+2008-11-18  Akim Demaille  <demaille@gostai.com>
+
+       Use b4_subtract where possible.
+       * data/lalr1.cc (b4_subtract): Move to...
+       * data/bison.m4: here.
+       * data/glr.c (b4_rhs_data): Use it.
+       * data/yacc.c (b4_rhs_value, b4_rhs_location): Use it.
+
+2008-11-18  Akim Demaille  <demaille@gostai.com>
+
+       Remove incorrect mode specification.
+       * data/glr.cc: Don't pretend it's C code.
+
+2008-11-17  Joel E. Denny  <jdenny@ces.clemson.edu>
+
+       Simplify last patch slightly.
+       * src/getargs.c (getargs): Here.
+
+2008-11-17  Joel E. Denny  <jdenny@ces.clemson.edu>
+
+       Fix last warning from --enable-gcc-warnings.
+       * src/getargs.c (getargs): Don't assign const address to non-const
+       pointer.
+
+2008-11-17  Joel E. Denny  <jdenny@ces.clemson.edu>
+
+       Don't let maintainer-*-check targets force a version update.
+       * cfg.mk (_is-dist-target): Implement.  maintainer-check* was already
+       handled.
+
+2008-11-17  Di-an Jan  <dianj@freeshell.org>
+
+       * doc/bison.texinfo: Synchronize ``Detail Node Listing''.
+       Align menus.  Adjust word wrapping.  Use node names for menu names.
+       (Examples): Don't abbreviate node names.
+       (LocalWords): Remove abbreviations.
+       (Copying): Make description a sentence.
+       (Java Action Features): Remove period to match the rest of menu.
+
+2008-11-17  Di-an Jan  <dianj@freeshell.org>
+
+       Handles several --enable-gcc-warnings.
+       * src/getargs.c (command_line_location): Set parameters to void.
+       * src/output.c (symbol_type_name_cmp): Make static.
+       (symbols_by_type_name): Set parameters to void.
+       (symbol_definitions_output): Remove unused parameter.  Rename as...
+       (prepare_symbol_definitions): this.
+       (muscles_output): Move symbol_definitions_output to...
+       (output): here as prepare_symbol_definitions.
+       * tests/c++.at (AT_CHECK_VARIANTS): Remove unused parameters of main.
+       (AT_CHECK_NAMESPACE): Make unused parameter lloc unnamed.
+
+2008-11-17  Di-an Jan  <dianj@freeshell.org>
+
+       * tests/c++.at (AT_CHECK_VARIANTS): Fixes tests 198-202.
+       Use AT_DATA_GRAMMAR instead of AT_DATA for compiled tests.
+
+2008-11-16  Akim Demaille  <demaille@gostai.com>
+
+       Add missing $(EXEEXT).
+       * doc/local.mk ($(CROSS_OPTIONS_TEXI)): The target is
+       "src/bison$(EXEEXT)".
+       Reported by Di-an Jan.
+
+2008-11-15  Akim Demaille  <demaille@gostai.com>
+
+       * TODO: Update.
+
+2008-11-15  Akim Demaille  <demaille@gostai.com>
+
+       Formatting changes.
+       * tests/input.at: here.
+
+2008-11-15  Akim Demaille  <demaille@gostai.com>
+
+       Remove duplicate header inclusion.
+       * src/LR0.c: here.
+
+2008-11-15  Akim Demaille  <demaille@gostai.com>
+
+       * src/parse-gram.h, src/parse-gram.c: Regen.
+
+2008-11-15  Akim Demaille  <demaille@gostai.com>
+
+       Support parametric types.
+
+       There are two issues to handle: first scanning nested angle
+       bracket pairs to support types such as std::pair< std::string,
+       std::list<std::string> > >.
+
+       Another issue is to address idiosyncracies of C++: do not glue two
+       closing angle brackets together (otherwise it's operator>>), and
+       avoid sticking blindly a TYPE to the opening <, as it can result
+       in '<:' which is a digraph for '['.
+
+       * src/scan-gram.l (brace_level): Rename as...
+       (nesting): this.
+       (SC_TAG): New.
+       Implement support for complex tags.
+       (tag): Accept
+       , but not <.
+       * data/lalr1.cc (b4_symbol_value, b4_symbol_value_template)
+       (b4_symbol_variant): Leave space around types as parameters.
+       * examples/variant.yy: Use nested template types and leading ::.
+       * src/parse-gram.y (TYPE, TYPE_TAG_ANY, TYPE_TAG_NONE, type.opt):
+       Rename as...
+       (TAG, TAG_ANY, TAG_NONE, tag.opt): these.
+       * tests/c++.at: Test parametric types.
+
+2008-11-15  Akim Demaille  <akim@betelgeuse.gostai.ensta.fr>
+
+       Test token.prefix.
+       This is not sufficient, but we test at least that the make_SYMBOL
+       interface is not affected by token.prefix.  A more general test
+       will be implemented when the support of token.prefix is generalized
+       to more skeletons.
+
+       * tests/c++.at: One more variant test, using token.prefix.
+
+2008-11-15  Akim Demaille  <akim@betelgeuse.gostai.ensta.fr>
+
+       Test the make_TOKEN interface.
+       * tests/c++.at (AT_CHECK_VARIANTS): Require and use locations.
+       Factor the common code in yylex.
+       Use it to test "%define lex_symbol".
+
+2008-11-15  Akim Demaille  <akim@betelgeuse.gostai.ensta.fr>
+
+       Formatting change.
+
+2008-11-15  Akim Demaille  <akim@betelgeuse.gostai.ensta.fr>
+
+       Simplify code for variants bench marks.
+       * etc/bench.pl.in (&generate_grammar_list): Define and use
+       location_type.
+       Factor the common code in yylex.
+
+2008-11-15  Akim Demaille  <demaille@gostai.com>
+
+       Better error message.
+       * bootstrap (find_tool): Fix the error message.
+
+2008-11-15  Akim Demaille  <demaille@gostai.com>
+
+       Update variant.yy to newest interface.
+       * examples/variant.yy: Define lex_symbol.
+       Adjust.
+
+2008-11-15  Akim Demaille  <demaille@gostai.com>
+
+       Don't use locations in variant.yy.
+       * examples/variant.yy: Adjust to not using locations.
+
+2008-11-15  Akim Demaille  <demaille@gostai.com>
+
+       Comment changes.
+       * data/local.mk, etc/local.mk, examples/local.mk: Use Automake
+       comments for the license.
+
+2008-11-15  Akim Demaille  <demaille@gostai.com>
+
+       Remove tests/Makefile.am.
+       * tests/Makefile.am: Rename as...
+       * tests/local.mk: this.
+       * Makefile.am, configure.ac: Adjust.
+       * Makefile.am (DISTCLEANFILES): Define.
+       (maintainer-check, maintainer-xml-check, maintainer-push-check):
+       Remove, we no longer need to bounce to the real targets.
+
+2008-11-15  Akim Demaille  <demaille@gostai.com>
+
+       Comment changes.
+
+2008-11-15  Akim Demaille  <demaille@gostai.com>
+
+       djgpp/local.mk.
+       * Makefile.am (EXTRA_DIST): Move djgpp related part to...
+       * djgpp/local.mk: this new file.
+
+2008-11-15  Akim Demaille  <demaille@gostai.com>
+
+       Remove doc/Makefile.am.
+       * doc/Makefile.am: Rename as...
+       * doc/local.mk: this.
+       Adjust paths
+       * Makefile.am, configure.ac: Adjust.
+       * Makefile.am (MOSTLYCLEANFILES): New.
+       * src/local.mk: Adjust.
+
+2008-11-15  Akim Demaille  <demaille@gostai.com>
+
+       Move sc_tight_scope into maint.mk.
+       It does not work, and I don't know how it was supposed to work: it
+       seems to be looking for sources in the build tree.  I just moved
+       it at a better place, fixing it is still required.
+
+       * src/local.mk (echo): Remove.
+       (sc_tight_scope): Move to...
+       * maint.mk: here.
+
+2008-11-15  Akim Demaille  <demaille@gostai.com>
+
+       Regen.
+       * src/parse-gram.h, src/parse-gram.h: Regen.
+
+2008-11-15  Akim Demaille  <demaille@gostai.com>
+
+       Remove src/Makefile.am.
+       * src/Makefile.am: Rename as...
+       * src/local.mk: this.
+       Prefix all the paths with src/.
+       (AUTOMAKE_OPTIONS): Build object files in the sub dirs.
+       (AM_CPPFLAGS): Find find in builddir/src.
+       (YACC): Move the flags into...
+       (AM_YFLAGS): here.
+       * maint.mk (sc_tight_scope): Disable.
+       It used to bounce to the version in src/Makefile.am which is now
+       part of this very Makefile.
+       * Makefile.am, configure.ac: Adjust.
+       * src/scan-code-c.c, src/scan-code.l: We can no longer rely on
+       include "..." to find files "here": we are no longer in src/, so
+       qualify the includes with src/.
+       * doc/Makefile.am (PREPATH): No longer include the top_builddir
+       prefix.
+       (.x.1): Adjust to be able to create src/foo from the top level
+       Makefile, instead of going bounce to src/Makefile the creation of
+       foo.
+
+2008-11-15  Akim Demaille  <demaille@gostai.com>
+
+       Remove useless variable.
+       * doc/Makefile.am (srcsrcdir): Remove.
+
+2008-11-15  Akim Demaille  <demaille@gostai.com>
+
+       Remove data/Makefile.am.
+       * data/Makefile.am: Rename as...
+       * data/local.mk: this.
+       Adjust paths.
+       * Makefile.am, configure.ac: Adjust.
+
+2008-11-15  Akim Demaille  <demaille@gostai.com>
+
+       Remove etc/Makefile.am.
+       * etc/Makefile.am: Rename as...
+       * etc/local.mk: this.
+       Adjust.
+       * Makefile.am, configure.ac: Adjust.
+
+2008-11-15  Akim Demaille  <demaille@gostai.com>
+
+       Remove examples/local.mk.
+       examples/calc++/Makefile.am might be interesting to keep as is, since
+       it is an example in itself.
+
+       * examples/Makefile.am: Rename as...
+       * examples/local.mk: this.
+       Adjust.
+       * Makefile.am, configure.ac: Adjust.
+
+2008-11-15  Akim Demaille  <demaille@gostai.com>
+
+       Remove build-aux/Makefile.am.
+       Recursive Makefiles are really way too slow, let's get rid of some of
+       them.
+
+       * build-aux/Makefile.am: Rename as...
+       * build-aux/local.mk: this.
+       Adjust paths.
+       * Makefile.am, configure.ac: Adjust.
+
+2008-11-15  Akim Demaille  <demaille@gostai.com>
+
+       Provide convenience constructors for locations and positions.
+       * data/location.cc (position::position): Accept file, line and
+       column as arguments with default values.
+       Always qualify initial line and column literals as unsigned.
+       (location::location): Provide convenience constructors.
+
+2008-11-15  Akim Demaille  <demaille@gostai.com>
+
+       Instead of using make_symbol<TOK_FOO>, generate make_FOO for each
+       token type.
+       Using template buys us nothing, and makes it uselessly complex to
+       construct a symbol.  Besides, it could not be generalized to other
+       languages, while make_FOO would work in C/Java etc.
+
+       * data/lalr1.cc (b4_symbol_): New.
+       (b4_symbol): Use it.
+       (b4_symbol_constructor_declaration_)
+       (b4_symbol_constructor_definition_): Instead of generating
+       specializations of an overloaded template function, just generate
+       several functions whose names are forged from the token names
+       without the token.prefix.
+       (b4_symbol_constructor_declarations): Generate them for all the
+       symbols, not just by class of symbol type, now that instead of
+       specializing a function template by the token, we generate a
+       function named after the token.
+       (b4_symbol_constructor_specialization_)
+       (b4_symbol_constructor_specializations): Remove.
+       * etc/bench.pl.in: Adjust to this new API.
+
+2008-11-13  Akim Demaille  <demaille@gostai.com>
+
+       %define token.prefix.
+       Provide a means to add a prefix to the name of the tokens as
+       output in the generated files.  Because of name clashes, it is
+       good to have such a prefix such as TOK_ that protects from names
+       such as EOF, FILE etc.  But it clutters the grammar itself.
+
+       * data/bison.m4 (token.prefix): Empty by default.
+       * data/c.m4 (b4_token_enum, b4_token_define): Use it.
+       * data/lalr1.cc (b4_symbol): Ditto.
+
+2008-11-13  Akim Demaille  <demaille@gostai.com>
+
+       Compute at M4 time some of the subtractions.
+       * data/lalr1.cc (b4_subtract): New.
+       (b4_rhs_data): Use it.
+
+2008-11-13  Akim Demaille  <demaille@gostai.com>
+
+       symbol::token.
+       This allows the user to get the type of a token returned by yylex.
+
+       * data/lalr1.cc (symbol::token): New.
+       (yytoknum_): Define when %define lex_symbol, independently of
+       %debug.
+       (yytoken_number_): Move into...
+       (symbol::token): here, since that's the only use.
+       The other one is YYPRINT which was not officially supported
+       by lalr1.cc, and anyway it did not work since YYPRINT uses this
+       array under a different name (yytoknum).
+
+2008-11-13  Akim Demaille  <demaille@gostai.com>
+
+       YYERRCODE.
+       * TODO (YYERRCODE): Mention the case of $undef.
+
+2008-11-13  Akim Demaille  <demaille@gostai.com>
+
+       TODO: YYPRINT.
+       * TODO (YYPRINT): New.
+
+2008-11-13  Akim Demaille  <demaille@gostai.com>
+
+       Comment changes.
+       * data/lalr1.cc, data/yacc.c: Fix the description of the
+       yytranslate and yytoknum tables.
+
+2008-11-13  Akim Demaille  <demaille@gostai.com>
+
+       Define make_symbol in the header.
+       To reach good performances these functions should be inlined (yet
+       this is to measure precisely).  To this end they must be available
+       to the caller.
+
+       * data/lalr1.cc (b4_symbol_constructor_definition_): Qualify
+       location_type with the class name.
+       Since will now be output in the header, declare "inline".
+       No longer use b4_symbol_constructor_specializations, but
+       b4_symbol_constructor_definitions in the header.
+       Don't call it in the *.cc file.
+
+2008-11-13  Akim Demaille  <demaille@gostai.com>
+
+       Define yytranslate in the header for lex_symbol.
+       * data/lalr1.cc: Move the invocation of b4_yytranslate_definition
+       into the header file when using %define lex_symbol.
+       (yytranslate_): Declare inline.
+
+2008-11-13  Akim Demaille  <demaille@gostai.com>
+
+       Define the constructors of symbol_type in
+       b4_symbol_constructor_definitions.
+       The constructors are called by the make_symbol functions, which a
+       forthcoming patch will move elsewhere.  Hence the interest of
+       putting them together.
+
+       The stack_symbol_type does not need to be moved, it is used only
+       by the parser.
+
+       * data/lalr1.cc: Move symbol_type and symbol_base_type
+       constructors into...
+       (b4_symbol_constructor_definitions): here.
+       Adjust.
+
+2008-11-13  Akim Demaille  <demaille@gostai.com>
+
+       Make it easier to move the definition of yytranslate_.
+       Forthcoming changes will make it possible to use yytranslate_
+       from outside the parser implementation file.
+
+       * data/lalr1.cc (b4_yytranslate_definition): New.
+       Use it.
+
+2008-11-13  Akim Demaille  <demaille@gostai.com>
+
+       Remove useless class specification.
+       * data/lalr1.cc (b4_symbol_constructor_specialization_): No need
+       to refer to the class name to use a type defined by the class for
+       arguments of member functions.
+
+2008-11-13  Akim Demaille  <demaille@gostai.com>
+
+       Finer input type for yytranslate.
+       This patch is debatable: the tradition expects yylex to return an int
+       which happens to correspond to token_number (which is an enum).  This
+       allows for instance to return characters (such as '*' etc.).  But this
+       goes against the stronger typing I am trying to have with the new
+       lex interface which return a symbol_type.  So in this case, feed
+       yytranslate_ with a token_type.
+
+       * data/lalr1.cc (yytranslate_): When in %define lex-symbol,
+       expect a token_type.
+
+2008-11-13  Akim Demaille  <demaille@gostai.com>
+
+       Honor lex-params in %define lex_symbol mode.
+       * data/lalr1.cc: Use b4_lex_param.
+
+2008-11-13  Akim Demaille  <demaille@gostai.com>
+
+       Simplify names.
+       * src/output.c (symbol_definitions_output): Rename symbol
+       attributes type_name and has_type_name as type and has_type.
+       * data/lalr1.cc: Adjust uses.
+
+2008-11-13  Akim Demaille  <demaille@gostai.com>
+
+       Use b4_type_names for the union type.
+       The union used to compute the size of the variant used to iterate
+       over the type of all the symbols, with a lot of redundancy.  Now
+       iterate over the lists of symbols having the same type-name.
+
+       * data/lalr1.cc (b4_char_sizeof_): New.
+       (b4_char_sizeof): Use it.
+       Adjust to be called with a list of numbers instead of a single
+       number.
+       Adjust its caller for new-line issues.
+
+2008-11-13  Akim Demaille  <demaille@gostai.com>
+
+       Define the "identifier" of a symbol.
+       Symbols may have several string representations, for instance if
+       they have an alias.  What I call its "id" is a string that can be
+       used as an identifier.  May not exist.
+
+       Currently the symbols which have the "tag_is_id" flag set are
+       those that don't have an alias.  Look harder for the id.
+
+       * src/output.c (is_identifier): Move to...
+       * src/symtab.c (is_identifier): here.
+       * src/symtab.h, src/symtab.c (symbol_id_get): New.
+       * src/output.c (symbol_definitions_output): Use it to define "id"
+       and "has_id".
+       Remove the definition of "tag_is_id".
+       * data/lalr1.cc: Use the "id" and "has_id" whereever "tag" and
+       "tag_is_id" were used to produce code.
+       We still use "tag" for documentation.
+
+2008-11-11  Akim Demaille  <demaille@gostai.com>
+
+       Locations are no longer required by lalr1.cc.
+       * data/lalr1.cc (_b4_args, b4_args): New.
+       Adjust all uses of locations to make them optional.
+       * tests/c++.at (AT_CHECK_VARIANTS): No longer use the locations.
+       (AT_CHECK_NAMESPACE): Check the use of locations.
+       * tests/calc.at (_AT_DATA_CALC_Y): Adjust to be usable with or
+       without locations with lalr1.cc.
+       Test these cases.
+       * tests/output.at: Check lalr1.cc with and without location
+       support.
+       * tests/regression.at (_AT_DATA_EXPECT2_Y, _AT_DATA_DANCER_Y):
+       Don't use locations.
+
+2008-11-11  Akim Demaille  <demaille@gostai.com>
+
+       AT_FULL_COMPILE.
+       * tests/local.at (AT_FULL_COMPILE): New.
+       * tests/actions.at, tests/calc.at, tests/regression.at: Use it.
+
+2008-11-11  Akim Demaille  <demaille@gostai.com>
+
+       Support parens in calc++.
+       * doc/bison.texinfo (Calc++ Scanner, Calc++ Parser): Support parens.
+       * examples/calc++/test (run): Check the expected output.
+       Adjust callers.
+       Check parens too.
+
+2008-11-11  Akim Demaille  <demaille@gostai.com>
+
+       Simplify lalr1.cc since %defines is mandatory.
+       * data/lalr1.cc: Remove useless calls to b4_defines_if.
+
+2008-11-11  Akim Demaille  <demaille@gostai.com>
+
+       TODO: yyfmt.
+       * TODO (yysyntax_error): New item.
+
+2008-11-11  Akim Demaille  <demaille@gostai.com>
+
+       Prefer M4 to CPP.
+       * data/lalr1.cc: Use b4_error_verbose_if instead of #if
+       YYERROR_VERBOSE.
+
+2008-11-11  Akim Demaille  <demaille@gostai.com>
+
+       Support i18n of the parse error messages.
+       * TODO (lalr1.cc/I18n): Remove.
+       * data/lalr1.cc (yysyntax_error_): Support the translation of the
+       error messages, as done in yacc.c.
+       Stay within the yy* pseudo namespace.
+
+2008-11-11  Akim Demaille  <demaille@gostai.com>
+
+       More TODO.
+       * TODO (single stack, yysyntax_error): New.
+
+2008-11-11  Akim Demaille  <demaille@gostai.com>
+
+       Make it possible to return a symbol_type from yylex.
+       * data/lalr1.cc (b4_lex_symbol_if): New.
+       (parse): When lex_symbol is defined, expected yylex to return the
+       complete lookahead.
+       * etc/bench.pl.in (generate_grammar_list): Extend to support this
+       yylex interface.
+       (bench_variant_parser): Exercise it.
+
+2008-11-11  Akim Demaille  <demaille@gostai.com>
+
+       Remove useless bench case.
+       * etc/bench.pl.in (bench_variant_parser): VARIANT_DESTROY is
+       no longer used.
+
+2008-11-11  Akim Demaille  <demaille@gostai.com>
+
+       Improve display of directives.
+       * etc/bench.pl.in (parse_term): Don't add useless eol.
+
+2008-11-11  Akim Demaille  <demaille@gostai.com>
+
+       Use string_cast in the bench.
+       * etc/bench.pl.in (generate_grammar_list): Define and use
+       string_cast.
+
+2008-11-11  Akim Demaille  <demaille@gostai.com>
+
+       Replace yychar with a Boolean.
+       * data/lalr1.cc (parse::yychar): Replace by...
+       (parse::yyempty): this.
+
+2008-11-11  Akim Demaille  <demaille@gostai.com>
+
+       Factor the tables.
+       * TODO: New item.
+
+2008-11-11  Akim Demaille  <demaille@gostai.com>
+
+       Let yytranslate handle the eof case.
+       * data/lalr1.cc (yytranslate_): Handle the EOF case.
+       Adjust callers.
+       No longer expect yychar to be equal to yyeof_, rather, test the
+       lookahead's (translated) kind.
+
+2008-11-11  Akim Demaille  <demaille@gostai.com>
+
+       yychar cannot be empty in yyerrlab.
+       * TODO (yychar == yyempty_): New.
+       * data/lalr1.cc: Remove the handling of this case.
+       This eases forthcoming changes related to yychar and yytranslate.
+
+2008-11-11  Akim Demaille  <demaille@gostai.com>
+
+       Bench: syntactic sugar for %define/#define.
+       * etc/bench.pl.in (parse_dirs): Support %d and #d with arguments.
+       (&bench_push_parser, bench_variant_parser): Use this feature.
+       (&eat): New.
+       Use it.
+
+2008-11-11  Akim Demaille  <demaille@gostai.com>
+
+       Less memory pressure on the "list" bench.
+       * etc/bench.pl.in (generate_grammar_list): Do not accumulate all
+       the values, to limit memory pressure.
+
+2008-11-11  Akim Demaille  <demaille@gostai.com>
+
+       Introduce make_symbol.
+       make_symbol provides a means to construct a full symbol (kind,
+       value, location) in a single shot.  It is meant to be a Symbol
+       constructor, parameterized by the symbol kind so that overloading
+       would prevent incorrect kind/value pairs.  Unfortunately
+       parameterized constructors do not work well in C++ (unless the
+       parameter also appears as an argument, which is not acceptable),
+       hence the use of a function instead of a constructor.
+
+       * data/lalr1.cc (b4_symbol_constructor_declaration_)
+       (b4_symbol_constructor_declarations)
+       (b4_symbol_constructor_specialization_)
+       (b4_symbol_constructor_specializations)
+       (b4_symbol_constructor_definition_)
+       (b4_symbol_constructor_definitions): New.
+       Use them where appropriate to generate declaration, declaration of
+       the specializations, and implementations of the templated
+       overloaded function "make_symbol".
+       (variant::variant): Always define a default ctor.
+       Also provide a copy ctor.
+       (symbol_base_type, symbol_type): New ctor overloads for value-less
+       symbols.
+       (symbol_type): Now public, so that functions such as yylex can use
+       it.
+
+2008-11-11  Akim Demaille  <demaille@gostai.com>
+
+       Inform m4 whether a tag is a valid id.
+       * src/output.c (is_identifier): New.
+       (symbol_definitions_output): Use it to define tag_is_id.
+       But maybe this should be done at m4 level?
+
+2008-11-11  Akim Demaille  <demaille@gostai.com>
+
+       Test 214 was failing: it greps with a pattern containing [     ]*
+       which obviously meant to catch spaces and tabs, but contained only
+       spaces. Tabulations in sources are a nuisance, so to simplify the
+       matter, get rid of all the tabulations in the Java sources.  The
+       other skeletons will be treated equally later.
+
+       * data/java.m4, data/lalr1.java: Untabify.
+       * tests/java.at: Simplify AT_CHECK_JAVA_GREP invocations:
+       tabulations are no longer generated.
+
+2008-11-11  Paolo Bonzini  <bonzini@gnu.org>
+
+       * bootstrap.conf: Replace m4/warning.m4 with warnings module.
+       * configure.ac: Adjust usage.
+       * lib/Makefile.am: Replace $(WARNING_CFLAGS) with $(WARN_CFLAGS).
+       * src/Makefile.am: Replace $(WARNING_CFLAGS) with $(WARN_CFLAGS).
+       * tests/atlocal.in: Replace $(WARNING_*FLAGS) with $(WARN_*FLAGS).
+
+2008-11-10  Di-an Jan  <dianj@freeshell.org>
+
+       Workaround Java's ``code too large'' problem for parser tables
+       in most cases, by using one function per initialization.
+       * data/java.m4 (b4_typed_parser_table, b4_integral_parser_table): New.
+       * data/lalr1.java (yypact_, yydefact_, yypgoto_, yydefgoto_,
+       yytable_, yycheck_, yystos_, yytoken_number_, yyr1_, yyr2_, yyrhs_
+       yyprhs_, yyrline_, yytranslate_table_): Use b4_integral_parser_table.
+       (yytname_): Use b4_typed_parser_table.
+       * doc/bison.texinfo (Java Bison Interface): Add note on Java's
+       ``code too large'' error.
+
+2008-11-10  Di-an Jan  <dianj@freeshell.org>
+
+       * NEWS: Document them.
+
+       General Java skeleton improvements.
+       * configure.ac (gt_JAVACOMP): Request target of 1.4, which allows
+       using gcj < 4.3 in the testsuite, according to comments in
+       gnulib/m4/javacomp.m4.
+       * data/java.m4 (stype, parser_class_name, lex_throws, throws,
+       location_type, position_type): Remove extraneous brackets from
+       b4_percent_define_default.
+       (b4_lex_param, b4_parse_param): Remove extraneous brackets from
+       m4_define and m4_define_default.
+       * data/lalr1.java (b4_pre_prologue): Change to b4_user_post_prologue,
+       which marks the end of user code with appropriate syncline, like all
+       the other skeletons.
+       (b4_user_post_prologue): Add.  Don't silently drop.
+       (yylex): Remove.
+       (parse): Inline yylex.
+       * doc/bison.texinfo (bisonVersion, bisonSkeleton): Document.
+       (%{...%}): Fix typo of %code imports.
+       * tests/java.at (AT_JAVA_COMPILE): Add "java" keyword.
+
+       Support annotations on parser class with %define annotations.
+       * data/lalr1.java (annotations): Add to parser class modifier.
+       * doc/bison.texinfo (Java Parser Interface): Document
+       %define annotations.
+       (Java Declarations Summary): Document %define annotations.
+       * tests/java.at (Java parser class modifiers): Test annotations.
+
+       Do not generate code for %error-verbose unless requested.
+       * data/lalr1.java (errorVerbose): Rename to yyErrorVerbose.
+       Make private.  Make conditional on %error-verbose.
+       (getErrorVerbose, setErrorVerbose): New.
+       (yytnamerr_): Make conditional on %error-verbose.
+       (yysyntax_error): Make some code conditional on %error-verbose.
+       * doc/bison.texinfo (Java Bison Interface): Remove the parts
+       about %error-verbose having no effect.
+       (getErrorVerbose, setErrorVerbose): Document.
+
+       Move constants for token names to Lexer interface.
+       * data/lalr1.java (Lexer): Move EOF, b4_token_enums(b4_tokens) here.
+       * data/java.m4 (b4_token_enum): Indent for move to Lexer interface.
+       (parse): Qualify EOF to Lexer.EOF.
+       * doc/bison.texinfo (Java Parser Interface): Move documentation of
+       EOF and token names to Java Lexer Interface.
+       * tests/java.at (_AT_DATA_JAVA_CALC_Y): Remove Calc qualifier.
+
+       Make yyerror public.
+       * data/lalr1.java (Lexer.yyerror): Use longer parameter name.
+       (yyerror): Change to public.  Add Javadoc comments.  Use longer
+       parameter names.  Make the body rather than the declarator
+       conditional on %locations.
+       * doc/bison.texinfo (yyerror): Document.  Don't mark as protected.
+
+       Allow user to add code to the constructor with %code init.
+       * data/java.m4 (b4_init_throws): New, for %define init_throws.
+       * data/lalr1.java (YYParser.YYParser): Add b4_init_throws.
+       Add %code init to the front of the constructor body.
+       * doc/bison.texinfo (YYParser.YYParser): Document %code init
+       and %define init_throws.
+       (Java Declarations Summary): Document %code init and
+       %define init_throws.
+       * tests/java.at (Java %parse-param and %lex-param): Adjust grep.
+       (Java constructor init and init_throws): Add tests.
+
+2008-11-10  Akim Demaille  <demaille@gostai.com>
+
+       Update TODO.
+       * TODO (-D): is implemented.
+       (associativity): Same precedence must have the same associativity.
+       For instance, how can a * b / c be parsed if * is %left and / is
+       %right?
+       (YYERRORCODE, YYFAIL, YYBACKUP): New.
+
+2008-11-10  Akim Demaille  <demaille@gostai.com>
+
+       Formatting changes.
+
+2008-11-10  Akim Demaille  <demaille@gostai.com>
+
+       More information about the symbols.
+       * src/output.c (type_names_output): Document all the symbols,
+       including those that don't have a type-name.
+       (symbol_definitions_output): Define "is_token" and
+       "has_type_name".
+       * data/lalr1.cc (b4_type_action_): Skip symbols that have an empty
+       type-name, now that they are defined too in b4_type_names.
+
+2008-11-10  Akim Demaille  <demaille@gostai.com>
+
+       Regen.
+
+2008-11-10  Akim Demaille  <demaille@gostai.com>
+
+       Make parser::yytranslate static.
+       Small speedup (1%) on the list grammar.  And makes yytranslate_
+       available in non member functions.
+
+       * data/lalr1.cc (yytranslate_): Does not need to be a instance
+       function.
+
+2008-11-10  Akim Demaille  <demaille@gostai.com>
+
+       Avoid trailing spaces.
+       * data/c.m4: b4_comment(TEXT): Don't indent empty lines.
+       * data/lalr1.cc: Don't indent before rule and symbol actions, as
+       they can be empty, and anyway this incorrectly indents the first
+       action.
+
+2008-11-10  Akim Demaille  <demaille@gostai.com>
+
+       Comment changes.
+
+2008-11-10  Akim Demaille  <demaille@gostai.com>
+
+       Use "enum" for integral constants.
+       This is just nicer to read, I observed no speedup.
+
+       * data/lalr1.cc (yyeof_, yylast_, yynnts_, yyempty_, yyfinal_)
+       (yterror_, yyerrcode_, yyntokens_): Define as members of an enum.
+       (yyuser_token_number_max_, yyundef_token_): Move into...
+       (yytranslate_): here.
+
+2008-11-10  Akim Demaille  <demaille@gostai.com>
+
+       Shortcuts in bench directives.
+       * etc/bench.pl.in (parse_dirs): New.
+       Use it.
+       (bench_variant_parser, bench_fusion_parser): Use %s and %d.
+       Create the benches in "benches/".
+
+2008-11-10  Akim Demaille  <demaille@gostai.com>
+
+       Formatting changes.
+       * data/lalr1.cc: here.
+
+2008-11-10  Akim Demaille  <demaille@gostai.com>
+
+       Adjust verbose message to using emacs.
+       * etc/bench.pl.in: Inform compilation-mode when we change the
+       directory.
+       (generate_grammar_list): Recognize %define "variant" in addition
+       to %define variant.
+
+2008-11-10  Akim Demaille  <demaille@gostai.com>
+
+       Classify symbols by type-name.
+       * src/uniqstr.h (UNIQSTR_CMP): New.
+       * src/output.c (symbol_type_name_cmp, symbols_by_type_name)
+       (type_names_output): New.
+       (muscles_output): Use it.
+       * data/lalr1.cc (b4_symbol_action_): Remove.
+       (b4_symbol_case_, b4_type_action_): New.
+       Adjust uses of b4_symbol_action_ to use b4_type_action_.
+
+2008-11-10  Akim Demaille  <demaille@gostai.com>
+
+       Change the handling of the symbols in the skeletons.
+       Before we were using tables which lines were the symbols and which
+       columns were things like number, tag, type-name etc.  It is was
+       difficult to extend: each time a column was added, all the numbers had
+       to be updated (you asked for colon $2, not for "tag").  Also, it was
+       hard to filter these tables when only a subset of the symbols (say the
+       tokens, or the nterms, or the tokens that have and external number
+       *and* a type-name) was of interest.
+
+       Now instead of monolithic tables, we define one macro per cell.  For
+       instance "b4_symbol(0, tag)" is a macro name which contents is
+       self-decriptive.  The macro "b4_symbol" provides easier access to
+       these cells.
+
+       * src/output.c (type_names_output): Remove.
+       (symbol_numbers_output, symbol_definitions_output): New.
+       (muscles_output): Call them.
+       (prepare_symbols): Define b4_symbols_number.
+
+2008-11-10  Akim Demaille  <demaille@gostai.com>
+
+       --trace=muscles
+       * src/getargs.h, src/getargs.c (trace_muscle): New.
+       (trace_types, trace_args): Support it.
+       * src/output.c (output_skeleton): Use it.
+
+2008-11-10  Akim Demaille  <demaille@gostai.com>
+
+       muscles_output.
+       * src/output.c (muscles_output): New, extracted from...
+       (output_skeleton): here.
+       Adjust.
+
+2008-11-10  Akim Demaille  <demaille@gostai.com>
+
+       Formatting changes.
+
+2008-11-10  Akim Demaille  <demaille@gostai.com>
+
+       Update the variant example.
+       * examples/variant.yy: Formatting changes.
+       One stage build.
+
+2008-11-10  Akim Demaille  <demaille@gostai.com>
+
+       Support constructor with an argument.
+       This improves the "list" bench by 2%.
+
+       * data/lalr1.cc (variant::build): Add an overloaded version with
+       an argument.
+       * tests/c++.at (AT_CHECK_VARIANT): Check it.
+
+2008-11-10  Akim Demaille  <demaille@gostai.com>
+
+       Test variants.
+       * tests/c++.at (AT_CHECK_VARIANTS): New.
+       Use it with and without %define assert.
+
+2008-11-10  Akim Demaille  <demaille@gostai.com>
+
+       Add %precedence support.
+       Unfortunately it is not possible to reuse the %prec directive.  This
+       is because to please POSIX, we do not require to end the rules with a
+       semicolon.  As a result,
+
+       foo: bar %prec baz
+
+       is ambiguous: either a rule which precedence is that of baz, or a rule,
+       and then a declaration of the precedence of the token baz.
+
+       * doc/bison.texinfo: Document %precedence.
+       (Precedence Only): New.
+       * src/assoc.h, src/assoc.c (precedence_assoc): New.
+       * src/conflicts.c (resolve_sr_conflict): Support it.
+       * src/scan-gram.l, src/parse-gram.y (%precedence): New token.
+       Parse it.
+       * tests/calc.at: Use %precedence for NEG.
+       * tests/conflicts.at (%precedence does not suffice)
+       (%precedence suffices): New tests.
+
+2008-11-09  Akim Demaille  <demaille@gostai.com>
+
+       Make benches in a sub dirs.
+       * etc/bench.pl.in ($dir): New.
+       Use it.
+       Check the use of constructors with an argument.
+       (bench_variant_parser): Fix.
+
+2008-11-09  Akim Demaille  <demaille@gostai.com>
+
+       fix eof condition
+
+2008-11-09  Akim Demaille  <demaille@gostai.com>
+
+       Fix --help.
+
+2008-11-09  Akim Demaille  <demaille@gostai.com>
+
+       Require the generation of parse-gram.output.
+       * src/Makefile.am (YACC): Pass --report=all.
+
+2008-11-09  Akim Demaille  <demaille@gostai.com>
+
+       Formatting changes.
+
+2008-11-09  Akim Demaille  <demaille@gostai.com>
+
+       Update TODO.
+       * TODO: Remove obsolete items.
+       Update others.
+
+2008-11-09  Akim Demaille  <demaille@gostai.com>
+
+       Enhance bench.pl.
+       * etc/bench.pl.in (parse, parse_expr, parse_term, parse_fact)
+       (@token, $grammar, $bench): New.
+       (generate_grammar_variant): Rename as...
+       (generate_grammar_list): this.
+       (generate_grammar): Adjust.
+       (bench_grammar): Rename as...
+       (bench): this.
+       Use it in the various bench-marking routines.
+       (-b, -g): New options.
+
+2008-11-09  Akim Demaille  <demaille@gostai.com>
+
+       Use a static hierarchy for symbols in the C++ parser.
+       * data/lalr1.cc (symbol_base_type, symbol_type)
+       (stack_symbol_type): Make it a static hierarchy.
+       Adjust dependencies.
+
+2008-11-09  Akim Demaille  <demaille@gostai.com>
+
+       bench.pl -d, --directive.
+       * etc/bench.pl.in (@directive): New.
+       (&bench_grammar): Use it.
+       (&bench_list_grammar): New, to provide access to the "variant"
+       grammar.
+       Use it.
+       (getopts): Support -d, --directive.
+
+2008-11-09  Akim Demaille  <demaille@gostai.com>
+
+       Use inline for small operations.
+       * data/lalr1.cc (symbol_base_type, symbol_type)
+       (stack_symbol_type): Declare constructor and other operations as
+       inline.
+       (yy_destroy_): Inline.
+
+2008-11-09  Akim Demaille  <demaille@gostai.com>
+
+       Introduce a hierarchy for symbols.
+       * data/lalr1.cc (symbol_base_type, symbol_type): New.
+       (data_type): Rename as...
+       (stack_symbol_type): this.
+       Derive from symbol_base_type.
+       (yy_symbol_value_print_): Merge into...
+       (yy_symbol_print_): this.
+       Rename as...
+       (yy_print_): this.
+       (yydestruct_): Rename as...
+       (yy_destroy_): this.
+       (b4_symbols_actions, YY_SYMBOL_PRINT): Adjust.
+       (parser::parse): yyla is now of symbol_type.
+       Use its type member instead of yytoken.
+
+2008-11-09  Akim Demaille  <demaille@gostai.com>
+
+       Rename data_type and stack_symbol_type.
+       * data/lalr1.cc (data_type): Rename as...
+       (stack_symbol_type): this.
+
+2008-11-09  Akim Demaille  <demaille@gostai.com>
+
+       Handle semantic value and location together.
+       * data/lalr1.cc (b4_symbol_actions): Bounce $$ and @$ to
+       yydata.value and yydata.location.
+       (yy_symbol_value_print_, yy_symbol_print_, yydestruct_)
+       (YY_SYMBOL_PRINT): Now take semantic value and location as a
+       single arg.
+       Adjust all callers.
+       (yydestruct_): New overload for a stack symbol.
+
+2008-11-09  Akim Demaille  <demaille@gostai.com>
+
+       Push a complete symbol, not connected parts.
+       * data/lalr1.cc (yypush_): Take a data_type&, not disconnected
+       state, value and location.
+       Adjust callers.
+
+2008-11-09  Akim Demaille  <demaille@gostai.com>
+
+       Agregate yylval and yylloc.
+       * data/lalr1.cc (parser::yylval, parser::yylloc): Replace by...
+       (parser::yyla): this.
+
+2008-11-09  Akim Demaille  <demaille@gostai.com>
+
+       Rely on the state stack to display reduction traces.
+       To display rhs symbols before a reduction, we used information
+       about the rule reduced, which required the tables yyrhs and
+       yyprhs.  Now use rely only on the state stack to get the same
+       information.
+
+       * data/lalr1.cc (b4_rhs_data, b4_rhs_state): New.
+       Use them.
+       (parser::yyrhs_, parser::yyprhs_): Remove.
+       (parser::yy_reduce_print_): Use the state stack.
+
+2008-11-09  Akim Demaille  <demaille@gostai.com>
+
+       Fuse yyval and yyloc into yylhs.
+       * data/lalr1.cc (b4_lhs_value, b4_lhs_location): Adjust to using
+       yylhs.
+       (parse): Replace yyval and yyloc with yylhs.value and
+       yylhs.location.
+       After a user action, compute yylhs.state earlier.
+       (yyerrlab1): Do not play tricks with yylhs.location, rather, use a
+       fresh error_token.
+
+2008-11-09  Di-an Jan  <dianj@freeshell.org>
+
+       Remove unused variable.
+       * src/output.c (type_names_output): Remove unused variable sep.
+
+2008-11-09  Paolo Bonzini  <bonzini@gnu.org>
+
+       Change tests/output.at quoting.
+       * tests/output.at (AT_CHECK_OUTPUT): Use conventional m4 quoting when
+       expanding arguments.
+
+2008-11-07  Joel E. Denny  <jdenny@ces.clemson.edu>
+
+       Don't add a semicolon to actions for %skeleton or %language.
+       It breaks Java test cases as reported by Akim Demaille.
+       * src/scan-code.l: Implement.
+
+2008-11-07  Joel E. Denny  <jdenny@ces.clemson.edu>
+
+       Clean up %skeleton and %language priority implementation.
+       * src/getargs.c (skeleton_prio): Use default_prio rather than 2, and
+       remove static qualifier because others will soon need to see it.
+       (language_prio): Likewise.
        (getargs): Use command_line_prio rather than 0.
        * src/getargs.h (command_line_prio, grammar_prio, default_prio): New
        enum fields.
        (language_prio): Extern it.
        * src/parse-gram.y: Use grammar_prio rather than 1.
 
-2008-11-04  Akim Demaille  <demaille@gostai.com>
+2008-11-07  Akim Demaille  <demaille@gostai.com>
 
-       * NEWS: Mention the trailing semicolon in action.
+       Moving push traces into yypush_.
+       * data/lalr1.cc (yypush_): Now takes a optional trace message.
+       Adjust all uses.
 
-2008-11-04  Akim Demaille  <demaille@gostai.com>
+2008-11-07  Akim Demaille  <demaille@gostai.com>
 
-       Reformat NEWS.
-       * NEWS: Use more outline-mode markup.
-       Suggested by Jim Meyering.
+       The single-stack C++ parser is now the standard one.
+       * data/lalr1.cc: Rename as...
+       * data/lalr1-split.cc: this.
+       * data/lalr1-fusion.cc: Rename as...
+       * data/lalr1.cc: this.
+       * etc/bench.pl.in: Adjust.
+
+2008-11-07  Akim Demaille  <demaille@gostai.com>
+
+       Avoid empty-if warnings.
+       Reported by Quentin Hocquet.
+
+       * data/lalr1-fusion.cc (YY_SYMBOL_PRINT, YY_REDUCE_PRINT)
+       (YY_STACK_PRINT): Provide some contents even when !YYDEBUG.
+
+2008-11-07  Akim Demaille  <demaille@gostai.com>
+
+       Pass command line location to skeleton_arg and language_argmatch.
+       * src/getargs.h, src/getargs.c (skeleton_arg, language_argmatch):
+       The location argument is now mandatory.
+       Adjust all dependencies.
+       (getargs): Use command_line_location.
+
+2008-11-07  Akim Demaille  <demaille@gostai.com>
+
+       -D, --define.
+       * src/getargs.c (usage): Document -D.
+       Fix help string for --locations.
+       (command_line_location): New.
+       (short_options, long_options, getargs): Support -D, --define.
+       (getargs): Move -d support at the right place.
+       * doc/bison.texinfo (Bison Options): Update.
+       * tests/input.at (%define, --define): New.
+
+2008-11-07  Akim Demaille  <demaille@gostai.com>
+
+       Initialize the muscle table before parsing the command line.
+       * src/getargs.c (quotearg.h, muscle_tab.h): Include.
+       (getargs): Define file_name.
+       * src/main.c (main): Initialize muscle_tab before calling
+       getargs.
+       * src/muscle_tab.c (muscle_init): No longer define file_name, as
+       its value is not available yet.
+
+2008-11-07  Akim Demaille  <demaille@gostai.com>
+
+       Locations without columns for command line arguments.
+       * src/location.c (location_print): Don't display negative columns.
+       * src/location.h: Document this.
+
+2008-11-07  Akim Demaille  <demaille@gostai.com>
+
+       Fix --help.
+       * src/getargs.c (usage): Fix help string for -W.
+
+2008-11-07  Akim Demaille  <demaille@gostai.com>
+
+       Handle more general types of option arguments.
+       * build-aux/cross-options.pl: The argument ends at the first
+       space, not the first non-symbol character.
+       Use @var for each word appearing the argument description.
+
+2008-11-07  Akim Demaille  <demaille@gostai.com>
+
+       Destroy the variants that remain on the stack in case of error.
+       * data/lalr1-fusion.cc (yydestruct_): Invoke the variant's
+       destructor.
+       Display the value only if yymsg is nonnull.
+       (yyreduce): Invoke yydestruct_ when popping lhs symbols.
+
+2008-11-07  Akim Demaille  <demaille@gostai.com>
+
+       Add "%define assert" to variants.
+       This is used to help the user catch cases where some value gets
+       ovewritten by a new one.  This should not happen, as this will
+       probably leak.
+
+       Unfortunately this uncovered a bug in the C++ parser itself: the
+       lookahead value was not destroyed between two calls to yylex.  For
+       instance if the previous lookahead was a std::string, and then an int,
+       then the value of the std::string was correctly taken (i.e., the
+       lookahead was now an empty string), but std::string structure itself
+       was not reclaimed.
+
+       This is now done in variant::build(other&) (which is used to take the
+       value of the lookahead): other is not only stolen from its value, it
+       is also destroyed.  This incurs a new performance penalty of a few
+       percent, and union becomes faster again.
+
+       * data/lalr1-fusion.cc (variant::build(other&)): Destroy other.
+       (b4_variant_if): New.
+       (variant::built): New.
+       Use it whereever the status of the variant changes.
+       * etc/bench.pl.in: Check the penalty of %define assert.
+
+2008-11-07  Akim Demaille  <demaille@gostai.com>
+
+       Use "%define variant" in bench.pl.
+       * etc/bench.pl.in: No longer use the pseudo directive %variants,
+       just use %define variants.
+
+2008-11-07  Akim Demaille  <demaille@gostai.com>
+
+       Regen.
+       * src/parse-gram.h, src/parse-gram.c: Regen.
 
 2008-11-04  Joel E. Denny  <jdenny@ces.clemson.edu>
 
        * tests/regression.at (Fix user actions without a trailing semicolon):
        New test case.
 
+2008-11-04  Akim Demaille  <demaille@gostai.com>
+
+       Use b4_copyright_years.
+       * data/yacc.c (b4_copyright_years): New.
+       Fix its value according to the comments in the file.
+       Use it and undefine it.
+
+2008-11-04  Akim Demaille  <demaille@gostai.com>
+
+       Formatting changes.
+       * data/lalr1-fusion.cc, src/parse-gram.y: here.
+
+2008-11-04  Akim Demaille  <demaille@gostai.com>
+
+       Formatting changes.
+       * data/lalr1-fusion.cc: here.
+
+2008-11-04  Akim Demaille  <demaille@gostai.com>
+
+       Use strict on bench.pl.
+       * etc/bench.pl.in (&run, &generate_grammar): New.
+       Rename the grammar generating functions for consistency.
+       Change the interface so that the list of benches to run is passed
+       as (optionless) arguments.
+       (&compile): Use &run.
+
+2008-11-04  Akim Demaille  <demaille@gostai.com>
+
+       Remove spurious initial empty lines.
+       * data/glr.c, data/glr.cc, data/lalr1.cc, data/lalr1.java,
+       * data/yacc.c: End the @output lines with an @.
+
+2008-11-04  Akim Demaille  <demaille@gostai.com>
+
+       Improve the display of sizes.
+       * etc/bench.p.in: Higher precision.
+       Sort by decreasing size.
+
+2008-11-04  Akim Demaille  <demaille@gostai.com>
+
+       Don't memcpy C++ structures.
+       * data/lalr1-fusion.cc (b4_symbol_variant): Adjust additional
+       arguments.
+       (variant::build): New overload for
+       copy-construction-that-destroys.
+       (variant::swap): New.
+       (parser::yypush_): Use it in variant mode.
+
+2008-11-04  Akim Demaille  <demaille@gostai.com>
+
+       Better defaults for bench.pl.
+       * etc/bench.pl.in ($verbose, $cflags, $iterations): Change the
+       default values.
+       Adjust &verbose uses.
+       (-q, --quiet): New.
+
+2008-11-04  Akim Demaille  <demaille@gostai.com>
+
+       Make variant.yy more complex.
+       std::list cannot be copied via memcpy, they are more demanding than
+       std::string.  Use one std::list to strengthen the test.
+
+       * examples/variant.yy: Use lalr1-fusion.cc, not lalr1.cc.
+       Adjust.
+       Create a list of strings, instead of a single large string.
+
+2008-11-04  Akim Demaille  <demaille@gostai.com>
+
+       bench.pl --bench.
+       * etc/bench.pl.in (--bench, $bench): New.
+
+2008-11-04  Akim Demaille  <demaille@gostai.com>
+
+       Sort methods.
+       * data/lalr1-fusion.cc (destroy): Use as() in its definition.
+       Define it after as().
+
+2008-11-04  Akim Demaille  <demaille@gostai.com>
+
+       Useless parens.
+       * data/lalr1-fusion.cc (b4_rhs_location): Remove useless parens.
+
+2008-11-04  Akim Demaille  <demaille@gostai.com>
+
+       Issue missing synclines after user actions.
+       * data/c.m4 (b4_case): Issue synclines on the output file.
+
+2008-11-04  Akim Demaille  <demaille@gostai.com>
+
+       Remove trailing empty line.
+       * data/lalr1-fusion.cc: Don't add an empty line after the user's
+       epilogue.
+
+2008-11-04  Akim Demaille  <demaille@gostai.com>
+
+       Fix output of copyright years.
+       * data/bison.m4 (b4_copyright): Fix the indentation of the
+       copyright year paragraph.
+       Use b4_copyright_years when no years are given.
+       * data/lalr1.cc, data/lalr1-fusion.cc, data/location.cc
+       (b4_copyright_years): New.
+       Use it.
+
+2008-11-04  Akim Demaille  <demaille@gostai.com>
+
+       Avoid the spurious initial empty line.
+       * data/lalr1-fusion.cc, data/location.cc: Put a trailing "@" at
+       the end of @output request to suppress the empty line that
+       results.
+
+2008-11-04  Akim Demaille  <demaille@gostai.com>
+
+       Remove parser::rhs_number_type.
+       * data/lalr1-fusion.cc (rhs_number_type): No longer define it.
+       (yyrhs_): Use b4_table_define.
+
+2008-11-04  Akim Demaille  <demaille@gostai.com>
+
+       Fix iteration type.
+       * data/lalr1-fusion.cc: Use an int to iterate up to an int.
+
+2008-11-04  Akim Demaille  <demaille@gostai.com>
+
+       Factor the declaration of the integer tables.
+       * data/lalr1-fusion.cc (b4_table_define): New.
+       Use it.
+
+2008-11-03  Akim Demaille  <demaille@gostai.com>
+
+       Fix indentation of tables in lalr1.cc
+       * data/lalr1-fusion.cc: Fix the indentation.
+
+2008-11-03  Akim Demaille  <demaille@gostai.com>
+
+       Destroy the lhs symbols after reduction.
+       * data/lalr1-fusion.cc (parse): After the user action, when in
+       variant mode, destroy the lhs symbols.
+
+2008-11-03  Akim Demaille  <demaille@gostai.com>
+
+       Simplify yysyntax_error_ use.
+       * data/lalr1-fusion.cc (yysyntax_error_): Always pass it the token
+       type, but make it unnamed in the declaration when it is not used.
+
+2008-11-03  Akim Demaille  <demaille@gostai.com>
+
+       Let yy::variant::build return an lvalue.
+       * data/lalr1-fusion.cc (variant::build): Return a reference to the
+       object.
+
+2008-11-03  Akim Demaille  <demaille@gostai.com>
+
+       Define yy::variant only when needed.
+       * data/lalr1-fusion.cc (yy::variant): Define only if variants are
+       used.
+
+2008-11-03  Akim Demaille  <demaille@gostai.com>
+
+       Bench the three-stack lalr1.cc.
+       * etc/bench.pl.in: Bench the three-stack lalr1.cc vs. the
+       one-stack one.
+
+2008-11-03  Akim Demaille  <demaille@gostai.com>
+
+       Fail on parse error in calc++.
+       * doc/bison.texinfo (calc++.cc): Propagate failures to the exit
+       status.
+       * examples/calc++/test ($me, $number, $exit, run): New.
+       Use them to propagate errors to the exit status.
+
+2008-11-03  Akim Demaille  <demaille@gostai.com>
+
+       Don't specify the skeleton twice in the example.
+       * examples/calc++/Makefile.am: Don't pass -S to Bison, the grammar
+       file does what is needed.
+
+2008-11-03  Akim Demaille  <demaille@gostai.com>
+
+       bench: Improve output.
+       * etc/bench.pl.in (bench_grammar): Tune the printf format.
+
+2008-11-03  Akim Demaille  <demaille@gostai.com>
+
+       bench: check impact of %debug on variants.
+       * etc/bench.pl.in (variant_grammar): Fix the computation of
+       $variant.
+       Generate a grammar file that can work with or without %debug.
+       Do use the @directive.
+       (bench_variant_parser): Check impact of %debug.
+       (@directives): Rename all the occurrences to...
+       (@directive): this, for consistency.
+
+2008-11-03  Akim Demaille  <demaille@gostai.com>
+
+       bench: report the size too.
+       * etc/bench.pl.in ($iterations): Defaults to -3.
+       (&bench_grammar): Require hireswallclock.
+       Compute and display the size of the result.
+       More comments.
+
+2008-11-03  Akim Demaille  <demaille@gostai.com>
+
+       bench: More use of the verbosity level.
+       * etc/bench.pl.in ($verbose, &verbose): New.
+       Use them.
+       More POD documentation.
+
+2008-11-03  Akim Demaille  <demaille@gostai.com>
+
+       bench.pl: a command line interface
+       * etc/bench.pl.in: More doc.
+       Some fixes in the documentation.
+       ($cflags, $iterations, &help, &getopt): New.
+       Use them.
+       (&variant_grammar): Let the number of stages be 10 times what is
+       specified.
+
+2008-11-03  Akim Demaille  <demaille@gostai.com>
+
+       Bench the use of Boost.Variants.
+       * etc/bench.pl.in ($cxx, &variant_grammar, &bench_variant_parser):
+       New.
+       (&compile): Be ready to compile C++ parsers.
+       (&bench_push_parser): Move debug information to the outermost
+       level.
+       * THANKS: Add Michiel De Wilde.
+
+2008-11-03  Akim Demaille  <demaille@gostai.com>
+
+       bench.pl: Pass directives as a list instead of as a string.
+       * etc/bench.pl.in (&directives): New.
+       (&triangular_grammar, &calc_grammar): Use it to format the Bison
+       directives.
+       (&triangular_grammar): Do use the directives (were ignored).
+       (&bench_grammar, &bench_push_parser): Adjust to pass lists of
+       directives.
+
+2008-11-03  Akim Demaille  <demaille@gostai.com>
+
+       Improve genericity of bench.pl.
+       * etc/bench.pl.in (&bench_grammar): Take the set of benches as
+       argument.
+       (&bench_push_parser): New.
+       Call it.
+
+2008-11-03  Akim Demaille  <demaille@gostai.com>
+
+       Add documentation to bench.pl.
+       * etc/bench.pl.in: Comment changes.
+
+2008-11-03  Akim Demaille  <demaille@gostai.com>
+
+       Fuse the three stacks into a single one.
+
+       In order to make it easy to perform benchmarks to ensure that
+       there are no performance loss, lalr1.cc is forked into
+       lalr1-fusion.cc.  Eventually, lalr1-fusion.cc will replace
+       lalr1.cc.
+
+       Meanwhile, to make sure that lalr1-fusion.cc is correctly
+       exercized by the test suite, the user must install a symbolic link
+       from lalr1.cc to it.
+
+       Instead of having three stacks (state, value, location), use a
+       stack of triples.  This considerably simplifies the code (and it
+       will be easier not to require locations as currently does the C++
+       parser), and also gives a 10% speedup according to
+       etc/bench (probably mainly since memory allocation is done once
+       instead of three times).
+
+       Another motivation is to make it easier to destruct properly
+       semantic values: now that they are bound to their state (hence
+       symbol type) it will be easier to call the appropriate destructor.
+
+       These changes should probably benefit the C parser too.
+
+       * data/lalr1.cc: Copy as...
+       * data/lalr1-fusion.cc: this new file.
+       (b4_rhs_value, b4_rhs_location): New definitions overriding those
+       from c++.m4.
+       (state_stack_type, semantic_stack_type, location_stack_type)
+       (yystate_stack_, yysemantic_stack_, yylocation_stack_): Remove.
+       (data_type, stack_type, yystack_): New.
+       (YYLLOC_DEFAULT, yypush_): Adjust.
+       (yyerror_range): Now based on data_type, not location_type.
+
+2008-11-03  Akim Demaille  <demaille@gostai.com>
+
+       Push the state, value, and location at the same time.
+       This is needed to prepare a forthcoming patch that fuses the three
+       stacks into one.
+
+       * data/lalr1.cc (parser::yypush_): New.
+       (parser::yynewstate): Change the semantics: instead of arriving to
+       this label when value and location have been pushed, but yystate
+       is to be pushed on the state stack, now the three of them must
+       have been pushed before.  yystate still must be the new state.
+       This allows to use yypush_ everywhere instead of individual
+       handling of the stacks.
+
+2008-11-03  Akim Demaille  <demaille@gostai.com>
+
+       Prefer references to pointers.
+       * data/lalr1.cc (b4_symbol_actions): New, overrides the default C
+       definition to use references instead of pointers.
+       (yy_symbol_value_print_, yy_symbol_print_, yydestruct_):
+       Take the value and location as references.
+       Adjust callers.
+
+2008-11-03  Akim Demaille  <demaille@gostai.com>
+
+       stack::size instead of stack::height.
+       * data/lalr1.cc (stack::height): Rename as...
+       (stack::size): this.
+       Fix the output type.
+       Comment changes.
+
+2008-11-03  Akim Demaille  <demaille@gostai.com>
+
+       Use variants to support objects as semantic values.
+       This patch was inspired by work by Michiel De Wilde.  But he used
+       Boost variants which (i) requires Boost on the user side, (ii) is
+       slow, and (iii) has useless overhead (the parser knows the type of
+       the semantic value there is no reason to duplicate this
+       information as Boost.Variants do).
+
+       This implementation reserves a buffer large enough to store the
+       largest objects.  yy::variant implements this buffer.  It was
+       implemented with Quentin Hocquet.
+
+       * src/output.c (type_names_output): New.
+       (output_skeleton): Invoke it.
+       * data/c++.m4 (b4_variant_if): New.
+       (b4_symbol_value): If needed, provide a definition for variants.
+       * data/lalr1.cc (b4_symbol_value, b4_symbol_action_)
+       (b4_symbol_variant, _b4_char_sizeof_counter, _b4_char_sizeof_dummy)
+       (b4_char_sizeof, yy::variant): New.
+       (parser::parse): If variants are requested, define
+       parser::union_type, parser::variant, change the definition of
+       semantic_type, construct $$ before running the user action instead
+       of performing a default $$ = $1.
+       * examples/variant.yy: New.
+       Based on an example by Michiel De Wilde.
+
+2008-11-03  Akim Demaille  <demaille@gostai.com>
+
+       Parameterize the extraction of semantic values.
+       To make future changes easier, no longer rely on ".TYPE" being the
+       way to get a semantic value.
+
+       * data/c.m4 (b4_symbol_value): New.
+       Use it.
+       * data/c++.m4, data/yacc.c: Use it.
+       * data/glr.c: Use b4_symbol_value.
+       (b4_rhs_data): New.
+       Use it.
+
+2008-11-03  Akim Demaille  <demaille@gostai.com>
+
+       Prepare easier M4 changes.
+       * data/lalr1.cc: Use escaped [] instead of literals to prepare
+       future changes.
+
 2008-11-02  Joel E. Denny  <jdenny@ces.clemson.edu>
 
        Initiate further development.
index 798704dd3ad4df896955c92fc36e9a36af7b3f10..339a3c63ae4eb14b0fd645b2a64b0cdc51963101 100644 (file)
@@ -1,7 +1,7 @@
-## Process this file with automake to produce Makefile.in -*-Makefile-*-
-
-## Copyright (C) 2001-2013 Free Software Foundation, Inc.
+## Process this file with automake to produce Makefile.in.
 
+# Copyright (C) 2001-2013 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
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+AUTOMAKE_OPTIONS = subdir-objects
 ACLOCAL_AMFLAGS = -I m4
 
-SUBDIRS = build-aux po runtime-po lib data src doc examples tests etc
+SUBDIRS = po runtime-po .
 
 # Files installed for use by Automake.
 aclocaldir = @aclocaldir@
 aclocal_DATA = m4/bison-i18n.m4
 
 EXTRA_DIST = .prev-version .version \
-  cfg.mk ChangeLog-1998 ChangeLog-2012 PACKAGING \
-  djgpp/Makefile.maint djgpp/README.in djgpp/config.bat \
-  djgpp/config.sed djgpp/config.site djgpp/config_h.sed \
-  djgpp/subpipe.c djgpp/subpipe.h djgpp/djunpack.bat \
-  djgpp/fnchange.lst djgpp/testsuite.sed
+  cfg.mk ChangeLog-1998 ChangeLog-2012 PACKAGING
+
+## Running the bison from this tarball.  To generate our own parser,
+## but also to run the tests.  Of course, you ought to keep a sane
+## version of Bison nearby...
+BISON = $(top_builddir)/tests/bison
+BISON_IN = $(top_srcdir)/tests/bison.in
+YACC = $(BISON) -o y.tab.c
+AM_YFLAGS = -d -v -Werror -Wall -Wno-yacc --report=all
+
+# Initialization before completion by local.mk's.
+AM_CFLAGS = $(WARN_CFLAGS)
+# Find builddir/src/scan-code.c etc.
+AM_CPPFLAGS = -I. -Ilib -I$(top_srcdir) -I$(top_srcdir)/lib
+BUILT_SOURCES =
+CLEANFILES =
+DISTCLEANFILES =
+EXTRA_DIST += $(dist_TESTS)
+MOSTLYCLEANDIRS =
+MOSTLYCLEANFILES =
+SUFFIXES =
+TESTS = $(dist_TESTS)
+check_PROGRAMS =
+dist_TESTS =
+noinst_LIBRARIES =
 
-MAINTAINER_CHECKS =                            \
-  maintainer-check                             \
-  maintainer-push-check                                \
-  maintainer-xml-check                         \
-  maintainer-release-check
-.PHONY: $(MAINTAINER_CHECKS)
-$(MAINTAINER_CHECKS):
-       $(AM_V_GEN)cd tests && $(MAKE) $(AM_MAKEFLAGS) $@
+include build-aux/local.mk
+include data/local.mk
+include djgpp/local.mk
+include doc/local.mk
+include etc/local.mk
+include examples/local.mk
+include lib/local.mk
+include src/local.mk
+include tests/local.mk
 
 # See comments in build-aux/git-version-gen.  However, we make .version depend
 # on configure so that .version and VERSION/PACKAGE_VERSION stay in sync in the
@@ -48,11 +70,11 @@ $(MAINTAINER_CHECKS):
 # a developer might naively reference .version in a test case while the bison
 # executable still compiles with VERSION, and so the test case might fail or
 # pass incorrectly.
-BUILT_SOURCES = $(top_srcdir)/.version
+BUILT_SOURCES += $(top_srcdir)/.version
 $(top_srcdir)/.version: configure
-       $(AM_V_GEN)echo $(VERSION) > $@-t && mv $@-t $@
+       echo $(VERSION) > $@-t && mv $@-t $@
 dist-hook: gen-ChangeLog
-       $(AM_V_GEN)echo $(VERSION) > $(distdir)/.tarball-version
+       echo $(VERSION) > $(distdir)/.tarball-version
 
 .PHONY: update-b4-copyright update-package-copyright-year
 update-b4-copyright:
diff --git a/NEWS b/NEWS
index 42c79408e9d4b17cebc6e97beaca21fc9fb3d98b..d7d89d2a86589bb9dcb73364dcd55da9ce306a25 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,575 @@ GNU Bison NEWS
 
 * Noteworthy changes in release ?.? (????-??-??) [?]
 
+** WARNING: Future backward-incompatibilities!
+
+  Like other GNU packages, Bison will start using some of the C99 features
+  for its own code, especially the definition of variables after statements.
+  The generated C parsers still aim at C90.
+
+** Backward incompatible changes
+
+*** Obsolete features
+
+  Support for YYFAIL is removed (deprecated in Bison 2.4.2): use YYERROR.
+
+  Support for yystype and yyltype is removed (deprecated in Bison 1.875):
+  use YYSTYPE and YYLTYPE.
+
+  Support for YYLEX_PARAM and YYPARSE_PARAM is removed (deprecated in Bison
+  1.875): use %lex-param, %parse-param, or %param.
+
+  Missing semicolons at the end of actions are no longer added (as announced
+  in the release 2.5).
+
+*** Use of YACC='bison -y'
+
+  TL;DR: With Autoconf <= 2.69, pass -Wno-yacc to (AM_)YFLAGS if you use
+  Bison extensions.
+
+  Traditional Yacc generates 'y.tab.c' whatever the name of the input file.
+  Therefore Makefiles written for Yacc expect 'y.tab.c' (and possibly
+  'y.tab.h' and 'y.outout') to be generated from 'foo.y'.
+
+  To this end, for ages, AC_PROG_YACC, Autoconf's macro to look for an
+  implementation of Yacc, was using Bison as 'bison -y'.  While it does
+  ensure compatible output file names, it also enables warnings for
+  incompatibilities with POSIX Yacc.  In other words, 'bison -y' triggers
+  warnings for Bison extensions.
+
+  Autoconf 2.70+ fixes this incompatibility by using YACC='bison -o y.tab.c'
+  (which also generates 'y.tab.h' and 'y.output' when needed).
+  Alternatively, disable Yacc warnings by passing '-Wno-yacc' to your Yacc
+  flags (YFLAGS, or AM_YFLAGS with Automake).
+
+** Bug fixes
+
+*** The epilogue is no longer affected by internal #defines (glr.c)
+
+  The glr.c skeleton uses defines such as #define yylval (yystackp->yyval) in
+  generated code.  These weren't properly undefined before the inclusion of
+  the user epilogue, so functions such as the following were butchered by the
+  preprocessor expansion:
+
+    int yylex (YYSTYPE *yylval);
+
+  This is fixed: yylval, yynerrs, yychar, and yylloc are now valid
+  identifiers for user-provided variables.
+
+*** stdio.h is no longer needed when locations are enabled (yacc.c)
+
+  Changes in Bison 2.7 introduced a dependency on FILE and fprintf when
+  locations are enabled.  This is fixed.
+
+** Diagnostics reported by Bison
+
+  Most of these features were contributed by Théophile Ranquet and Victor
+  Santet.
+
+*** Carets
+
+  Version 2.7 introduced caret errors, for a prettier output.  These are now
+  activated by default.  The old format can still be used by invoking Bison
+  with -fno-caret (or -fnone).
+
+  Some error messages that reproduced excerpts of the grammar are now using
+  the caret information only.  For instance on:
+
+    %%
+    exp: 'a' | 'a';
+
+  Bison 2.7 reports:
+
+    in.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
+    in.y:2.12-14: warning: rule useless in parser due to conflicts: exp: 'a' [-Wother]
+
+  Now bison reports:
+
+    in.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
+    in.y:2.12-14: warning: rule useless in parser due to conflicts [-Wother]
+     exp: 'a' | 'a';
+                ^^^
+
+  and "bison -fno-caret" reports:
+
+    in.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
+    in.y:2.12-14: warning: rule useless in parser due to conflicts [-Wother]
+
+*** Enhancements of the -Werror option
+
+  The -Werror=CATEGORY option is now recognized, and will treat specified
+  warnings as errors. The warnings need not have been explicitly activated
+  using the -W option, this is similar to what GCC 4.7 does.
+
+  For example, given the following command line, Bison will treat both
+  warnings related to POSIX Yacc incompatibilities and S/R conflicts as
+  errors (and only those):
+
+    $ bison -Werror=yacc,error=conflicts-sr input.y
+
+  If no categories are specified, -Werror will make all active warnings into
+  errors. For example, the following line does the same the previous example:
+
+    $ bison -Werror -Wnone -Wyacc -Wconflicts-sr input.y
+
+  (By default -Wconflicts-sr,conflicts-rr,deprecated,other is enabled.)
+
+  Note that the categories in this -Werror option may not be prefixed with
+  "no-". However, -Wno-error[=CATEGORY] is valid.
+
+  Note that -y enables -Werror=yacc. Therefore it is now possible to require
+  Yacc-like behavior (e.g., always generate y.tab.c), but to report
+  incompatibilities as warnings: "-y -Wno-error=yacc".
+
+*** The display of warnings is now richer
+
+  The option that controls a given warning is now displayed:
+
+    foo.y:4.6: warning: type clash on default action: <foo> != <bar> [-Wother]
+
+  In the case of warnings treated as errors, the prefix is changed from
+  "warning: " to "error: ", and the suffix is displayed, in a manner similar
+  to GCC, as [-Werror=CATEGORY].
+
+  For instance, where the previous version of Bison would report (and exit
+  with failure):
+
+    bison: warnings being treated as errors
+    input.y:1.1: warning: stray ',' treated as white space
+
+  it now reports:
+
+    input.y:1.1: error: stray ',' treated as white space [-Werror=other]
+
+*** Deprecated constructs
+
+  The new 'deprecated' warning category flags obsolete constructs whose
+  support will be discontinued.  It is enabled by default.  These warnings
+  used to be reported as 'other' warnings.
+
+*** 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
+
+*** Undefined but unused symbols
+
+  Bison used to raise an error for undefined symbols that are not used in
+  the grammar.  This is now only a warning.
+
+    %printer    {} symbol1
+    %destructor {} symbol2
+    %type <type>   symbol3
+    %%
+    exp: "a";
+
+*** 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>
+
+*** Conflicts
+
+  The warnings and error messages about shift/reduce and reduce/reduce
+  conflicts have been normalized.  For instance on the following foo.y file:
+
+    %glr-parser
+    %%
+    exp: exp '+' exp | '0' | '0';
+
+  compare the previous version of bison:
+
+    $ bison foo.y
+    foo.y: conflicts: 1 shift/reduce, 2 reduce/reduce
+    $ bison -Werror foo.y
+    bison: warnings being treated as errors
+    foo.y: conflicts: 1 shift/reduce, 2 reduce/reduce
+
+  with the new behavior:
+
+    $ bison foo.y
+    foo.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
+    foo.y: warning: 2 reduce/reduce conflicts [-Wconflicts-rr]
+    $ bison -Werror foo.y
+    foo.y: error: 1 shift/reduce conflict [-Werror=conflicts-sr]
+    foo.y: error: 2 reduce/reduce conflicts [-Werror=conflicts-rr]
+
+  When %expect or %expect-rr is used, such as with bar.y:
+
+    %expect 0
+    %glr-parser
+    %%
+    exp: exp '+' exp | '0' | '0';
+
+  Former behavior:
+
+    $ bison bar.y
+    bar.y: conflicts: 1 shift/reduce, 2 reduce/reduce
+    bar.y: expected 0 shift/reduce conflicts
+    bar.y: expected 0 reduce/reduce conflicts
+
+  New one:
+
+    $ bison bar.y
+    bar.y: error: shift/reduce conflicts: 1 found, 0 expected
+    bar.y: error: reduce/reduce conflicts: 2 found, 0 expected
+
+** Incompatibilities with POSIX Yacc
+
+  The 'yacc' category is no longer part of '-Wall', enable it explicitly
+  with '-Wyacc'.
+
+** 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}
+
+** Variable api.token.prefix
+
+  The variable api.token.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.token.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.value.type
+
+  This new %define variable supersedes the #define macro YYSTYPE.  The use
+  of YYSTYPE is discouraged.  In particular, #defining YYSTYPE *and* either
+  using %union or %defining api.value.type results in undefined behavior.
+
+  Either define api.value.type, or use "%union":
+
+    %union
+    {
+      int ival;
+      char *sval;
+    }
+    %token <ival> INT "integer"
+    %token <sval> STRING "string"
+    %printer { fprintf (yyo, "%d", $$); } <ival>
+    %destructor { free ($$); } <sval>
+
+    /* In yylex().  */
+    yylval.ival = 42; return INT;
+    yylval.sval = "42"; return STRING;
+
+  The %define variable api.value.type supports several special values.  The
+  keyword value 'union' means that the user provides genuine types, not
+  union member names such as "ival" and "sval" above (WARNING: will fail if
+  -y/--yacc/%yacc is enabled).
+
+    %define api.value.type union
+    %token <int> INT "integer"
+    %token <char *> STRING "string"
+    %printer { fprintf (yyo, "%d", $$); } <int>
+    %destructor { free ($$); } <char *>
+
+    /* In yylex().  */
+    yylval.INT = 42; return INT;
+    yylval.STRING = "42"; return STRING;
+
+  The keyword value variant is somewhat equivalent, but for C++ special
+  provision is made to allow classes to be used (more about this below).
+
+    %define api.value.type variant
+    %token <int> INT "integer"
+    %token <std::string> STRING "string"
+
+  Values between braces denote user defined types.  This is where YYSTYPE
+  used to be used.
+
+    %code requires
+    {
+      struct my_value
+      {
+        enum
+        {
+          is_int, is_string
+        } kind;
+        union
+        {
+          int ival;
+          char *sval;
+        } u;
+      };
+    }
+    %define api.value.type {struct my_value}
+    %token <u.ival> INT "integer"
+    %token <u.sval> STRING "string"
+    %printer { fprintf (yyo, "%d", $$); } <u.ival>
+    %destructor { free ($$); } <u.sval>
+
+    /* In yylex().  */
+    yylval.u.ival = 42; return INT;
+    yylval.u.sval = "42"; return STRING;
+
+** Variable parse.error
+
+  This variable controls the verbosity of error messages.  The use of the
+  %error-verbose directive is deprecated in favor of "%define parse.error
+  verbose".
+
+** Renamed %define variables
+
+  The following variables have been renamed for consistency.  Backward
+  compatibility is ensured, but upgrading is recommended.
+
+    lr.default-reductions      -> lr.default-reduction
+    lr.keep-unreachable-states -> lr.keep-unreachable-state
+    namespace                  -> api.namespace
+    stype                      -> api.value.type
+
+** Semantic predicates
+
+  Contributed by Paul Hilfinger.
+
+  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.
+
+** The directive %expect-rr is now an error in non GLR mode
+
+  It used to be an error only if used in non GLR mode, _and_ if there are
+  reduce/reduce conflicts.
+
+** Tokens are numbered in their order of appearance
+
+  Contributed by Valentin Tolmer.
+
+  With '%token A B', A had a number less than the one of B.  However,
+  precedence declarations used to generate a reversed order.  This is now
+  fixed, and introducing tokens with any of %token, %left, %right,
+  %precedence, or %nonassoc yields the same result.
+
+  When mixing declarations of tokens with a litteral character (e.g., 'a')
+  or with an identifier (e.g., B) in a precedence declaration, Bison
+  numbered the litteral characters first.  For example
+
+    %right A B 'c' 'd'
+
+  would lead to the tokens declared in this order: 'c' 'd' A B.  Again, the
+  input order is now preserved.
+
+  These changes were made so that one can remove useless precedence and
+  associativity declarations (i.e., map %nonassoc, %left or %right to
+  %precedence, or to %token) and get exactly the same output.
+
+** Useless precedence and associativity
+
+  Contributed by Valentin Tolmer.
+
+  When developing and maintaining a grammar, useless associativity and
+  precedence directives are common.  They can be a nuisance: new ambiguities
+  arising are sometimes masked because their conflicts are resolved due to
+  the extra precedence or associativity information.  Furthermore, it can
+  hinder the comprehension of a new grammar: one will wonder about the role
+  of a precedence, where in fact it is useless.  The following changes aim
+  at detecting and reporting these extra directives.
+
+*** Precedence warning category
+
+  A new category of warning, -Wprecedence, was introduced. It flags the
+  useless precedence and associativity directives.
+
+*** Useless associativity
+
+  Bison now warns about symbols with a declared associativity that is never
+  used to resolve conflicts.  In that case, using %precedence is sufficient;
+  the parsing tables will remain unchanged.  Solving these warnings may raise
+  useless precedence warnings, as the symbols no longer have associativity.
+  For example:
+
+    %left '+'
+    %left '*'
+    %%
+    exp:
+      "number"
+    | exp '+' "number"
+    | exp '*' exp
+    ;
+
+  will produce a
+
+    warning: useless associativity for '+', use %precedence [-Wprecedence]
+     %left '+'
+           ^^^
+
+*** Useless precedence
+
+  Bison now warns about symbols with a declared precedence and no declared
+  associativity (i.e., declared with %precedence), and whose precedence is
+  never used.  In that case, the symbol can be safely declared with %token
+  instead, without modifying the parsing tables.  For example:
+
+    %precedence '='
+    %%
+    exp: "var" '=' "number";
+
+  will produce a
+
+    warning: useless precedence for '=' [-Wprecedence]
+     %precedence '='
+                 ^^^
+
+*** Useless precedence and associativity
+
+  In case of both useless precedence and associativity, the issue is flagged
+  as follows:
+
+    %nonassoc '='
+    %%
+    exp: "var" '=' "number";
+
+  The warning is:
+
+    warning: useless precedence and associativity for '=' [-Wprecedence]
+     %nonassoc '='
+               ^^^
+
+** Empty rules
+
+  With help from Joel E. Denny and Gabriel Rassoul.
+
+  Empty rules (i.e., with an empty right-hand side) can now be explicitly
+  marked by the new %empty directive.  Using %empty on a non-empty rule is
+  an error.  The new -Wempty-rule warning reports empty rules without
+  %empty.  On the following grammar:
+
+    %%
+    s: a b c;
+    a: ;
+    b: %empty;
+    c: 'a' %empty;
+
+  bison reports:
+
+    3.4-5: warning: empty rule without %empty [-Wempty-rule]
+     a: {}
+        ^^
+    5.8-13: error: %empty on non-empty rule
+     c: 'a' %empty {};
+            ^^^^^^
+
+** Java skeleton improvements
+
+  Contributed by Paolo Bonzini.
+
+  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++ skeletons improvements
+
+*** The parser header is no longer mandatory (lalr1.cc, glr.cc)
+
+  Using %defines is now optional.  Without it, the needed support classes
+  are defined in the generated parser, instead of additional files (such as
+  location.hh, position.hh and stack.hh).
+
+*** Locations are no longer mandatory (lalr1.cc, glr.cc)
+
+  Both lalr1.cc and glr.cc no longer require %location.
+
+*** syntax_error exception (lalr1.cc)
+
+  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).
+
+*** %define api.value.type variant
+
+  This is based on a submission from Michiel De Wilde.  With help
+  from Théophile Ranquet.
+
+  In this mode, complex C++ objects can be used as semantic values.  For
+  instance:
+
+    %token <::std::string> TEXT;
+    %token <int> NUMBER;
+    %token SEMICOLON ";"
+    %type <::std::string> item;
+    %type <::std::list<std::string>> list;
+    %%
+    result:
+      list  { std::cout << $1 << std::endl; }
+    ;
+
+    list:
+      %empty        { /* Generates an empty string list. */ }
+    | list item ";" { std::swap ($$, $1); $$.push_back ($2); }
+    ;
+
+    item:
+      TEXT    { std::swap ($$, $1); }
+    | NUMBER  { $$ = string_cast ($1); }
+    ;
+
+*** %define api.token.constructor
+
+  When variants are enabled, Bison can generate functions to build the
+  tokens.  This guarantees that the token type (e.g., NUMBER) is consistent
+  with the semantic value (e.g., int):
+
+    parser::symbol_type yylex ()
+    {
+      parser::location_type loc = ...;
+      ...
+      return parser::make_TEXT ("Hello, world!", loc);
+      ...
+      return parser::make_NUMBER (42, loc);
+      ...
+      return parser::make_SEMICOLON (loc);
+      ...
+    }
+
+* Noteworthy changes in release ?.? (????-??-??) [?]
+
 ** Bug fixes
 
 *** Fix compiler attribute portability (yacc.c)
@@ -20,6 +589,8 @@ GNU Bison NEWS
 
 ** Diagnostics are improved
 
+  Contributed by Théophile Ranquet.
+
 *** Changes in the format of error messages
 
   This used to be the format of many error reports:
@@ -58,8 +629,8 @@ GNU Bison NEWS
      exp: exp '+' exp { $exp = $1 + $3; };
                   ^^^
 
-  The default behaviour for now is still not to display these unless
-  explictly asked with -fcaret (or -fall). However, in a later release, it
+  The default behavior for now is still not to display these unless
+  explicitly asked with -fcaret (or -fall). However, in a later release, it
   will be made the default behavior (but may still be deactivated with
   -fno-caret).
 
@@ -105,6 +676,8 @@ GNU Bison NEWS
 
 ** Graph improvements in DOT and XSLT
 
+  Contributed by Théophile Ranquet.
+
   The graphical presentation of the states is more readable: their shape is
   now rectangular, the state number is clearly displayed, and the items are
   numbered and left-justified.
@@ -144,7 +717,7 @@ GNU Bison NEWS
 
   Other issues in the test suite have been addressed.
 
-  Nul characters are correctly displayed in error messages.
+  Null characters are correctly displayed in error messages.
 
   When possible, yylloc is correctly initialized before calling yylex.  It
   is no longer necessary to initialize it in the %initial-action.
@@ -215,7 +788,7 @@ GNU Bison NEWS
 
 * Noteworthy changes in release 2.6.1 (2012-07-30) [stable]
 
 Bison no longer executes user-specified M4 code when processing a grammar.
+ Bison no longer executes user-specified M4 code when processing a grammar.
 
 ** Future Changes
 
@@ -253,7 +826,7 @@ GNU Bison NEWS
 
 * 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.
@@ -546,7 +1119,9 @@ GNU Bison NEWS
   These features are experimental.  More user feedback will help to
   stabilize them.
 
-** LAC (Lookahead Correction) for syntax error handling:
+** LAC (Lookahead Correction) for syntax error handling
+
+  Contributed by Joel E. Denny.
 
   Canonical LR, IELR, and LALR can suffer from a couple of problems
   upon encountering a syntax error.  First, the parser might perform
@@ -2057,8 +2632,13 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
  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 calc yyo fval Wmaybe
- LocalWords:  yyvsp pragmas noreturn java's
+ LocalWords:  lang yyoutput dvi html ps POSIX lvalp llocp Wother nterm arg init
+ LocalWords:  TOK calc yyo fval Wconflicts parsers yystackp yyval yynerrs
+ LocalWords:  Théophile Ranquet Santet fno fnone stype associativity Tolmer
+ LocalWords:  Wprecedence Rassoul Wempty Paolo Bonzini parser's Michiel loc
+ LocalWords:  redeclaration sval fcaret reentrant XSLT xsl Wmaybe yyvsp Tedi
+ LocalWords:  pragmas noreturn untyped Rozenman unexpanded Wojciech Polak
+ LocalWords:  Alexandre MERCHANTABILITY yytype
 
 Local Variables:
 mode: outline
diff --git a/README b/README
index ad667a236b5c656d8ea72d81fdea56464629e6d6..ed393c28560e81711ea9347b917756415996f72b 100644 (file)
--- a/README
+++ b/README
@@ -30,7 +30,7 @@ not answer them, please send mail to <help-bison@gnu.org>.
 
 * Bug reports
 Please send bug reports to <bug-bison@gnu.org>.  Please include the
-version number from `bison --version', and a complete, self-contained
+version number from 'bison --version', and a complete, self-contained
 test case in each bug report.
 
 * Copyright statements
index 515d2a91bd3d5b75fcc0a5946311b28288328e72..28870cb268de91ad3704123dff12769b9fd135ad 100644 (file)
@@ -35,6 +35,13 @@ of the .output file etc.  This excludes impossible error messages
 (comparable to assert/abort), and all the --trace output which is
 meant for the maintainers only.
 
+** Horizontal tabs
+Do not add horizontal tab characters to any file in Bison's repository
+except where required.  For example, do not use tabs to format C code.
+However, make files, ChangeLog, and some regular expressions require
+tabs.  Also, test cases might need to contain tabs to check that Bison
+properly processes tabs in its input.
+
 
 * Working from the repository
 
@@ -169,6 +176,28 @@ decide whether to update.
 ** make check
 Use liberally.
 
+** TESTSUITEFLAGS
+
+The default is for make check to run all tests sequentially. This can be
+very time consumming when checking repeatedly or on slower setups. This can
+be sped up in two ways:
+
+Using -j, in a make-like fashion, for example:
+  $ make check TESTSUITEFLAGS='-j8'
+
+Running only the tests of a certain category, as specified in the AT files
+with AT_KEYWORDS([[category]]). Categories include:
+  - c++, for c++ parsers
+  - deprec, for tests concerning deprecated constructs.
+  - glr, for glr parsers
+  - java, for java parsers
+  - report, for automaton dumps
+
+To run a specific set of tests, use -k (for "keyword"). For example:
+  $ make check TESTSUITEFLAGS='-k c++'
+
+Both can be combined.
+
 ** Typical errors
 If the test suite shows failures such as the following one
 
@@ -240,6 +269,9 @@ release:
   that it does not make sense for glr.c, which should be ANSI, but
   currently is actually GNU C, nor for lalr1.cc.
 
+- Test with a very recent version of GCC for both C and C++.  Testing
+  with older versions that are still in use is nice too.
+
 
 * Release Procedure
 This section needs to be updated to take into account features from
index 23084822cc83f0bf7abfac61e65e614da14e44e0..9af367312cef358cc5517a1e52b72d00ada7d7f6 100644 (file)
@@ -9,7 +9,7 @@ Bison supports the @N construction, which gives you access to
 the starting and ending line number and character number associated
 with any of the symbols in the current rule.
 
-Also, Bison supports the command `%expect N' which says not to mention
+Also, Bison supports the command '%expect N' which says not to mention
 the conflicts if there are N shift/reduce conflicts and no reduce/reduce
 conflicts.
 
@@ -25,8 +25,8 @@ LALR(1) Look-Ahead Sets", ACM Transactions on Programming Languages
 and Systems (TOPLAS) 4, 4 (October 1982), 615-649.  Their
 technique is the standard one now.)
 
-       paul rubin
-       free software foundation
+        paul rubin
+        free software foundation
 
 
 [DeRemer-Pennello reference corrected by Paul Eggert <eggert@cs.ucla.edu>,
diff --git a/THANKS b/THANKS
index a2d3ea231d4e03a7140e89a0f856cecd48b30cf7..a7d1d47ec9c244f9d4dd74dafd2c3e0134a75106 100644 (file)
--- a/THANKS
+++ b/THANKS
@@ -44,6 +44,7 @@ Fabrice Bauzac            noon@cote-dazur.com
 Florian Krohm             florian@edamail.fishkill.ibm.com
 Frank Heckenbach          frank@g-n-u.de
 Frans Englich             frans.englich@telia.com
+Gabriel Rassoul           gabriel.rassoul@epita.fr
 Georg Sauthoff            gsauthof@TechFak.Uni-Bielefeld.DE
 George Neuner             gneuner2@comcast.net
 Gilles Espinasse          g.esp@free.fr
@@ -76,10 +77,12 @@ Matt Kraai                kraai@alumni.cmu.edu
 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
 Nelson H. F. Beebe        beebe@math.utah.edu
+Nick Bowler               nbowler@elliptictech.com
 Nicolas Burrus            nicolas.burrus@epita.fr
 Nicolas Tisserand         nicolas.tisserand@epita.fr
 Noah Friedman             friedman@gnu.org
@@ -96,6 +99,7 @@ Peter Fales               psfales@lucent.com
 Peter Hamorsky            hamo@upjs.sk
 Peter Simons              simons@cryp.to
 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
@@ -104,6 +108,7 @@ Richard Stallman          rms@gnu.org
 Rob Vermaas               rob.vermaas@gmail.com
 Robert Anisko             anisko_r@epita.fr
 Rob Conde                 rob.conde@ai-solutions.com
+Roland Levillain          roland@lrde.epita.fr
 Satya Kiran Popuri        satyakiran@gmail.com
 Sebastian Setzer          sebastian.setzer.ext@siemens.com
 Sebastien Fricker         sebastien.fricker@gmail.com
@@ -122,6 +127,7 @@ Tom Tromey                tromey@cygnus.com
 Tommy Nordgren            tommy.nordgren@chello.se
 Troy A. Johnson           troyj@ecn.purdue.edu
 Tys Lefering              gccbison@gmail.com
+Valentin Tolmer           nitnelave1@gmail.com
 Victor Khomenko           victor.khomenko@newcastle.ac.uk
 Vin Shelton               acs@alumni.princeton.edu
 W.C.A. Wijngaards         wouter@NLnetLabs.nl
diff --git a/TODO b/TODO
index 45307ce1316afb298da4a8cbd18e9ea9388be150..09fce0896dc52bd9163d3c72655c7862898567b9 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,26 +1,63 @@
 * Short term
 ** Graphviz display code thoughts
 The code for the --graph option is over two files: print_graph, and
-graphviz. I believe this is because Bison used to also produce VCG graphs,
-but since this is no longer true, maybe we could consider these files for
-fusion.
-
-Little effort factoring seems to have been given to factoring in these files,
-and their print-xml and print counterpart. We would very much like to re-use
-the pretty format of states from .output in the .dot
-
-Also, the underscore in print_graph.[ch] isn't very fitting considering
-the dashes in the other filenames.
-
-** 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
+graphviz. This is because Bison used to also produce VCG graphs, but since
+this is no longer true, maybe we could consider these files for fusion.
+
+An other consideration worth noting is that print_graph.c (correct me if I
+am wrong) should contain generic functions, whereas graphviz.c and other
+potential files should contain just the specific code for that output
+format. It will probably prove difficult to tell if the implementation is
+actually generic whilst only having support for a single format, but it
+would be nice to keep stuff a bit tidier: right now, the construction of the
+bitset used to show reductions is in the graphviz-specific code, and on the
+opposite side we have some use of \l, which is graphviz-specific, in what
+should be generic code.
+
+Little effort seems to have been given to factoring these files and their
+rint{,-xml} counterpart. We would very much like to re-use the pretty format
+of states from .output for the graphs, etc.
+
+Also, the underscore in print_graph.[ch] isn't very fitting considering the
+dashes in the other filenames.
+
+Since graphviz dies on medium-to-big grammars, maybe consider an other tool?
+
+** push-parser
+Check it too when checking the different kinds of parsers.  And be
+sure to check that the initial-action is performed once per parsing.
+
+** m4 names
+b4_shared_declarations is no longer what it is.  Make it
+b4_parser_declaration for instance.
+
+** yychar in lalr1.cc
+There is a large difference bw maint and master on the handling of
+yychar (which was removed in lalr1.cc).  See what needs to be
+back-ported.
+
+
+    /* 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.  */
+
+    /* Make sure we have latest lookahead translation.  See comments at
+       user semantic actions for why this is necessary.  */
+    yytoken = yytranslate_ (yychar);
+
+
+** stack.hh
+Get rid of it.  The original idea is nice, but actually it makes
+the code harder to follow, and uselessly different from the other
+skeletons.
 
 ** Get rid of fake #lines [Bison: ...]
 Possibly as simple as checking whether the column number is nonnegative.
@@ -48,14 +85,7 @@ since it is no longer bound to a particular parser, it's just a
 ** Rename LR0.cc
 as lr0.cc, why upper case?
 
-** bench several bisons.
-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
@@ -101,9 +131,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:
 
@@ -121,12 +148,6 @@ really possible?  The test suite does not exercise this case.
 This shows that it would be interesting to manage to install skeleton
 coverage analysis to the test suite.
 
-** Table definitions
-It should be very easy to factor the definition of the various tables,
-including the separation bw declaration and definition.  See for
-instance b4_table_define in lalr1.cc.  This way, we could even factor
-C vs. C++ definitions.
-
 * From lalr1.cc to yacc.c
 ** Single stack
 Merging the three stacks in lalr1.cc simplified the code, prompted for
@@ -155,13 +176,13 @@ part of $default.  Should we make the two reductions explicit, or just
 keep $default?  See the following point.
 
 ** Disabled Reductions
-See `tests/conflicts.at (Defaulted Conflicted Reduction)', and decide
+See 'tests/conflicts.at (Defaulted Conflicted Reduction)', and decide
 what we want to do.
 
 ** Documentation
 Extend with error productions.  The hard part will probably be finding
 the right rule so that a single state does not exhibit too many yet
-undocumented ``features''.  Maybe an empty action ought to be
+undocumented ''features''.  Maybe an empty action ought to be
 presented too.  Shall we try to make a single grammar with all these
 features, or should we have several very small grammars?
 
@@ -222,9 +243,9 @@ into
         exp: exp '+' exp | exp '&' exp;
 
 when there are no actions.  This can significantly speed up some
-grammars.  I can't find the papers.  In particular the book `LR
+grammars.  I can't find the papers.  In particular the book 'LR
 parsing: Theory and Practice' is impossible to find, but according to
-`Parsing Techniques: a Practical Guide', it includes information about
+'Parsing Techniques: a Practical Guide', it includes information about
 this issue.  Does anybody have it?
 
 
@@ -252,9 +273,6 @@ Paul notes:
         tokens, either via escapes (e.g., "x\0y") or via a NUL byte in
         the source code.  This should get fixed.
 
-* --graph
-Show reductions.
-
 * Broken options ?
 ** %token-table
 ** Skeleton strategy
index d0685c224043f43b0887292e9931ed03670511aa..c58470e28b448e481dad64d7fd7c0b91e0c33739 100644 (file)
@@ -21,12 +21,12 @@ gnulib_modules='
   configmake
   dirname
   error extensions fdl fopen-safer
-  getline
   getopt-gnu
   gettext git-version-gen gitlog-to-changelog
   gpl-3.0 hash inttypes isnan javacomp-script
-  javaexec-script ldexpl malloc-gnu mbschr mbsrchr
+  javaexec-script ldexpl malloc-gnu
   mbswidth
+  non-recursive-gnulib-prefix-hack
   obstack
   obstack-printf
   perror progname
@@ -36,7 +36,11 @@ gnulib_modules='
   spawn-pipe stdbool stpcpy strdup-posix strerror strtoul strverscmp
   unistd unistd-safer unlocked-io update-copyright unsetenv verify
   warnings
-  xalloc xalloc-die xmemdup0 xstrndup
+  xalloc
+  xalloc-die
+  xconcat-filename
+  xmemdup0
+  xstrndup
 
   fprintf-posix printf-posix snprintf-posix sprintf-posix
   vsnprintf-posix vsprintf-posix
@@ -46,9 +50,8 @@ gnulib_modules='
 XGETTEXT_OPTIONS=$XGETTEXT_OPTIONS'\\\
  --from-code=UTF-8\\\
  --flag=asprintf:2:c-format\\\
- --flag=complain:1:c-format --flag=complain_at:2:c-format\\\
- --flag=fatal:1:c-format --flag=fatal_at:2:c-format\\\
- --flag=warn:1:c-format  --flag=warn_at:2:c-format\\\
+ --flag=complain:3:c-format\\\
+ --flag=complain_indent:4:c-format\\\
  --flag=unexpected_end:2:c-format\\\
 '
 XGETTEXT_OPTIONS_RUNTIME=$XGETTEXT_OPTIONS'\\\
@@ -76,6 +79,9 @@ gnulib_tool_option_extras='--symlink --makefile-name=gnulib.mk'
 
 bootstrap_post_import_hook()
 {
+  # Massage lib/gnulib.mk before using it later in the bootstrapping process.
+  build-aux/prefix-gnulib-mk --lib-name=$gnulib_name lib/$gnulib_mk
+
   # Ensure that ChangeLog exists, for automake.
   test -f ChangeLog || touch ChangeLog
 }
index 17aa54519265f2431467152b889de31489b0c954..2c8b6fe13291927d6e8c29a8675a2ca1e29f31e9 100644 (file)
@@ -1,11 +1,10 @@
-/Makefile
-/Makefile.in
 /announce-gen
 /arg-nonnull.h
 /c++defs.h
 /compile
 /config.guess
 /config.rpath
+/config.rpath~
 /config.sub
 /depcomp
 /do-release-commit-and-tag
 /link-warning.h
 /mdate-sh
 /missing
+/test-driver
 /texinfo.tex
 /update-copyright
 /useless-if-before-free
 /vc-list-files
 /warn-on-use.h
 /ylwrap
+/prefix-gnulib-mk
diff --git a/build-aux/Makefile.am b/build-aux/Makefile.am
deleted file mode 100644 (file)
index d307de4..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-## Copyright (C) 2006, 2009-2013 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/>.
-
-EXTRA_DIST =                                   \
-  cross-options.pl                             \
-  darwin11.4.0.valgrind                                \
-  prev-version.txt                             \
-  update-b4-copyright
index 7762e276c27d60cf3e985136f062a7d0930be093..0f5009ce0c9afe062b953e7973bc08f2adea2bd7 100755 (executable)
@@ -18,50 +18,50 @@ while (<STDIN>)
         \s                # Spaces.
         /x)
     {
-       my ($short, $long, $opt, $arg) = ($1, $2, $3, $4);
-       $short = '' if ! defined $short;
-       $short = '-d' if $long eq '--defines' && ! $short;
-       my $dir = '%' . substr($long, 2);
-       if (index ($scanner, "\"$dir\"") < 0)
-       {
-         if ($long eq '--force-define') { $dir = '%define'; }
-         else { $dir = ''; }
-       }
-       if ($arg)
-       {
+        my ($short, $long, $opt, $arg) = ($1, $2, $3, $4);
+        $short = '' if ! defined $short;
+        $short = '-d' if $long eq '--defines' && ! $short;
+        my $dir = '%' . substr($long, 2);
+        if (index ($scanner, "\"$dir\"") < 0)
+        {
+          if ($long eq '--force-define') { $dir = '%define'; }
+          else { $dir = ''; }
+        }
+        if ($arg)
+        {
             # if $opt, $arg contains the closing ].
             substr ($arg, -1) = ''
                 if $opt eq '[';
-           $arg =~ s/^=//;
+            $arg =~ s/^=//;
             $arg = lc ($arg);
-           my $dir_arg = $arg;
+            my $dir_arg = $arg;
             # If the argument is compite (e.g., for --define[=NAME[=VALUE]]),
             # put each word in @var, to build @var{name}[=@var{value}], not
             # @var{name[=value]}].
-           $arg =~ s/(\w+)/\@var{$1}/g;
-           my $long_arg = "=$arg";
-           if ($opt eq '[') {
-             $long_arg = "[$long_arg]";
-             $arg = "[$arg]";
-           }
-           # For arguments of directives: this only works if all arguments
-           # are strings and have the same syntax as on the command line.
-           if ($dir_arg eq 'name[=value]')
-           {
-               $dir_arg = '@var{name} ["@var{value}"]';
-           }
-           else
-           {
-               $dir_arg =~ s/(\w+)/\@var{"$1"}/g;
-               $dir_arg = '[' . $dir_arg . ']'
-                   if $opt eq '[';
-           }
-           $long = "$long$long_arg";
-           $short = "$short $arg" if $short && $short ne '-d';
-           $dir = "$dir $dir_arg" if $dir;
-       }
-       $option{$long} = $short;
-       $directive{$long} = $dir;
+            $arg =~ s/(\w+)/\@var{$1}/g;
+            my $long_arg = "=$arg";
+            if ($opt eq '[') {
+              $long_arg = "[$long_arg]";
+              $arg = "[$arg]";
+            }
+            # For arguments of directives: this only works if all arguments
+            # are strings and have the same syntax as on the command line.
+            if ($dir_arg eq 'name[=value]')
+            {
+                $dir_arg = '@var{name} ["@var{value}"]';
+            }
+            else
+            {
+                $dir_arg =~ s/(\w+)/\@var{"$1"}/g;
+                $dir_arg = '[' . $dir_arg . ']'
+                    if $opt eq '[';
+            }
+            $long = "$long$long_arg";
+            $short = "$short $arg" if $short && $short ne '-d';
+            $dir = "$dir $dir_arg" if $dir;
+        }
+        $option{$long} = $short;
+        $directive{$long} = $dir;
     }
 }
 
diff --git a/build-aux/local.mk b/build-aux/local.mk
new file mode 100644 (file)
index 0000000..8922ea5
--- /dev/null
@@ -0,0 +1,21 @@
+# Copyright (C) 2000-2013 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/>.
+
+EXTRA_DIST +=                                   \
+  build-aux/cross-options.pl                    \
+  build-aux/darwin11.4.0.valgrind               \
+  build-aux/move-if-change                      \
+  build-aux/prev-version.txt                    \
+  build-aux/update-b4-copyright
diff --git a/build-aux/move-if-change b/build-aux/move-if-change
new file mode 120000 (symlink)
index 0000000..2df61a6
--- /dev/null
@@ -0,0 +1 @@
+../gnulib/build-aux/move-if-change
\ No newline at end of file
diff --git a/cfg.mk b/cfg.mk
index 3418ac37e23bc9af73f3b923b3a4be6f19e704f6..7fbad01b3e9f33f23ced316c1a3cca3c8cc08930 100644 (file)
--- a/cfg.mk
+++ b/cfg.mk
@@ -37,15 +37,9 @@ url_dir_list = \
   ftp://$(gnu_rel_host)/gnu/bison
 
 # Tests not to run as part of "make distcheck".
-# Exclude changelog-check here so that there's less churn in ChangeLog
-# files -- otherwise, you'd need to have the upcoming version number
-# at the top of the file for each `make distcheck' run.
-local-checks-to-skip = \
-  changelog-check \
+local-checks-to-skip =                 \
   sc_immutable_NEWS                    \
-  sc_prohibit_always_true_header_tests \
-  sc_prohibit_atoi_atof                        \
-  sc_prohibit_strcmp
+  sc_prohibit_atoi_atof
 
 # The local directory containing the checked-out copy of gnulib used in
 # this release.  Used solely to get a date for the "announcement" target.
@@ -61,6 +55,11 @@ update-copyright: update-b4-copyright update-package-copyright-year
 update-copyright-env = \
   UPDATE_COPYRIGHT_FORCE=1 UPDATE_COPYRIGHT_USE_INTERVALS=1
 
+
+## -------------------- ##
+## More syntax-checks.  ##
+## -------------------- ##
+
 # At least for Mac OS X's grep, the order between . and [ in "[^.[]"
 # matters:
 # $ LC_ALL=fr_FR grep -nE '[^[.]' /dev/null
@@ -73,21 +72,108 @@ sc_at_parser_check:
        halt='use AT_PARSER_CHECK for and only for generated parsers'   \
          $(_sc_search_regexp)
 
+# Indent only with spaces.
+# Taken from Coreutils.
+sc_prohibit_tab_based_indentation:
+       @prohibit='^ *  '                                               \
+       halt='TAB in indentation; use only spaces'                      \
+         $(_sc_search_regexp)
+
+# Prohibit the use of `...` in tests/.  Use $(...) instead.
+# Taken from Coreutils.
+# Not ready for Bison yet.
+#sc_prohibit_test_backticks:
+#      @prohibit='`' in_vc_files='^tests/'             \
+#      halt='use $$(...), not `...` in tests/'         \
+#        $(_sc_search_regexp)
+
+# Enforce recommended preprocessor indentation style.
+# Taken from Coreutils.
+sc_preprocessor_indentation:
+       @if cppi --version >/dev/null 2>&1; then                        \
+         $(VC_LIST_EXCEPT) | grep '\.[ch]$$' | xargs cppi -a -c        \
+           || { echo '$(ME): incorrect preprocessor indentation' 1>&2; \
+               exit 1; };                                              \
+       else                                                            \
+         echo '$(ME): skipping test $@: cppi not installed' 1>&2;      \
+       fi
+
+###########################################################
+# Taken from Coreutils.
+_p0 = \([^"'/]\|"\([^\"]\|[\].\)*"\|'\([^\']\|[\].\)*'
+_pre = $(_p0)\|[/][^"'/*]\|[/]"\([^\"]\|[\].\)*"\|[/]'\([^\']\|[\].\)*'\)*
+_pre_anchored = ^\($(_pre)\)
+_comment_and_close = [^*]\|[*][^/*]\)*[*][*]*/
+# help font-lock mode: '
+
+# A sed expression that removes ANSI C and ISO C99 comments.
+# Derived from the one in GNU gettext's 'moopp' preprocessor.
+_sed_remove_comments =                                 \
+/[/][/*]/{                                             \
+  ta;                                                  \
+  :a;                                                  \
+  s,$(_pre_anchored)//.*,\1,;                          \
+  te;                                                  \
+  s,$(_pre_anchored)/[*]\($(_comment_and_close),\1 ,;  \
+  ta;                                                  \
+  /^$(_pre)[/][*]/{                                    \
+    s,$(_pre_anchored)/[*].*,\1 ,;                     \
+    tu;                                                        \
+    :u;                                                        \
+    n;                                                 \
+    s,^\($(_comment_and_close),,;                      \
+    tv;                                                        \
+    s,^.*$$,,;                                         \
+    bu;                                                        \
+    :v;                                                        \
+  };                                                   \
+  :e;                                                  \
+}
+# Quote all single quotes.
+_sed_rm_comments_q = $(subst ','\'',$(_sed_remove_comments))
+# help font-lock mode: '
+
+_space_before_paren_exempt =? \\n\\$$
+_space_before_paren_exempt = \
+  (^ *\#|\\n\\$$|%s\(to %s|(date|group|character)\(s\))
+# Ensure that there is a space before each open parenthesis in C code.
+sc_space_before_open_paren:
+       @if $(VC_LIST_EXCEPT) | grep -l '\.[ch]$$' > /dev/null; then    \
+         fail=0;                                                       \
+         for c in $$($(VC_LIST_EXCEPT) | grep '\.[ch]$$'); do          \
+           sed '$(_sed_rm_comments_q)' $$c 2>/dev/null                 \
+             | grep -i '[[:alnum:]]('                                  \
+             | grep -vE '$(_space_before_paren_exempt)'                \
+             | grep . && { fail=1; echo "*** $$c"; };                  \
+         done;                                                         \
+         test $$fail = 1 &&                                            \
+           { echo '$(ME): the above files lack a space-before-open-paren' \
+               1>&2; exit 1; } || :;                                   \
+       else :;                                                         \
+       fi
+
+## -------------------------- ##
+## syntax-checks exceptions.  ##
+## -------------------------- ##
+
 exclude = \
   $(foreach a,$(1),$(eval $(subst $$,$$$$,exclude_file_name_regexp--sc_$(a))))
 $(call exclude,                                                                \
   bindtextdomain=^lib/main.c$$                                         \
+  preprocessor_indentation=^data/|^lib/|^src/parse-gram.[ch]$$         \
   program_name=^lib/main.c$$                                           \
   prohibit_always-defined_macros=^data/yacc.c$$|^djgpp/                        \
   prohibit_always-defined_macros+=?|^lib/timevar.c$$                   \
   prohibit_always-defined_macros+=?|^src/(parse-gram.c|system.h)$$     \
   prohibit_always-defined_macros+=?|^tests/regression.at$$             \
+  prohibit_always_true_header_tests=^djgpp/subpipe.h$$|^lib/timevar.c$$        \
+  prohibit_always_true_header_tests+=?|^m4/timevar.m4$$                        \
   prohibit_defined_have_decl_tests=?|^lib/timevar.c$$                  \
   prohibit_doubled_word=^tests/named-refs.at$$                          \
   prohibit_magic_number_exit=^doc/bison.texi$$                         \
   prohibit_magic_number_exit+=?|^tests/(conflicts|regression).at$$     \
+  prohibit_strcmp=^doc/bison\.texi|tests/local\.at$$                   \
+  prohibit_tab_based_indentation=\.(am|mk)$$|^djgpp/|^\.git            \
   require_config_h_first=^(lib/yyerror|data/(glr|yacc))\.c$$           \
-  space_tab=^tests/(input|c\+\+)\.at$$                                 \
-  trailing_blank=^src/parse-gram.[ch]$$                                        \
   unmarked_diagnostics=^(djgpp/|doc/bison.texi$$|tests/c\+\+\.at$$)    \
 )
index 2c9be082917b3c533713751e8f4e5ce6e0a8d55a..e6ef8baf91a3877b0e255816fc3a76f2a42d9228 100644 (file)
@@ -18,7 +18,7 @@
 # In order for some versions of Sun Studio to compile our C++ test cases
 # correctly, we need Autoconf 2.64 or better to handle the restrict
 # keyword in at least string.h from gnulib.  We need Autoconf 2.68 or
-# better to avoid a typo in the `configure --help' entry for the YACC
+# better to avoid a typo in the 'configure --help' entry for the YACC
 # environment variable.
 AC_PREREQ([2.68])
 m4_pattern_forbid([^gl_[A-Z]])
@@ -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])
@@ -141,9 +143,9 @@ if test "$enable_gcc_warnings" = yes; then
     gl_WARN_ADD([$i], [WARN_CXXFLAGS_TEST])
   done
   # Clang++ 3.2+ reject C code generated by Flex.
-  gl_WARN_ADD([-Wno-null-conversion], [WARN_NO_NULL_CONVERSION_CXXFLAGS])
-  # Variants break strict aliasing analysis.
-  gl_WARN_ADD([-fno-strict-aliasing], [NO_STRICT_ALIAS_CXXFLAGS])
+  gl_WARN_ADD([-Wno-null-conversion], [FLEX_SCANNER_CXXFLAGS])
+  # So does G++ 4.8 in std=c++11 mode.
+  gl_WARN_ADD([-Wno-zero-as-null-pointer-constant], [FLEX_SCANNER_CXXFLAGS])
   CXXFLAGS=$save_CXXFLAGS
   AC_LANG_POP([C++])
 fi
@@ -159,8 +161,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=;;
@@ -219,7 +221,7 @@ AC_CONFIG_FILES([etc/bench.pl], [chmod +x etc/bench.pl])
 
 # 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
@@ -236,17 +238,10 @@ 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
 
 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 --git a/data/.cvsignore b/data/.cvsignore
deleted file mode 100644 (file)
index 3dda729..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-Makefile.in
-Makefile
diff --git a/data/.gitignore b/data/.gitignore
deleted file mode 100644 (file)
index 9ee6454..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-/Makefile.in
-/Makefile
diff --git a/data/Makefile.am b/data/Makefile.am
deleted file mode 100644 (file)
index 5678c25..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-## Copyright (C) 2002, 2005-2013 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 = README bison.m4 \
-   c-like.m4 \
-   c-skel.m4 c.m4 yacc.c glr.c \
-   c++-skel.m4 c++.m4 location.cc lalr1.cc glr.cc stack.hh \
-   java-skel.m4 java.m4 lalr1.java
-
-m4sugardir = $(pkgdatadir)/m4sugar
-dist_m4sugar_DATA = m4sugar/m4sugar.m4 m4sugar/foreach.m4
-
-xsltdir = $(pkgdatadir)/xslt
-dist_xslt_DATA =                               \
-   xslt/bison.xsl                              \
-   xslt/xml2dot.xsl                            \
-   xslt/xml2text.xsl                           \
-   xslt/xml2xhtml.xsl
index 9dc9ca6ef3027d123f6c36ff0cd87f594b395819..842c0041865d5a9b612f8603d55e1bf8c6093fcb 100644 (file)
@@ -27,7 +27,7 @@ Currently, the supported skeletons are:
 These skeletons are the only ones supported by the Bison team.
 Because the interface between skeletons and the bison program is not
 finished, *we are not bound to it*.  In particular, Bison is not
-mature enough for us to consider that ``foreign skeletons'' are
+mature enough for us to consider that "foreign skeletons" are
 supported.
 
 * m4sugar
index d87082840a3b5ff85047d8593a37267ff8056af6..910cdf26270e79a6cc4a0fddcaa9feb5c116f8e4 100644 (file)
 ## 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
@@ -82,6 +85,20 @@ m4_changecom([#])
 ])
 
 
+# b4_divert_kill(CODE)
+# --------------------
+# Expand CODE for its side effects, discard its output.
+m4_define([b4_divert_kill],
+[m4_divert_text([KILL], [$1])])
+
+
+# b4_define_silent(MACRO, CODE)
+# -----------------------------
+# Same as m4_define, but throw away the expansion of CODE.
+m4_define([b4_define_silent],
+[m4_define([$1], [b4_divert_kill([$2])])])
+
+
 ## ---------------- ##
 ## Error handling.  ##
 ## ---------------- ##
@@ -103,30 +120,16 @@ _m4eof
 ])dnl
 m4_if(m4_sysval, [0], [], [m4_fatal([$0: cannot write to stdout])])])
 
-# b4_error(KIND, FORMAT, [ARG1], [ARG2], ...)
-# -------------------------------------------
-# Write @KIND(FORMAT@,ARG1@,ARG2@,...@) to stdout.
+# b4_error(KIND, START, END, FORMAT, [ARG1], [ARG2], ...)
+# -------------------------------------------------------
+# Write @KIND(START@,END@,FORMAT@,ARG1@,ARG2@,...@) to stdout.
 #
 # For example:
 #
-#   b4_error([[warn]], [[invalid value for '%s': %s]], [[foo]], [[3]])
+#   b4_error([[complain]], [[input.y:2.3]], [[input.y:5.4]],
+#            [[invalid %s]], [[foo]])
 m4_define([b4_error],
-[b4_cat([[@]$1[(]$2[]]dnl
-[m4_if([$#], [2], [],
-       [m4_foreach([b4_arg],
-                   m4_dquote(m4_shift(m4_shift($@))),
-                   [[@,]b4_arg])])[@)]])])
-
-# b4_error_at(KIND, START, END, FORMAT, [ARG1], [ARG2], ...)
-# ----------------------------------------------------------
-# Write @KIND_at(START@,END@,FORMAT@,ARG1@,ARG2@,...@) to stdout.
-#
-# For example:
-#
-#   b4_error_at([[complain]], [[input.y:2.3]], [[input.y:5.4]],
-#               [[invalid %s]], [[foo]])
-m4_define([b4_error_at],
-[b4_cat([[@]$1[_at(]$2[@,]$3[@,]$4[]]dnl
+[b4_cat([[@complain][(]$1[@,]$2[@,]$3[@,]$4[]]dnl
 [m4_if([$#], [4], [],
        [m4_foreach([b4_arg],
                    m4_dquote(m4_shift(m4_shift(m4_shift(m4_shift($@))))),
@@ -146,21 +149,21 @@ m4_define([b4_error_at],
 #   m4_define([asdf], [ASDF])
 #   m4_define([fsa], [FSA])
 #   m4_define([fdsa], [FDSA])
-#   b4_warn([[[asdf), asdf]]], [[[fsa), fsa]]], [[[fdsa), fdsa]]])
-#   b4_warn([[asdf), asdf]], [[fsa), fsa]], [[fdsa), fdsa]])
-#   b4_warn()
-#   b4_warn(1)
-#   b4_warn(1, 2)
+#   b4_warn_at([[[asdf), asdf]]], [[[fsa), fsa]]], [[[fdsa), fdsa]]])
+#   b4_warn_at([[asdf), asdf]], [[fsa), fsa]], [[fdsa), fdsa]])
+#   b4_warn_at()
+#   b4_warn_at(1)
+#   b4_warn_at(1, 2)
 #
 # Should produce this without newlines:
 #
-#   @warn([asdf), asdf]@,[fsa), fsa]@,[fdsa), fdsa]@)
-#   @warn(asdf), asdf@,fsa), fsa@,fdsa), fdsa@)
+#   @warn_at([asdf), asdf]@,@,@,[fsa), fsa]@,[fdsa), fdsa]@)
+#   @warn(asdf), asdf@,@,@,fsa), fsa@,fdsa), fdsa@)
 #   @warn(@)
 #   @warn(1@)
 #   @warn(1@,2@)
 m4_define([b4_warn],
-[b4_error([[warn]], $@)])
+[b4_error([[warn]], [], [], $@)])
 
 # b4_warn_at(START, END, FORMAT, [ARG1], [ARG2], ...)
 # ---------------------------------------------------
@@ -170,15 +173,15 @@ m4_define([b4_warn],
 #
 #   b4_warn_at([[input.y:2.3]], [[input.y:5.4]], [[invalid %s]], [[foo]])
 m4_define([b4_warn_at],
-[b4_error_at([[warn]], $@)])
+[b4_error([[warn]], $@)])
 
 # b4_complain(FORMAT, [ARG1], [ARG2], ...)
 # ----------------------------------------
-# Write @complain(FORMAT@,ARG1@,ARG2@,...@) to stdout.
+# Bounce to b4_complain_at.
 #
 # See b4_warn example.
 m4_define([b4_complain],
-[b4_error([[complain]], $@)])
+[b4_error([[complain]], [], [], $@)])
 
 # b4_complain_at(START, END, FORMAT, [ARG1], [ARG2], ...)
 # -------------------------------------------------------
@@ -186,15 +189,15 @@ m4_define([b4_complain],
 #
 # See b4_warn_at example.
 m4_define([b4_complain_at],
-[b4_error_at([[complain]], $@)])
+[b4_error([[complain]], $@)])
 
 # b4_fatal(FORMAT, [ARG1], [ARG2], ...)
 # -------------------------------------
-# Write @fatal(FORMAT@,ARG1@,ARG2@,...@) to stdout and exit.
+# Bounce to b4_fatal_at.
 #
 # See b4_warn example.
 m4_define([b4_fatal],
-[b4_error([[fatal]], $@)dnl
+[b4_error([[fatal]], [], [], $@)dnl
 m4_exit(1)])
 
 # b4_fatal_at(START, END, FORMAT, [ARG1], [ARG2], ...)
@@ -203,7 +206,7 @@ m4_exit(1)])
 #
 # See b4_warn_at example.
 m4_define([b4_fatal_at],
-[b4_error_at([[fatal]], $@)dnl
+[b4_error([[fatal]], $@)dnl
 m4_exit(1)])
 
 
@@ -218,6 +221,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_join(ARG1, ...)
+# _b4_join(ARG1, ...)
+# -------------------
+# Join with comma, skipping empty arguments.
+# b4_join calls itself recursively until it sees the first non-empty
+# argument, then calls _b4_join which prepends each non-empty argument
+# with a comma.
+m4_define([b4_join],
+[m4_if([$#$1],
+       [1], [],
+       [m4_ifval([$1],
+                 [$1[]_$0(m4_shift($@))],
+                 [$0(m4_shift($@))])])])
+
+# _b4_join(ARGS1, ...)
+# --------------------
+m4_define([_b4_join],
+[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[STATE-NUM] -- Default reduction number in state STATE-NUM.
+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 whose
+number is the opposite.  If YYTABLE_NINF, syntax error.]])
+
+$1([check], [b4_check])
+
+$1([stos], [b4_stos],
+   [[YYSTOS[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 on the 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.  ##
@@ -229,8 +313,8 @@ m4_define([b4_ints_in],
 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: ]b4_$1_flag)])])
 
 
 # b4_define_flag_if(FLAG)
@@ -243,7 +327,7 @@ m4_define([b4_define_flag_if],
 # _b4_define_flag_if($1, $2, FLAG)
 # --------------------------------
 # Work around the impossibility to define macros inside macros,
-# because issuing `[$1]' is not possible in M4.  GNU M4 should provide
+# because issuing '[$1]' is not possible in M4.  GNU M4 should provide
 # $$1 a la M5/TeX.
 m4_define([_b4_define_flag_if],
 [m4_if([$1$2], $[1]$[2], [],
@@ -256,15 +340,225 @@ 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 various FIELDS are:
+#
+# - has_id: 0 or 1.
+#   Whether the symbol has an id.
+# - id: string
+#   If has_id, the id.  Guaranteed to be usable as a C identifier.
+#   Prefixed by api.token.prefix if defined.
+# - tag: string.
+#   A representat of the symbol.  Can be 'foo', 'foo.id', '"foo"' etc.
+# - user_number: integer
+#   The assigned (external) number as used by yylex.
+# - is_token: 0 or 1
+#   Whether this is a terminal symbol.
+# - number: integer
+#   The internalized number (used after yytranslate).
+# - has_type: 0, 1
+#   Whether has a semantic value.
+# - type_tag: string
+#   When api.value.type=union, the generated name for the union member.
+#   yytype_INT etc. for symbols that has_id, otherwise yytype_1 etc.
+# - type
+#   If it has a semantic value, its type tag, or, if variant are used,
+#   its type.
+#   In the case of api.value.type=union, type is the real type (e.g. int).
+# - has_printer: 0, 1
+# - printer: string
+# - printer_file: string
+# - printer_line: integer
+#   If the symbol has a printer, everything about it.
+# - has_destructor, destructor, destructor_file, destructor_line
+#   Likewise.
+#
+# 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 token prefix.
+m4_define([b4_symbol],
+[m4_case([$2],
+         [id],    [m4_do([b4_percent_define_get([api.token.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_tag_comment(SYMBOL-NUM)
+# ---------------------------------
+# Issue a comment giving the tag of symbol NUM.
+m4_define([b4_symbol_tag_comment],
+[b4_comment([b4_symbol([$1], [tag])])
+])
+
+
+# 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],
+[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;
+
+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_actions(KIND, [TYPE = yytype])
+# ----------------------------------------
+# Emit the symbol actions for KIND ("printer" or "destructor").
+# Dispatch on TYPE.
+m4_define([b4_symbol_actions],
+[m4_pushdef([b4_actions_], m4_expand([b4_symbol_foreach([b4_symbol_$1])]))dnl
+m4_ifval(m4_defn([b4_actions_]),
+[switch (m4_default([$2], [yytype]))
+    {
+      m4_defn([b4_actions_])
+      default:
+        break;
+    }dnl
+],
+[YYUSE (m4_default([$2], [yytype]));])dnl
+m4_popdef([b4_actions_])dnl
+])
+
+# b4_symbol_case_(SYMBOL-NUM)
+# ---------------------------
+# Issue a "case NUM" for SYMBOL-NUM.
+m4_define([b4_symbol_case_],
+[case b4_symbol([$1], [number]): b4_symbol_tag_comment([$1])])
+])
+
+
+# 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.
+#
+# To specify the action to run, define b4_dollar_dollar(NUMBER,
+# TAG, TYPE).
+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]))])
 
 
 
@@ -284,11 +578,21 @@ m4_define([b4_basename],
 # -----------------------
 m4_define([b4_syncline],
 [b4_flag_if([synclines],
-[b4_sync_end([__line__], [b4_basename(m4_quote(__file__))])
-b4_sync_start([$1], [$2])])])
+[b4_sync_start([$1], [$2]) b4_sync_end([__line__],
+                                       [b4_basename(m4_quote(__file__))])[]dnl
+])])
+
+# b4_sync_start(LINE, FILE)
+# -----------------------
+# Syncline for the new place.  Typically a directive for the compiler.
+m4_define([b4_sync_start], [b4_comment([$2:$1])])
+
+# b4_sync_end(LINE, FILE)
+# -----------------------
+# Syncline for the current place, which ends.  Typically a comment
+# left for the reader.
+m4_define([b4_sync_end],   [b4_comment([$2:$1])])
 
-m4_define([b4_sync_end], [b4_comment([Line $1 of $2])])
-m4_define([b4_sync_start], [b4_comment([Line $1 of $2])])
 
 # b4_user_code(USER-CODE)
 # -----------------------
@@ -310,14 +614,14 @@ m4_define([b4_define_user_code],
 # b4_user_initial_action
 # b4_user_post_prologue
 # b4_user_pre_prologue
-# b4_user_stype
+# b4_user_union_members
 # ----------------------
 # Macros that issue user code, ending with synclines.
 b4_define_user_code([actions])
 b4_define_user_code([initial_action])
 b4_define_user_code([post_prologue])
 b4_define_user_code([pre_prologue])
-b4_define_user_code([stype])
+b4_define_user_code([union_members])
 
 
 # b4_check_user_names(WHAT, USER-LIST, BISON-NAMESPACE)
@@ -373,7 +677,6 @@ m4_popdef([b4_end])dnl
 
 
 
-
 ## --------------------- ##
 ## b4_percent_define_*.  ##
 ## --------------------- ##
@@ -403,7 +706,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,
@@ -421,7 +723,21 @@ m4_define([b4_percent_define_get_loc],
           [m4_pushdef([b4_loc], m4_indir([b4_percent_define_loc(]$1[)]))dnl
 b4_loc[]dnl
 m4_popdef([b4_loc])],
-          [b4_fatal([[b4_percent_define_get_loc: undefined %%define variable '%s']], [$1])])])
+          [b4_fatal([[$0: undefined %%define variable '%s']], [$1])])])
+
+# b4_percent_define_get_kind(VARIABLE)
+# ------------------------------------
+# Get the kind (code, keyword, string) of VARIABLE, i.e., how its
+# value was defined (braces, not delimiters, quotes).
+#
+# If the %define variable VARIABLE is undefined, complain fatally
+# since that's a Bison or skeleton error.  Don't record this as a
+# Bison usage of VARIABLE as there's no reason to suspect that the
+# user-supplied value has yet influenced the output.
+m4_define([b4_percent_define_get_kind],
+[m4_ifdef([b4_percent_define_kind(]$1[)],
+          [m4_indir([b4_percent_define_kind(]$1[)])],
+          [b4_fatal([[$0: undefined %%define variable '%s']], [$1])])])
 
 # b4_percent_define_get_syncline(VARIABLE)
 # ----------------------------------------
@@ -438,7 +754,7 @@ m4_popdef([b4_loc])],
 m4_define([b4_percent_define_get_syncline],
 [m4_ifdef([b4_percent_define_syncline(]$1[)],
           [m4_indir([b4_percent_define_syncline(]$1[)])],
-          [b4_fatal([[b4_percent_define_get_syncline: undefined %%define variable '%s']], [$1])])])
+          [b4_fatal([[$0: undefined %%define variable '%s']], [$1])])])
 
 # b4_percent_define_ifdef(VARIABLE, IF-TRUE, [IF-FALSE])
 # ------------------------------------------------------
@@ -452,8 +768,14 @@ m4_define([b4_percent_define_get_syncline],
 #   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])
 # --------------------------------------------------------
@@ -476,7 +798,8 @@ m4_define([b4_percent_define_flag_if],
                                            [[invalid value for %%define Boolean variable '%s']],
                                            [$1])],
                            [[b4_percent_define_flag_if($1)]])])],
-  [b4_fatal([[b4_percent_define_flag_if: undefined %%define variable '%s']], [$1])])])
+  [b4_fatal([[$0: undefined %%define variable '%s']], [$1])])])
+
 
 # b4_percent_define_default(VARIABLE, DEFAULT)
 # --------------------------------------------
@@ -496,6 +819,21 @@ m4_define([b4_percent_define_default],
                         [[<skeleton default value>:-1.-1]]]])dnl
             m4_define([b4_percent_define_syncline(]$1[)], [[]])])])
 
+
+# b4_percent_define_if_define(NAME, [VARIABLE = NAME])
+# ----------------------------------------------------
+# Define b4_NAME_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(m4_default([$2], [$1]),
+                                      [$3], [$4])])])
+m4_define([b4_percent_define_if_define],
+[b4_percent_define_default([m4_default([$2], [$1])], [[false]])
+b4_percent_define_if_define_([$1], [$2], $[1], $[2])])
+
+
 # b4_percent_define_check_values(VALUES)
 # --------------------------------------
 # Mimic muscle_percent_define_check_values in ../src/muscle-tab.h exactly
@@ -529,11 +867,11 @@ m4_define([_b4_percent_define_check_values],
                          [$1],
                          m4_dquote(m4_indir([b4_percent_define(]$1[)])))
           m4_foreach([b4_value], m4_dquote(m4_shift($@)),
-                     [b4_complain_at(b4_percent_define_get_loc([$1]),
+                     [b4_error([[note]], b4_percent_define_get_loc([$1]), []
                                      [[accepted value: '%s']],
                                      m4_dquote(b4_value))])])dnl
    m4_popdef([b4_good_value])],
-  [b4_fatal([[b4_percent_define_check_values: undefined %%define variable '%s']], [$1])])])
+  [b4_fatal([[$0: undefined %%define variable '%s']], [$1])])])
 
 # b4_percent_code_get([QUALIFIER])
 # --------------------------------
@@ -567,7 +905,62 @@ 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.token.prefix, it is empty.
+m4_percent_define_default([[api.token.prefix]], [[]])
+
+# b4_parse_assert_if([IF-ASSERTIONS-ARE-USED], [IF-NOT])
+# b4_parse_trace_if([IF-DEBUG-TRACES-ARE-ENABLED], [IF-NOT])
+# b4_token_ctor_if([IF-YYLEX-RETURNS-A-TOKEN], [IF-NOT])
+# ----------------------------------------------
+b4_percent_define_if_define([token_ctor], [api.token.constructor])
+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_bison_locations_if([IF-TRUE])
+# --------------------------------
+# Expand IF-TRUE if using locations, and using the default location
+# type.
+m4_define([b4_bison_locations_if],
+[b4_locations_if([b4_percent_define_ifdef([[api.location.type]], [], [$1])])])
+
+
+# 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])])
+
+
+# b4_variant_if([IF-VARIANT-ARE-USED], [IF-NOT])
+# ----------------------------------------------
+b4_percent_define_if_define([variant])
+m4_define([b4_variant_flag], [[0]])
+b4_percent_define_ifdef([[api.value.type]],
+   [m4_case(b4_percent_define_get_kind([[api.value.type]]), [keyword],
+            [m4_case(b4_percent_define_get([[api.value.type]]), [variant],
+                    [m4_define([b4_variant_flag], [[1]])])])])
+b4_define_flag_if([variant])
 
 
 ## ----------------------------------------------------------- ##
@@ -601,10 +994,32 @@ m4_define_default([b4_parse_param], [])
 m4_define_default([b4_location_initial_column], [1])
 m4_define_default([b4_location_initial_line],   [1])
 
-# Sanity checks.
+
+## --------------- ##
+## Sanity checks.  ##
+## --------------- ##
+
+# api.prefix >< %name-prefix.
 b4_percent_define_ifdef([api.prefix],
 [m4_ifdef([b4_prefix],
 [b4_complain_at(b4_percent_define_get_loc([api.prefix]),
                 [['%s' and '%s' cannot be used together]],
                 [%name-prefix],
                 [%define api.prefix])])])
+
+# api.value.type >< %union.
+b4_percent_define_ifdef([api.value.type],
+[m4_ifdef([b4_union_members],
+[b4_complain_at(b4_percent_define_get_loc([api.value.type]),
+                [['%s' and '%s' cannot be used together]],
+                [%union],
+                [%define api.value.type])])])
+
+# api.value.type=union >< %yacc.
+b4_percent_define_ifdef([api.value.type],
+[m4_if(b4_percent_define_get([api.value.type]), [union],
+[b4_yacc_if(dnl
+[b4_complain_at(b4_percent_define_get_loc([api.value.type]),
+                [['%s' and '%s' cannot be used together]],
+                [%yacc],
+                [%define api.value.type "union"])])])])
index 429b9e925e987c46a7b323c5b9495d6f1d9aa0fb..e2c20fbd612dad753accace8e5f1b8b2318196c7 100644 (file)
 
 m4_include(b4_pkgdatadir/[c.m4])
 
+# b4_comment(TEXT, [PREFIX])
+# --------------------------
+# Put TEXT in comment. Prefix all the output lines with PREFIX.
+m4_define([b4_comment],
+[b4_comment_([$1], [$2// ], [$2// ])])
+
+
 ## ---------------- ##
 ## Default values.  ##
 ## ---------------- ##
 
-# Default parser class name.
 b4_percent_define_default([[parser_class_name]], [[parser]])
 
 # Don't do that so that we remember whether we're using a user
@@ -32,28 +38,31 @@ b4_percent_define_default([[parser_class_name]], [[parser]])
 # b4_percent_define_default([[api.location.type]], [[location]])
 
 b4_percent_define_default([[filename_type]], [[std::string]])
-b4_percent_define_default([[namespace]], m4_defn([b4_prefix]))
+b4_percent_define_default([[api.namespace]], m4_defn([b4_prefix]))
+
 b4_percent_define_default([[global_tokens_and_yystype]], [[false]])
 b4_percent_define_default([[define_location_comparison]],
                           [m4_if(b4_percent_define_get([[filename_type]]),
                                  [std::string], [[true]], [[false]])])
 
 
+
 ## ----------- ##
 ## Namespace.  ##
 ## ----------- ##
 
-m4_define([b4_namespace_ref], [b4_percent_define_get([[namespace]])])
+m4_define([b4_namespace_ref], [b4_percent_define_get([[api.namespace]])])
 
-# Don't permit an empty b4_namespace_ref.  Any `::parser::foo' appended to it
-# would compile as an absolute reference with `parser' in the global namespace.
+
+# Don't permit an empty b4_namespace_ref.  Any '::parser::foo' appended to it
+# would compile as an absolute reference with 'parser' in the global namespace.
 # b4_namespace_open would open an anonymous namespace and thus establish
 # internal linkage.  This would compile.  However, it's cryptic, and internal
 # linkage for the parser would be specified in all translation units that
 # include the header, which is always generated.  If we ever need to permit
 # internal linkage somehow, surely we can find a cleaner approach.
 m4_if(m4_bregexp(b4_namespace_ref, [^[  ]*$]), [-1], [],
-[b4_complain_at(b4_percent_define_get_loc([[namespace]]),
+[b4_complain_at(b4_percent_define_get_loc([[api.namespace]]),
                 [[namespace reference is empty]])])
 
 # Instead of assuming the C++ compiler will do it, Bison should reject any
@@ -64,36 +73,36 @@ m4_if(m4_bregexp(b4_namespace_ref, [^[       ]*$]), [-1], [],
 # Specifically, don't allow empty names as b4_namespace_open would just convert
 # those into anonymous namespaces, and that might tempt some users.
 m4_if(m4_bregexp(b4_namespace_ref, [::[         ]*::]), [-1], [],
-[b4_complain_at(b4_percent_define_get_loc([[namespace]]),
+[b4_complain_at(b4_percent_define_get_loc([[api.namespace]]),
                 [[namespace reference has consecutive "::"]])])
 m4_if(m4_bregexp(b4_namespace_ref, [::[         ]*$]), [-1], [],
-[b4_complain_at(b4_percent_define_get_loc([[namespace]]),
+[b4_complain_at(b4_percent_define_get_loc([[api.namespace]]),
                 [[namespace reference has a trailing "::"]])])
 
 m4_define([b4_namespace_open],
-[b4_user_code([b4_percent_define_get_syncline([[namespace]])
+[b4_user_code([b4_percent_define_get_syncline([[api.namespace]])
 [namespace ]m4_bpatsubst(m4_dquote(m4_bpatsubst(m4_dquote(b4_namespace_ref),
                                                 [^\(.\)[        ]*::], [\1])),
                          [::], [ { namespace ])[ {]])])
 
 m4_define([b4_namespace_close],
-[b4_user_code([b4_percent_define_get_syncline([[namespace]])
+[b4_user_code([b4_percent_define_get_syncline([[api.namespace]])
 m4_bpatsubst(m4_dquote(m4_bpatsubst(m4_dquote(b4_namespace_ref[ ]),
                                     [^\(.\)[    ]*\(::\)?\([^][:]\|:[^:]\)*],
                                     [\1])),
              [::\([^][:]\|:[^:]\)*], [} ])[} // ]b4_namespace_ref])])
 
 
-# b4_token_enums(LIST-OF-PAIRS-TOKEN-NAME-TOKEN-NUMBER)
-# -----------------------------------------------------
+# b4_token_enums
+# --------------
 # Output the definition of the tokens as enums.
 m4_define([b4_token_enums],
-[/* Tokens.  */
-   enum yytokentype {
-m4_map_sep([     b4_token_enum], [,
-],
-           [$@])
-   };
+[[enum yytokentype
+      {
+        ]m4_join([,
+        ],
+                 b4_symbol_map([b4_token_enum]))[
+      };]dnl
 ])
 
 
@@ -104,11 +113,323 @@ m4_map_sep([     b4_token_enum], [,
 ## ----------------- ##
 
 
+
+# b4_value_type_declare
+# ---------------------
+# Declare semantic_type.
+m4_define([b4_value_type_declare],
+[b4_value_type_setup[]dnl
+[    /// Symbol semantic values.
+]m4_bmatch(b4_percent_define_get_kind([[api.value.type]]),
+[code],
+[[    typedef ]b4_percent_define_get([[api.value.type]])[ semantic_type;]],
+[m4_bmatch(b4_percent_define_get([[api.value.type]]),
+[union\|union-directive],
+[[    union semantic_type
+    {
+    ]b4_user_union_members[
+    };]])])dnl
+])
+
+
+# b4_public_types_declare
+# -----------------------
+# Define the public types: token, semantic value, location, and so forth.
+# Depending on %define token_lex, may be output in the header or source file.
+m4_define([b4_public_types_declare],
+[[#ifndef ]b4_api_PREFIX[STYPE
+]b4_value_type_declare[
+#else
+    typedef ]b4_api_PREFIX[STYPE semantic_type;
+#endif]b4_locations_if([
+    /// Symbol locations.
+    typedef b4_percent_define_get([[api.location.type]],
+                                  [[location]]) location_type;])[
+
+    /// Syntax errors thrown from user actions.
+    struct syntax_error : std::runtime_error
+    {
+      syntax_error (]b4_locations_if([const location_type& l, ])[const std::string& m);]b4_locations_if([
+      location_type location;])[
+    };
+
+    /// Tokens.
+    struct token
+    {
+      ]b4_token_enums[
+    };
+
+    /// (External) token type, as returned by yylex.
+    typedef token::yytokentype token_type;
+
+    /// Internal symbol number.
+    typedef int symbol_number_type;
+
+    /// Internal symbol number for tokens (subsumed by symbol_number_type).
+    typedef ]b4_int_type_for([b4_translate])[ token_number_type;
+
+    /// A complete symbol.
+    ///
+    /// Expects its Base type to provide access to the symbol type
+    /// via type_get().
+    ///
+    /// Provide access to semantic value]b4_locations_if([ and location])[.
+    template <typename Base>
+    struct basic_symbol : Base
+    {
+      /// Alias to Base.
+      typedef Base super_type;
+
+      /// Default constructor.
+      basic_symbol ();
+
+      /// Copy constructor.
+      basic_symbol (const basic_symbol& other);
+]b4_variant_if([[
+      /// Constructor for valueless symbols, and symbols from each type.
+]b4_type_foreach([b4_basic_symbol_constructor_declare])], [[
+      /// Constructor for valueless symbols.
+      basic_symbol (typename Base::kind_type t]b4_locations_if([,
+                    const location_type& l])[);]])[
+
+      /// Constructor for symbols with semantic value.
+      basic_symbol (typename Base::kind_type t,
+                    const semantic_type& v]b4_locations_if([,
+                    const location_type& l])[);
+
+      ~basic_symbol ();
+
+      /// Destructive move, \a s is emptied into this.
+      void move (basic_symbol& s);
+
+      /// The semantic value.
+      semantic_type value;]b4_locations_if([
+
+      /// The location.
+      location_type location;])[
+
+    private:
+      /// Assignment operator.
+      basic_symbol& operator= (const basic_symbol& other);
+    };
+
+    /// Type access provider for token (enum) based symbols.
+    struct by_type
+    {
+      /// Default constructor.
+      by_type ();
+
+      /// Copy constructor.
+      by_type (const by_type& other);
+
+      /// The symbol type as needed by the constructor.
+      typedef token_type kind_type;
+
+      /// Constructor from (external) token numbers.
+      by_type (kind_type t);
+
+      /// Steal the symbol type from \a that.
+      void move (by_type& that);
+
+      /// The (internal) type number (corresponding to \a type).
+      /// -1 when this symbol is empty.
+      symbol_number_type type_get () const;
+
+      /// The token.
+      token_type token () const;
+
+      enum { empty = 0 };
+
+      /// The symbol type.
+      /// -1 when this symbol is empty.
+      token_number_type type;
+    };
+
+    /// "External" symbols: returned by the scanner.
+    typedef basic_symbol<by_type> symbol_type;
+
+]b4_symbol_constructor_declare])
+
+
+# b4_public_types_define
+# ----------------------
+# Provide the implementation needed by the public types.
+m4_define([b4_public_types_define],
+[[  inline
+  ]b4_parser_class_name[::syntax_error::syntax_error (]b4_locations_if([const location_type& l, ])[const std::string& m)
+    : std::runtime_error (m)]b4_locations_if([
+    , location (l)])[
+  {}
+
+  // basic_symbol.
+  template <typename Base>
+  inline
+  ]b4_parser_class_name[::basic_symbol<Base>::basic_symbol ()
+    : value ()
+  {}
+
+  template <typename Base>
+  inline
+  ]b4_parser_class_name[::basic_symbol<Base>::basic_symbol (const basic_symbol& other)
+    : Base (other)
+    , value ()]b4_locations_if([
+    , location (other.location)])[
+  {
+    ]b4_variant_if([b4_symbol_variant([other.type_get ()], [value], [copy],
+                                      [other.value])],
+                   [value = other.value;])[
+  }
+
+
+  template <typename Base>
+  inline
+  ]b4_parser_class_name[::basic_symbol<Base>::basic_symbol (]b4_join(
+          [typename Base::kind_type t],
+          [const semantic_type& v],
+          b4_locations_if([const location_type& l]))[)
+    : Base (t)
+    , value (]b4_variant_if([], [v])[)]b4_locations_if([
+    , location (l)])[
+  {]b4_variant_if([[
+    (void) v;
+    ]b4_symbol_variant([this->type_get ()], [value], [copy], [v])])[}
+
+]b4_variant_if([[
+  // Implementation of basic_symbol constructor for each type.
+]b4_type_foreach([b4_basic_symbol_constructor_define])], [[
+  /// Constructor for valueless symbols.
+  template <typename Base>
+  inline
+  ]b4_parser_class_name[::basic_symbol<Base>::basic_symbol (]b4_join(
+          [typename Base::kind_type t],
+          b4_locations_if([const location_type& l]))[)
+    : Base (t)
+    , value ()]b4_locations_if([
+    , location (l)])[
+  {}]])[
+
+  template <typename Base>
+  inline
+  ]b4_parser_class_name[::basic_symbol<Base>::~basic_symbol ()
+  {]b4_variant_if([[
+    // User destructor.
+    symbol_number_type yytype = this->type_get ();
+    switch (yytype)
+    {
+]b4_symbol_foreach([b4_symbol_destructor])dnl
+[   default:
+      break;
+    }
+
+    // Type destructor.
+  ]b4_symbol_variant([[yytype]], [[value]], [[template destroy]])])[
+  }
+
+  template <typename Base>
+  inline
+  void
+  ]b4_parser_class_name[::basic_symbol<Base>::move (basic_symbol& s)
+  {
+    super_type::move(s);
+    ]b4_variant_if([b4_symbol_variant([this->type_get ()], [value], [move],
+                                      [s.value])],
+                   [value = s.value;])[]b4_locations_if([
+    location = s.location;])[
+  }
+
+  // by_type.
+  inline
+  ]b4_parser_class_name[::by_type::by_type ()
+     : type (empty)
+  {}
+
+  inline
+  ]b4_parser_class_name[::by_type::by_type (const by_type& other)
+    : type (other.type)
+  {}
+
+  inline
+  ]b4_parser_class_name[::by_type::by_type (token_type t)
+    : type (yytranslate_ (t))
+  {}
+
+  inline
+  void
+  ]b4_parser_class_name[::by_type::move (by_type& that)
+  {
+    type = that.type;
+    that.type = empty;
+  }
+
+  inline
+  int
+  ]b4_parser_class_name[::by_type::type_get () const
+  {
+    return type;
+  }
+]b4_token_ctor_if([[
+  inline
+  ]b4_parser_class_name[::token_type
+  ]b4_parser_class_name[::by_type::token () const
+  {
+    // 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])[
+    yytoken_number_[] =
+    {
+  ]b4_toknum[
+    };
+    return static_cast<token_type> (yytoken_number_[type]);
+  }
+]])[]dnl
+b4_symbol_constructor_define])
+
+
+# b4_symbol_constructor_declare
+# b4_symbol_constructor_define
+# -----------------------------
+# Declare/define symbol constructors for all the value types.
+# Use at class-level.  Redefined in variant.hh.
+m4_define([b4_symbol_constructor_declare], [])
+m4_define([b4_symbol_constructor_define], [])
+
+
+# b4_yytranslate_define
+# ---------------------
+# Define yytranslate_.  Sometimes used in the header file,
+# sometimes in the cc file.
+m4_define([b4_yytranslate_define],
+[[  // Symbol number corresponding to token number t.
+  inline
+  ]b4_parser_class_name[::token_number_type
+  ]b4_parser_class_name[::yytranslate_ (]b4_token_ctor_if([token_type],
+                                                          [int])[ t)
+  {
+    static
+    const token_number_type
+    translate_table[] =
+    {
+]b4_translate[
+    };
+    const unsigned int user_token_number_max_ = ]b4_user_token_number_max[;
+    const token_number_type undef_token_ = ]b4_undef_token_number[;
+
+    if (static_cast<int>(t) <= yyeof_)
+      return yyeof_;
+    else if (static_cast<unsigned int> (t) <= user_token_number_max_)
+      return translate_table[t];
+    else
+      return undef_token_;
+  }
+]])
+
+
 # b4_lhs_value([TYPE])
 # --------------------
 # 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])
@@ -116,7 +437,8 @@ m4_define([b4_lhs_value],
 # Expansion of $<TYPE>NUM, where the current rule has RULE-LENGTH
 # symbols on RHS.
 m4_define([b4_rhs_value],
-[(yysemantic_stack_@{($1) - ($2)@}m4_ifval([$3], [.$3]))])
+[b4_symbol_value([yysemantic_stack_@{($1) - ($2)@}], [$3])])
+
 
 # b4_lhs_location()
 # -----------------
@@ -153,27 +475,27 @@ m4_define([b4_parse_param_decl_1],
 # Extra initialisations of the constructor.
 m4_define([b4_parse_param_cons],
           [m4_ifset([b4_parse_param],
-                   [
+                    [
       b4_cc_constructor_calls(b4_parse_param)])])
 m4_define([b4_cc_constructor_calls],
-         [m4_map_sep([b4_cc_constructor_call], [,
+          [m4_map_sep([b4_cc_constructor_call], [,
       ], [$@])])
 m4_define([b4_cc_constructor_call],
-         [$2 ($2_yyarg)])
+          [$2 ($2_yyarg)])
 
 # b4_parse_param_vars
 # -------------------
 # Extra instance variables.
 m4_define([b4_parse_param_vars],
           [m4_ifset([b4_parse_param],
-                   [
-    /* User arguments.  */
+                    [
+    // User arguments.
 b4_cc_var_decls(b4_parse_param)])])
 m4_define([b4_cc_var_decls],
-         [m4_map_sep([b4_cc_var_decl], [
+          [m4_map_sep([b4_cc_var_decl], [
 ], [$@])])
 m4_define([b4_cc_var_decl],
-         [    $1;])
+          [    $1;])
 
 
 ## ---------##
@@ -203,3 +525,13 @@ m4_define([b4_yylloc_default_define],
     while (/*CONSTCOND*/ false)
 # endif
 ]])
+
+## -------- ##
+## Checks.  ##
+## -------- ##
+
+b4_token_ctor_if([b4_variant_if([],
+  [b4_fatal_at(b4_percent_define_get_loc(api.token.constructor),
+               [cannot use '%s' without '%s'],
+               [%define api.token.constructor],
+               [%define api.value.type variant]))])])
index 4ee310da56dc883a10abb576f20ce054a914c14b..eb06de2a4dcf451cfa6c3be8066d21c4631408d0 100644 (file)
 # 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_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(m4_expand([[$1]]), [
+\(.\)], [
+$3\1])$4])
+
+
+# b4_comment(TEXT, [PREFIX])
+# --------------------------
+# Put TEXT in comment.  Prefix all the output lines with PREFIX.
+m4_define([b4_comment],
+[b4_comment_([$1], [$2/* ], [$2   ], [  */])])
+
+
+
+
 # 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_],
-[m4_if([$2], [[]],
-       [m4_ifval([$3], [($1.$3)],
-                 [$1])],
-       [($1.$2)])])
+[b4_symbol_value([$1],
+                 m4_if([$2], [[]],
+                       [[$3]], [[$2]]))])
 
 # b4_dollar_pushdef(VALUE-POINTER, DEFAULT-FIELD, LOCATION)
 # b4_dollar_popdef
index b1b6e2895937d19b8521030e4eff2d37d140f6e9..abc769b9c3adfa1483e566ecca61d6d1d19577cc 100644 (file)
--- a/data/c.m4
+++ b/data/c.m4
@@ -51,12 +51,6 @@ m4_define([b4_cpp_guard_close],
 ## Identification.  ##
 ## ---------------- ##
 
-# b4_comment(TEXT)
-# ----------------
-m4_define([b4_comment], [/* m4_bpatsubst([$1], [
-], [
-   ])  */])
-
 # b4_identification
 # -----------------
 # Depends on individual skeletons to define b4_pure_flag, b4_push_flag, or
@@ -110,10 +104,27 @@ m4_define_default([b4_union_name], [b4_api_PREFIX[]STYPE])
 ## Pure/impure interfaces.  ##
 ## ------------------------ ##
 
+# b4_lex_formals
+# --------------
+# All the yylex formal arguments.
+# b4_lex_param arrives quoted twice, but we want to keep only one level.
+m4_define([b4_lex_formals],
+[b4_pure_if([[[[YYSTYPE *yylvalp]], [[&yylval]]][]dnl
+b4_locations_if([, [[YYLTYPE *yyllocp], [&yylloc]]])])dnl
+m4_ifdef([b4_lex_param], [, ]b4_lex_param)])
+
+
+# b4_lex
+# ------
+# Call yylex.
+m4_define([b4_lex],
+[b4_function_call([yylex], [int], b4_lex_formals)])
+
+
 # b4_user_args
 # ------------
 m4_define([b4_user_args],
-[m4_ifset([b4_parse_param], [, b4_c_args(b4_parse_param)])])
+[m4_ifset([b4_parse_param], [, b4_args(b4_parse_param)])])
 
 
 # b4_parse_param
@@ -137,11 +148,13 @@ m4_popdef([$2])dnl
 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
 ])
 
@@ -169,7 +182,7 @@ m4_define([b4_int_type],
 # b4_int_type_for(NAME)
 # ---------------------
 # Return the smallest int type able to handle numbers ranging from
-# `NAME_min' to `NAME_max' (included).
+# 'NAME_min' to 'NAME_max' (included).
 m4_define([b4_int_type_for],
 [b4_int_type($1_min, $1_max)])
 
@@ -178,12 +191,11 @@ m4_define([b4_int_type_for],
 # --------------------------------------------
 # Without inducing a comparison warning from the compiler, check if the
 # literal value LITERAL equals VALUE from table TABLE, which must have
-# TABLE_min and TABLE_max defined.  YYID must be defined as an identity
-# function that suppresses warnings about constant conditions.
+# TABLE_min and TABLE_max defined.
 m4_define([b4_table_value_equals],
 [m4_if(m4_eval($3 < m4_indir([b4_]$1[_min])
                || m4_indir([b4_]$1[_max]) < $3), [1],
-       [[YYID (0)]],
+       [[0]],
        [(!!(($2) == ($3)))])])
 
 
@@ -212,6 +224,11 @@ m4_define([b4_attribute_define],
 ])
 
 
+## ---------##
+## Values.  ##
+## ---------##
+
+
 # b4_null_define
 # --------------
 # Portability issues: define a YY_NULL appropriate for the current
@@ -232,191 +249,148 @@ 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>" whose contents is CONTENT.
+m4_define([b4_integral_parser_table_define],
+[m4_ifvaln([$3], [b4_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([[/* Token type.  */
 #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], [,
-],
-           [$@])[
-   };
+  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.  ##
+## ----------------- ##
 
-## --------------------------------------------- ##
-## Defining C functions in both K&R and ANSI-C.  ##
-## --------------------------------------------- ##
 
+# 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]))])
 
-# b4_modern_c
-# -----------
-# A predicate useful in #if to determine whether C is ancient or modern.
-#
-# If __STDC__ is defined, the compiler is modern.  IBM xlc 7.0 when run
-# as 'cc' doesn't define __STDC__ (or __STDC_VERSION__) for pedantic
-# reasons, but it defines __C99__FUNC__ so check that as well.
-# Microsoft C normally doesn't define these macros, but it defines _MSC_VER.
-# Consider a C++ compiler to be modern if it defines __cplusplus.
-#
-m4_define([b4_c_modern],
-  [[(defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)]])
 
-# b4_c_function_def(NAME, RETURN-VALUE, [DECL1, NAME1], ...)
-# ----------------------------------------------------------
-# Declare the function NAME.
-m4_define([b4_c_function_def],
-[#if b4_c_modern
-b4_c_ansi_function_def($@)
-#else
-$2
-$1 (b4_c_knr_formal_names(m4_shift2($@)))
-b4_c_knr_formal_decls(m4_shift2($@))
-#endif[]dnl
-])
 
+## ---------------------- ##
+## Defining C functions.  ##
+## ---------------------- ##
 
-# b4_c_ansi_function_def(NAME, RETURN-VALUE, [DECL1, NAME1], ...)
-# ---------------------------------------------------------------
-# Declare the function NAME in ANSI.
-m4_define([b4_c_ansi_function_def],
+
+# b4_function_define(NAME, RETURN-VALUE, [DECL1, NAME1], ...)
+# -----------------------------------------------------------
+# Declare the function NAME in C.
+m4_define([b4_function_define],
 [$2
-$1 (b4_c_ansi_formals(m4_shift2($@)))[]dnl
+$1 (b4_formals(m4_shift2($@)))[]dnl
 ])
 
 
-# b4_c_ansi_formals([DECL1, NAME1], ...)
-# --------------------------------------
-# Output the arguments ANSI-C definition.
-m4_define([b4_c_ansi_formals],
+# b4_formals([DECL1, NAME1], ...)
+# -------------------------------
+# The formal arguments of a C function definition.
+m4_define([b4_formals],
 [m4_if([$#], [0], [void],
        [$#$1], [1], [void],
-               [m4_map_sep([b4_c_ansi_formal], [, ], [$@])])])
+               [m4_map_sep([b4_formal], [, ], [$@])])])
 
-m4_define([b4_c_ansi_formal],
+m4_define([b4_formal],
 [$1])
 
 
-# b4_c_knr_formal_names([DECL1, NAME1], ...)
-# ------------------------------------------
-# Output the argument names.
-m4_define([b4_c_knr_formal_names],
-[m4_map_sep([b4_c_knr_formal_name], [, ], [$@])])
-
-m4_define([b4_c_knr_formal_name],
-[$2])
 
+## ----------------------- ##
+## Declaring C functions.  ##
+## ----------------------- ##
 
-# b4_c_knr_formal_decls([DECL1, NAME1], ...)
-# ------------------------------------------
-# 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;])
-
-
-
-## ------------------------------------------------------------ ##
-## Declaring (prototyping) C functions in both K&R and ANSI-C.  ##
-## ------------------------------------------------------------ ##
-
-
-# b4_c_ansi_function_decl(NAME, RETURN-VALUE, [DECL1, NAME1], ...)
-# ----------------------------------------------------------------
-# Declare the function NAME ANSI C style.
-m4_define([b4_c_ansi_function_decl],
-[$2 $1 (b4_c_ansi_formals(m4_shift2($@)));[]dnl
+# b4_function_declare(NAME, RETURN-VALUE, [DECL1, NAME1], ...)
+# ------------------------------------------------------------
+# Declare the function NAME.
+m4_define([b4_function_declare],
+[$2 $1 (b4_formals(m4_shift2($@)));[]dnl
 ])
 
 
 
-# b4_c_function_decl(NAME, RETURN-VALUE, [DECL1, NAME1], ...)
-# -----------------------------------------------------------
-# Declare the function NAME in both K&R and ANSI C.
-m4_define([b4_c_function_decl],
-[#if defined __STDC__ || defined __cplusplus
-b4_c_ansi_function_decl($@)
-#else
-$2 $1 ();
-#endif[]dnl
-])
-
-
 
 ## --------------------- ##
 ## Calling C functions.  ##
 ## --------------------- ##
 
 
-# b4_c_function_call(NAME, RETURN-VALUE, [DECL1, NAME1], ...)
+# b4_function_call(NAME, RETURN-VALUE, [DECL1, NAME1], ...)
 # -----------------------------------------------------------
 # Call the function NAME with arguments NAME1, NAME2 etc.
-m4_define([b4_c_function_call],
-[$1 (b4_c_args(m4_shift2($@)))[]dnl
+m4_define([b4_function_call],
+[$1 (b4_args(m4_shift2($@)))[]dnl
 ])
 
 
-# b4_c_args([DECL1, NAME1], ...)
-# ------------------------------
+# b4_args([DECL1, NAME1], ...)
+# ----------------------------
 # Output the arguments NAME1, NAME2...
-m4_define([b4_c_args],
-[m4_map_sep([b4_c_arg], [, ], [$@])])
+m4_define([b4_args],
+[m4_map_sep([b4_arg], [, ], [$@])])
 
-m4_define([b4_c_arg],
+m4_define([b4_arg],
 [$2])
 
 
@@ -438,53 +412,28 @@ m4_define([b4_sync_start], [[#]line $1 $2])
 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_symbol_actions(KIND)
-# -----------------------
-# Emit the symbol actions for KIND ("printers" or "destructors").
-# Dispatch on "yytype".
-m4_define([b4_symbol_actions],
-[m4_ifval(m4_defn([b4_symbol_$1]),
-[[switch (yytype)
-    {
-]m4_map([_b4_symbol_actions], m4_defn([b4_symbol_$1]))[
-      default:
-        break;
-    }]],
-[YYUSE (yytype);])])
-
-
-# b4_yydestruct_generate(FUNCTION-DECLARATOR)
-# -------------------------------------------
-# Generate the "yydestruct" function, which declaration is issued using
-# FUNCTION-DECLARATOR, which may be "b4_c_ansi_function_def" for ISO C
-# or "b4_c_function_def" for K&R.
-m4_define_default([b4_yydestruct_generate],
+
+# b4_yydestruct_define
+# --------------------
+# Define the "yydestruct" function.
+m4_define_default([b4_yydestruct_define],
 [[/*-----------------------------------------------.
 | Release the memory associated to this symbol.  |
 `-----------------------------------------------*/
 
-/*ARGSUSED*/
-]$1([yydestruct],
+]b4_function_define([yydestruct],
     [static void],
     [[const char *yymsg],    [yymsg]],
     [[int yytype],           [yytype]],
@@ -492,33 +441,26 @@ m4_define_default([b4_yydestruct_generate],
 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);
 
-  ]b4_symbol_actions([destructors])[
+  ]b4_symbol_actions([destructor])[
 }]dnl
 ])
 
 
-# b4_yy_symbol_print_generate(FUNCTION-DECLARATOR)
-# ------------------------------------------------
-# Generate the "yy_symbol_print" function, which declaration is issued using
-# FUNCTION-DECLARATOR, which may be "b4_c_ansi_function_def" for ISO C
-# or "b4_c_function_def" for K&R.
-m4_define_default([b4_yy_symbol_print_generate],
+# b4_yy_symbol_print_define
+# -------------------------
+# Define the "yy_symbol_print" function.
+m4_define_default([b4_yy_symbol_print_define],
 [[
 /*--------------------------------.
 | Print this symbol on YYOUTPUT.  |
 `--------------------------------*/
 
-/*ARGSUSED*/
-]$1([yy_symbol_value_print],
+]b4_function_define([yy_symbol_value_print],
     [static void],
                [[FILE *yyoutput],                       [yyoutput]],
                [[int yytype],                           [yytype]],
@@ -527,19 +469,17 @@ 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
-  ]b4_symbol_actions([printers])[
+]])dnl
+  b4_symbol_actions([printer])[
 }
 
 
@@ -547,7 +487,7 @@ b4_parse_param_use[]dnl
 | Print this symbol on YYOUTPUT.  |
 `--------------------------------*/
 
-]$1([yy_symbol_print],
+]b4_function_define([yy_symbol_print],
     [static void],
                [[FILE *yyoutput],                       [yyoutput]],
                [[int yytype],                           [yytype]],
@@ -555,10 +495,8 @@ b4_parse_param_use[]dnl
 b4_locations_if([, [[YYLTYPE const * const yylocationp], [yylocationp]]])[]dnl
 m4_ifset([b4_parse_param], [, b4_parse_param]))[
 {
-  if (yytype < YYNTOKENS)
-    YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
-  else
-    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+  YYFPRINTF (yyoutput, "%s %s (",
+             yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
 
 ]b4_locations_if([  YY_LOCATION_PRINT (yyoutput, *yylocationp);
   YYFPRINTF (yyoutput, ": ");
@@ -569,63 +507,205 @@ b4_locations_if([, yylocationp])[]b4_user_args[);
 }]dnl
 ])
 
+
+## ---------------- ##
+## api.value.type.  ##
+## ---------------- ##
+
+
+# ---------------------- #
+# api.value.type=union.  #
+# ---------------------- #
+
+# b4_symbol_type_register(SYMBOL-NUM)
+# -----------------------------------
+# Symbol SYMBOL-NUM has a type (for variant) instead of a type-tag.
+# Extend the definition of %union's body with a field of that type,
+# and extend the symbol's "type" field to point to the field name,
+# instead of the type name.
+m4_define([b4_symbol_type_register],
+[m4_define([b4_symbol($1, type_tag)],
+           [b4_symbol_if([$1], [has_id],
+                         [b4_symbol([$1], [id])],
+                         [yytype_[]b4_symbol([$1], [number])])])dnl
+m4_append([b4_user_union_members],
+m4_expand([
+  b4_symbol_tag_comment([$1])dnl
+  b4_symbol([$1], [type]) b4_symbol([$1], [type_tag]);]))
+])
+
+
+# b4_type_define_tag(SYMBOL1-NUM, ...)
+# ------------------------------------
+# For the batch of symbols SYMBOL1-NUM... (which all have the same
+# type), enhance the %union definition for each of them, and set
+# there "type" field to the field tag name, instead of the type name.
+m4_define([b4_type_define_tag],
+[b4_symbol_if([$1], [has_type],
+              [m4_map([b4_symbol_type_register], [$@])])
+])
+
+
+# b4_symbol_value_union(VAL, [TYPE])
+# ----------------------------------
+# Same of b4_symbol_value, but when api.value.type=union.
+m4_define([b4_symbol_value_union],
+[m4_ifval([$2],
+          [(*($2*)(&$1))],
+          [$1])])
+])
+
+
+# b4_value_type_setup_union
+# -------------------------
+# Setup support for api.value.type=union.  Symbols are defined with a
+# type instead of a union member name: build the corresponding union,
+# and give the symbols their tag.
+m4_define([b4_value_type_setup_union],
+[m4_define([b4_union_members])
+b4_type_foreach([b4_type_define_tag])
+m4_copy_force([b4_symbol_value_union], [b4_symbol_value])
+])
+
+
+# ---------------- #
+# api.value.type.  #
+# ---------------- #
+
+
+# b4_value_type_setup_variant
+# ---------------------------
+# Setup support for api.value.type=variant.  By default, fail, specialized
+# by other skeletons.
+m4_define([b4_value_type_setup_variant],
+[b4_complain_at(b4_percent_define_get_loc([[api.value.type]]),
+                [['%s' does not support '%s']],
+                [b4_skeleton],
+                [%define api.value.type variant])])
+
+
+# _b4_value_type_setup_keyword
+# ----------------------------
+# api.value.type is defined with a keyword/string syntax.  Check if
+# that is properly defined, and prepare its use.
+m4_define([_b4_value_type_setup_keyword],
+[b4_percent_define_check_values([[[[api.value.type]],
+                                  [[none]],
+                                  [[union]],
+                                  [[union-directive]],
+                                  [[variant]],
+                                  [[yystype]]]])dnl
+m4_case(b4_percent_define_get([[api.value.type]]),
+        [union],   [b4_value_type_setup_union],
+        [variant], [b4_value_type_setup_variant])])
+
+
+# b4_value_type_setup
+# -------------------
+# Check if api.value.type is properly defined, and possibly prepare
+# its use.
+b4_define_silent([b4_value_type_setup],
+[# Define default value.
+b4_percent_define_ifdef([[api.value.type]], [],
+[# %union => api.value.type=union-directive
+m4_ifdef([b4_union_members],
+[m4_define([b4_percent_define_kind(api.value.type)], [keyword])
+m4_define([b4_percent_define(api.value.type)], [union-directive])],
+[# no tag seen => api.value.type={int}
+m4_if(b4_tag_seen_flag, 0,
+[m4_define([b4_percent_define_kind(api.value.type)], [code])
+m4_define([b4_percent_define(api.value.type)], [int])],
+[# otherwise api.value.type=yystype
+m4_define([b4_percent_define_kind(api.value.type)], [keyword])
+m4_define([b4_percent_define(api.value.type)], [yystype])])])])
+
+# Set up.
+m4_bmatch(b4_percent_define_get_kind([[api.value.type]]),
+   [keyword\|string], [_b4_value_type_setup_keyword])
+])
+
+
 ## -------------- ##
 ## Declarations.  ##
 ## -------------- ##
 
-# b4_declare_yylstype
-# -------------------
-# Declarations that might either go into the header (if --defines) or
-# in the parser body.  Declare YYSTYPE/YYLTYPE, and yylval/yylloc.
-m4_define([b4_declare_yylstype],
+
+# b4_value_type_define
+# --------------------
+m4_define([b4_value_type_define],
+[b4_value_type_setup[]dnl
+/* Value type.  */
+m4_bmatch(b4_percent_define_get_kind([[api.value.type]]),
+[code],
 [[#if ! defined ]b4_api_PREFIX[STYPE && ! defined ]b4_api_PREFIX[STYPE_IS_DECLARED
-]m4_ifdef([b4_stype],
-[[typedef union ]b4_union_name[
+typedef ]b4_percent_define_get([[api.value.type]])[ ]b4_api_PREFIX[STYPE;
+# define ]b4_api_PREFIX[STYPE_IS_TRIVIAL 1
+# define ]b4_api_PREFIX[STYPE_IS_DECLARED 1
+#endif
+]],
+[m4_bmatch(b4_percent_define_get([[api.value.type]]),
+[union\|union-directive],
+[[#if ! defined ]b4_api_PREFIX[STYPE && ! defined ]b4_api_PREFIX[STYPE_IS_DECLARED
+typedef union ]b4_union_name[ ]b4_api_PREFIX[STYPE;
+union ]b4_union_name[
 {
-]b4_user_stype[
-} ]b4_api_PREFIX[STYPE;
-# define ]b4_api_PREFIX[STYPE_IS_TRIVIAL 1]],
-[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 */
+]b4_user_union_members[
+};
+# define ]b4_api_PREFIX[STYPE_IS_TRIVIAL 1
 # define ]b4_api_PREFIX[STYPE_IS_DECLARED 1
-#endif]b4_locations_if([[
+#endif
+]])])])
+
 
+# b4_location_type_define
+# -----------------------
+m4_define([b4_location_type_define],
+[[/* Location type.  */
 #if ! defined ]b4_api_PREFIX[LTYPE && ! defined ]b4_api_PREFIX[LTYPE_IS_DECLARED
-typedef struct ]b4_api_PREFIX[LTYPE
+typedef struct ]b4_api_PREFIX[LTYPE ]b4_api_PREFIX[LTYPE;
+struct ]b4_api_PREFIX[LTYPE
 {
   int first_line;
   int first_column;
   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]])
+#endif
+]])
+
+
+# b4_declare_yylstype
+# -------------------
+# Declarations that might either go into the header (if --defines) or
+# in the parser body.  Declare YYSTYPE/YYLTYPE, and yylval/yylloc.
+m4_define([b4_declare_yylstype],
+[b4_value_type_define[]b4_locations_if([
+b4_location_type_define])
 
 b4_pure_if([], [[extern ]b4_api_PREFIX[STYPE ]b4_prefix[lval;
 ]b4_locations_if([[extern ]b4_api_PREFIX[LTYPE ]b4_prefix[lloc;]])])[]dnl
 ])
 
+
 # b4_YYDEBUG_define
-# ------------------
+# -----------------
 m4_define([b4_YYDEBUG_define],
-[[/* Enabling traces.  */
+[[/* Debug 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 YYDEBUG */
 #endif  /* ! defined ]b4_api_PREFIX[DEBUG */]])[]dnl
 ])
@@ -650,7 +730,7 @@ m4_define([b4_yylloc_default_define],
 #ifndef YYLLOC_DEFAULT
 # define YYLLOC_DEFAULT(Current, Rhs, N)                                \
     do                                                                  \
-      if (YYID (N))                                                     \
+      if (N)                                                            \
         {                                                               \
           (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;        \
           (Current).first_column = YYRHSLOC (Rhs, 1).first_column;      \
@@ -664,7 +744,7 @@ m4_define([b4_yylloc_default_define],
           (Current).first_column = (Current).last_column =              \
             YYRHSLOC (Rhs, 0).last_column;                              \
         }                                                               \
-    while (YYID (0))
+    while (0)
 #endif
 ]])
 
@@ -683,7 +763,7 @@ m4_define([b4_yy_location_print_define],
 /* Print *YYLOCP on YYO.  Private, do not rely on its existence. */
 
 __attribute__((__unused__))
-]b4_c_function_def([yy_location_print_],
+]b4_function_define([yy_location_print_],
     [static unsigned],
                [[FILE *yyo],                    [yyo]],
                [[YYLTYPE const * const yylocp], [yylocp]])[
@@ -692,20 +772,20 @@ __attribute__((__unused__))
   int end_col = 0 != yylocp->last_column ? yylocp->last_column - 1 : 0;
   if (0 <= yylocp->first_line)
     {
-      res += fprintf (yyo, "%d", yylocp->first_line);
+      res += YYFPRINTF (yyo, "%d", yylocp->first_line);
       if (0 <= yylocp->first_column)
-        res += fprintf (yyo, ".%d", yylocp->first_column);
+        res += YYFPRINTF (yyo, ".%d", yylocp->first_column);
     }
   if (0 <= yylocp->last_line)
     {
       if (yylocp->first_line < yylocp->last_line)
         {
-          res += fprintf (yyo, "-%d", yylocp->last_line);
+          res += YYFPRINTF (yyo, "-%d", yylocp->last_line);
           if (0 <= end_col)
-            res += fprintf (yyo, ".%d", end_col);
+            res += YYFPRINTF (yyo, ".%d", end_col);
         }
       else if (0 <= end_col && yylocp->first_column < end_col)
-        res += fprintf (yyo, "-%d", end_col);
+        res += YYFPRINTF (yyo, "-%d", end_col);
     }
   return res;
  }
index 1a2e6ba68729beaf1517c86ce1c0e35eab8408da..ff70890f334f6b739e94d09d82004ae438ee099f 100644 (file)
@@ -52,17 +52,7 @@ m4_ifndef([b4_pure_flag],
 # This is not shared with yacc.c in c.m4 because  GLR relies on ISO C
 # formal argument declarations.
 m4_define([b4_user_formals],
-[m4_ifset([b4_parse_param], [, b4_c_ansi_formals(b4_parse_param)])])
-
-
-# b4_lex_param
-# ------------
-# Accumule in b4_lex_param all the yylex arguments.
-# Yes, this is quite ugly...
-m4_define([b4_lex_param],
-m4_dquote(b4_pure_if([[[[YYSTYPE *]], [[&yylval]]][]dnl
-b4_locations_if([, [[YYLTYPE *], [&yylloc]]])])dnl
-m4_ifdef([b4_lex_param], [, ]b4_lex_param)))
+[m4_ifset([b4_parse_param], [, b4_formals(b4_parse_param)])])
 
 
 # b4_yyerror_args
@@ -71,7 +61,7 @@ m4_ifdef([b4_lex_param], [, ]b4_lex_param)))
 # a trailing comma.
 m4_define([b4_yyerror_args],
 [b4_pure_if([b4_locations_if([yylocp, ])])dnl
-m4_ifset([b4_parse_param], [b4_c_args(b4_parse_param), ])])
+m4_ifset([b4_parse_param], [b4_args(b4_parse_param), ])])
 
 
 # b4_lyyerror_args
@@ -79,7 +69,7 @@ m4_ifset([b4_parse_param], [b4_c_args(b4_parse_param), ])])
 # Same as above, but on the lookahead, hence &yylloc instead of yylocp.
 m4_define([b4_lyyerror_args],
 [b4_pure_if([b4_locations_if([&yylloc, ])])dnl
-m4_ifset([b4_parse_param], [b4_c_args(b4_parse_param), ])])
+m4_ifset([b4_parse_param], [b4_args(b4_parse_param), ])])
 
 
 # b4_pure_args
@@ -126,7 +116,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])
@@ -134,7 +132,7 @@ m4_define([b4_lhs_value],
 # 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])])
 
 
 
@@ -154,7 +152,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)])
 
 
 ## -------------- ##
@@ -164,16 +162,17 @@ m4_define([b4_rhs_location],
 # b4_shared_declarations
 # ----------------------
 # Declaration that might either go into the header (if --defines)
-# or open coded in the parser body.
-m4_define([b4_shared_declarations],
+# or open coded in the parser body.  glr.cc has its own definition.
+m4_if(b4_skeleton, ["glr.c"],
+[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_function_declare(b4_prefix[parse], [int], b4_parse_param)[
 ]b4_percent_code_get([[provides]])[]dnl
 ])
-
+])
 
 ## -------------- ##
 ## Output files.  ##
@@ -197,13 +196,14 @@ b4_percent_code_get([[top]])[
 #define yyparse ]b4_prefix[parse
 #define yylex   ]b4_prefix[lex
 #define yyerror ]b4_prefix[error
+#define yydebug ]b4_prefix[debug
+]]b4_pure_if([], [[
 #define yylval  ]b4_prefix[lval
 #define yychar  ]b4_prefix[char
-#define yydebug ]b4_prefix[debug
 #define yynerrs ]b4_prefix[nerrs]b4_locations_if([[
-#define yylloc  ]b4_prefix[lloc]])])[
+#define yylloc  ]b4_prefix[lloc]])]))[
 
-/* Copy the first part of user declarations.  */
+/* First part of user declarations.  */
 ]b4_user_pre_prologue[
 
 ]b4_null_define[
@@ -216,7 +216,7 @@ b4_percent_code_get([[top]])[
 # 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
@@ -246,16 +246,6 @@ b4_percent_code_get[]dnl
 # endif
 #endif
 
-/* Identity function, used to suppress warnings about constant conditions.  */
-#ifndef lint
-# define YYID(N) (N)
-#else
-]b4_c_function_def([YYID], [static int], [[int i], [i]])[
-{
-  return i;
-}
-#endif
-
 #ifndef YYFREE
 # define YYFREE free
 #endif
@@ -323,19 +313,6 @@ static const ]b4_int_type_for([b4_translate])[ yytranslate[] =
 };
 
 #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[] =
 {
@@ -352,17 +329,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[] =
@@ -376,41 +346,11 @@ static const ]b4_int_type_for([b4_merger])[ yymerger[] =
   ]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[] =
-{
-  ]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[] =
+/* YYIMMEDIATE[RULE-NUM] -- True iff rule #RULE-NUM is not to be deferred, as
+   in the case of predicates.  */
+static const yybool yyimmediate[] =
 {
-  ]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
@@ -425,25 +365,13 @@ static const ]b4_int_type_for([b4_conflict_list_heads])[ yyconflp[] =
 /* YYCONFL[I] -- lists of conflicting rule numbers, each terminated by
    0, pointed into by YYCONFLP.  */
 ]dnl Do not use b4_int_type_for here, since there are places where
-dnl pointers onto yyconfl are taken, which type is "short int *".
+dnl pointers onto yyconfl are taken, whose type is "short int *".
 dnl We probably ought to introduce a type for confl.
 [static const short int yyconfl[] =
 {
   ]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[
-};
-
 /* Error token number */
 #define YYTERROR 1
 
@@ -451,10 +379,6 @@ static const ]b4_int_type_for([b4_stos])[ yystos[] =
 ]b4_yylloc_default_define[
 # define YYRHSLOC(Rhs, K) ((Rhs)[K].yystate.yyloc)
 ]])[
-]b4_yy_location_print_define[
-
-/* YYLEX -- calling `yylex' with the right arguments.  */
-#define YYLEX ]b4_c_function_call([yylex], [int], b4_lex_param)[
 
 ]b4_pure_if(
 [
@@ -482,9 +406,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 (0)
 
 #if ]b4_api_PREFIX[DEBUG
 
@@ -492,28 +419,36 @@ typedef enum { yyok, yyaccept, yyabort, yyerr } YYRESULTTAG;
 #  define YYFPRINTF fprintf
 # endif
 
+]b4_yy_location_print_define[
+
 # define YYDPRINTF(Args)                        \
-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))
+  do {                                          \
+    if (yydebug)                                \
+      YYFPRINTF Args;                           \
+  } while (0)
+
+]b4_yy_symbol_print_define[
+
+# 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 (0)
 
 /* Nonzero means print parse trace.  It is left uninitialized so that
    multiple parsers can coexist.  */
 int yydebug;
 
+struct yyGLRStack;
+static void yypstack (struct yyGLRStack* yystackp, size_t yyk)
+  __attribute__ ((__unused__));
+static void yypdumpstack (struct yyGLRStack* yystackp)
+  __attribute__ ((__unused__));
+
 #else /* !]b4_api_PREFIX[DEBUG */
 
 # define YYDPRINTF(Args)
@@ -545,13 +480,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
@@ -559,13 +488,13 @@ int yydebug;
   do {                                                  \
     if (Yystack->yyspaceLeft < YYHEADROOM)              \
       yyexpandGLRStack (Yystack);                       \
-  } while (YYID (0))
+  } while (0)
 #else
 # define YY_RESERVE_GLRSTACK(Yystack)                   \
   do {                                                  \
     if (Yystack->yyspaceLeft < YYHEADROOM)              \
       yyMemoryExhausted (Yystack);                      \
-  } while (YYID (0))
+  } while (0)
 #endif
 
 
@@ -648,7 +577,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;
@@ -669,7 +598,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
@@ -781,9 +710,16 @@ yyfillin (yyGLRStackItem *yyvsp, int yylow0, int yylow1)
   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;
     }
@@ -810,16 +746,17 @@ yyfill (yyGLRStackItem *yyvsp, int *yylow, int yylow1, yybool yynormal)
  *  value ($$), and yylocp points to place for location information
  *  (@@$).  Returns yyok for normal return, yyaccept for YYACCEPT,
  *  yyerr for YYERROR, yyabort for YYABORT.  */
-/*ARGSUSED*/ static YYRESULTTAG
-yyuserAction (yyRuleNum yyn, int yyrhslen, yyGLRStackItem* yyvsp,
+static YYRESULTTAG
+yyuserAction (yyRuleNum yyn, size_t yyrhslen, yyGLRStackItem* yyvsp,
               yyGLRStack* yystackp,
               YYSTYPE* yyvalp]b4_locuser_formals[)
 {
   yybool yynormal __attribute__ ((__unused__)) =
     (yystackp->yysplitPoint == YY_NULL);
   int yylow;
-]b4_parse_param_use[]dnl
-[# undef yyerrok
+]b4_parse_param_use([yyvalp], [yylocp])dnl
+[  YYUSE (yyrhslen);
+# undef yyerrok
 # define yyerrok (yystackp->yyerrState = 0)
 # undef YYACCEPT
 # define YYACCEPT return yyaccept
@@ -861,9 +798,9 @@ yyuserAction (yyRuleNum yyn, int yyrhslen, yyGLRStackItem* yyvsp,
 # undef yyclearin
 # undef YYRECOVERING
 }
-\f
 
-/*ARGSUSED*/ static void
+
+static void
 yyuserMerge (int yyn, YYSTYPE* yy0, YYSTYPE* yy1)
 {
   YYUSE (yy0);
@@ -871,14 +808,14 @@ yyuserMerge (int yyn, YYSTYPE* yy0, YYSTYPE* yy1)
 
   switch (yyn)
     {
-      ]b4_mergers[
+]b4_mergers[
       default: break;
     }
 }
 
                               /* Bison grammar-table manipulation.  */
 
-]b4_yydestruct_generate([b4_c_ansi_function_def])[
+]b4_yydestruct_define[
 
 /** Number of symbols composing the right hand side of rule #RULE.  */
 static inline int
@@ -921,7 +858,7 @@ yydestroyGLRState (char const *yymsg, yyGLRState *yys]b4_user_formals[)
     }
 }
 
-/** Left-hand-side symbol for rule #RULE.  */
+/** Left-hand-side symbol for rule #YYRULE.  */
 static inline yySymbol
 yylhsNonterm (yyRuleNum yyrule)
 {
@@ -931,7 +868,7 @@ 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)
@@ -939,7 +876,7 @@ 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)
 {
@@ -954,8 +891,8 @@ 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,
@@ -983,8 +920,7 @@ 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
@@ -1005,9 +941,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)
@@ -1020,16 +957,16 @@ 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])
     {
@@ -1047,7 +984,7 @@ yyaddDeferredAction (yyGLRStack* yystackp, size_t yyk, yyGLRState* yystate,
 
                                 /* 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)
 {
@@ -1073,8 +1010,8 @@ static void yyfreeStateSet (yyGLRStateSet* yyset)
   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)
 {
@@ -1096,7 +1033,7 @@ 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
@@ -1166,9 +1103,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)
 {
@@ -1176,7 +1113,7 @@ 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)
 {
@@ -1185,8 +1122,8 @@ 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)
@@ -1235,8 +1172,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,
@@ -1255,12 +1193,12 @@ yyglrShift (yyGLRStack* yystackp, size_t yyk, yyStateNum yylrState,
   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;
 
@@ -1272,14 +1210,55 @@ yyglrShiftDefer (yyGLRStack* yystackp, size_t yyk, yyStateNum yylrState,
   yystackp->yytops.yystates[yyk] = yynewState;
 
   /* Invokes YY_RESERVE_GLRSTACK.  */
-  yyaddDeferredAction (yystackp, yyk, yynewState, rhs, yyrule);
+  yyaddDeferredAction (yystackp, yyk, yynewState, yyrhs, yyrule);
 }
 
-/** Pop the symbols consumed by reduction #RULE from the top of stack
- *  #K of STACK, and perform the appropriate semantic action on their
+#if !]b4_api_PREFIX[DEBUG
+# define YY_REDUCE_PRINT(Args)
+#else
+# define YY_REDUCE_PRINT(Args)          \
+do {                                    \
+  if (yydebug)                          \
+    yy_reduce_print Args;               \
+} while (0)
+
+/*----------------------------------------------------------------------.
+| Report that stack #YYK of *YYSTACKP is going to be reduced by YYRULE. |
+`----------------------------------------------------------------------*/
+
+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 #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,
@@ -1290,20 +1269,17 @@ 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];
@@ -1319,62 +1295,21 @@ yydoAction (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
         }
       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
@@ -1385,11 +1320,18 @@ yyglrReduce (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
 
   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,
@@ -1412,7 +1354,8 @@ yyglrReduce (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
       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 +1426,7 @@ yysplitStack (yyGLRStack* yystackp, size_t yyk)
   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 +1448,8 @@ yyidenticalOptions (yySemanticOption* yyy0, yySemanticOption* yyy1)
     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)
 {
@@ -1533,7 +1476,7 @@ yymergeOptionSets (yySemanticOption* yyy0, yySemanticOption* yyy1)
         {
           yySemanticOption** yyz0p = &yys0->yysemantics.yyfirstVal;
           yySemanticOption* yyz1 = yys1->yysemantics.yyfirstVal;
-          while (YYID (yytrue))
+          while (yytrue)
             {
               if (yyz1 == *yyz0p || yyz1 == YY_NULL)
                 break;
@@ -1585,11 +1528,11 @@ static YYRESULTTAG yyresolveValue (yyGLRState* yys,
                                    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[)
@@ -1604,9 +1547,10 @@ yyresolveStates (yyGLRState* yys, int yyn,
   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,
@@ -1680,11 +1624,11 @@ yyreportTree (yySemanticOption* yyx, int yyindent)
         {
           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
@@ -1693,7 +1637,7 @@ yyreportTree (yySemanticOption* yyx, int yyindent)
 }
 #endif
 
-/*ARGSUSED*/ static YYRESULTTAG
+static YYRESULTTAG
 yyreportAmbiguity (yySemanticOption* yyx0,
                    yySemanticOption* yyx1]b4_pure_formals[)
 {
@@ -1713,9 +1657,9 @@ yyreportAmbiguity (yySemanticOption* yyx0,
   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[)
@@ -1769,11 +1713,12 @@ yyresolveLocations (yyGLRState* yys1, int yyn1,
     }
 }]])[
 
-/** Resolve the ambiguity represented in state S, perform the indicated
- *  actions, and set the semantic value of S.  If result != yyok, the chain of
- *  semantic options in S has been cleared instead or it has been left
- *  unmodified except that redundant options may have been removed.  Regardless
- *  of whether result = yyok, S has been left with consistent data so that
+/** Resolve the ambiguity represented in state YYS in *YYSTACKP,
+ *  perform the indicated actions, and set the semantic value of YYS.
+ *  If result != yyok, the chain of semantic options in YYS has been
+ *  cleared instead or it has been left unmodified except that
+ *  redundant options may have been removed.  Regardless of whether
+ *  result = yyok, YYS has been left with consistent data so that
  *  yydestroyGLRState can be invoked if necessary.  */
 static YYRESULTTAG
 yyresolveValue (yyGLRState* yys, yyGLRStack* yystackp]b4_user_formals[)
@@ -1911,10 +1856,6 @@ static YYRESULTTAG
 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;
@@ -1925,7 +1866,8 @@ yyprocessOneStack (yyGLRStack* yystackp, size_t yyk,
 
       if (yyisDefaultedState (yystate))
         {
-          yyrule = yydefaultAction (yystate);
+          YYRESULTTAG yyflag;
+          yyRuleNum yyrule = yydefaultAction (yystate);
           if (yyrule == 0)
             {
               YYDPRINTF ((stderr, "Stack %lu dies.\n",
@@ -1933,16 +1875,30 @@ yyprocessOneStack (yyGLRStack* yystackp, size_t yyk,
               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)
             {
               YYDPRINTF ((stderr, "Reading a token: "));
-              yychar = YYLEX;
+              yychar = ]b4_lex[;
             }
 
           if (yychar <= YYEOF)
@@ -1960,14 +1916,25 @@ yyprocessOneStack (yyGLRStack* yystackp, size_t yyk,
 
           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;
             }
 
@@ -1981,14 +1948,27 @@ yyprocessOneStack (yyGLRStack* yystackp, size_t yyk,
               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;
 }
 
-/*ARGSUSED*/ static void
+static void
 yyreportSyntaxError (yyGLRStack* yystackp]b4_user_formals[)
 {
   if (yystackp->yyerrState != 0)
@@ -2125,7 +2105,7 @@ yyreportSyntaxError (yyGLRStack* yystackp]b4_user_formals[)
 /* Recover from a syntax error on *YYSTACKP, assuming that *YYSTACKP->YYTOKENP,
    yylval, and yylloc are the syntactic category, semantic value, and location
    of the lookahead.  */
-/*ARGSUSED*/ static void
+static void
 yyrecoverSyntaxError (yyGLRStack* yystackp]b4_user_formals[)
 {
   size_t yyk;
@@ -2134,7 +2114,7 @@ yyrecoverSyntaxError (yyGLRStack* yystackp]b4_user_formals[)
   if (yystackp->yyerrState == 3)
     /* We just shifted the error token and (perhaps) took some
        reductions.  Skip tokens until we can proceed.  */
-    while (YYID (yytrue))
+    while (yytrue)
       {
         yySymbol yytoken;
         if (yychar == YYEOF)
@@ -2153,7 +2133,7 @@ yyrecoverSyntaxError (yyGLRStack* yystackp]b4_user_formals[)
                         yytoken, &yylval]b4_locuser_args([&yylloc])[);
           }
         YYDPRINTF ((stderr, "Reading a token: "));
-        yychar = YYLEX;
+        yychar = ]b4_lex[;
         if (yychar <= YYEOF)
           {
             yychar = yytoken = YYEOF;
@@ -2238,14 +2218,13 @@ yyrecoverSyntaxError (yyGLRStack* yystackp]b4_user_formals[)
     default:                                                                 \
       goto yybuglab;                                                         \
     }                                                                        \
-  } while (YYID (0))
-
+  } while (0)
 
 /*----------.
 | yyparse.  |
 `----------*/
 
-]b4_c_ansi_function_def([yyparse], [int], b4_parse_param)[
+]b4_function_define([yyparse], [int], b4_parse_param)[
 {
   int yyresult;
   yyGLRStack yystack;
@@ -2259,8 +2238,8 @@ yyrecoverSyntaxError (yyGLRStack* yystackp]b4_user_formals[)
   yylloc = yyloc_default;])[
 ]m4_ifdef([b4_initial_action], [
 b4_dollar_pushdef([yylval], [], [yylloc])dnl
-/* User initialization code.  */
-b4_user_initial_action
+  /* User initialization code.  */
+  b4_user_initial_action
 b4_dollar_popdef])[]dnl
 [
   if (! yyinitGLRStack (yystackp, YYINITDEPTH))
@@ -2275,13 +2254,13 @@ b4_dollar_popdef])[]dnl
   yyglrShift (&yystack, 0, 0, 0, &yylval]b4_locations_if([, &yylloc])[);
   yyposn = 0;
 
-  while (YYID (yytrue))
+  while (yytrue)
     {
       /* For efficiency, we have two loops, the first of which is
          specialized to deterministic operation (single stack, no
          potential ambiguity).  */
       /* Standard mode */
-      while (YYID (yytrue))
+      while (yytrue)
         {
           yyRuleNum yyrule;
           int yyaction;
@@ -2308,7 +2287,7 @@ b4_dollar_popdef])[]dnl
               if (yychar == YYEMPTY)
                 {
                   YYDPRINTF ((stderr, "Reading a token: "));
-                  yychar = YYLEX;
+                  yychar = ]b4_lex[;
                 }
 
               if (yychar <= YYEOF)
@@ -2345,7 +2324,7 @@ b4_dollar_popdef])[]dnl
             }
         }
 
-      while (YYID (yytrue))
+      while (yytrue)
         {
           yySymbol yytoken_to_shift;
           size_t yys;
@@ -2477,16 +2456,11 @@ b4_dollar_popdef])[]dnl
       yyfreeGLRStack (&yystack);
     }
 
-  /* Make sure YYID is used.  */
-  return YYID (yyresult);
+  return yyresult;
 }
 
 /* DEBUGGING ONLY */
 #if ]b4_api_PREFIX[DEBUG
-static void yypstack (yyGLRStack* yystackp, size_t yyk)
-  __attribute__ ((__unused__));
-static void yypdumpstack (yyGLRStack* yystackp) __attribute__ ((__unused__));
-
 static void
 yy_yypstack (yyGLRState* yys)
 {
@@ -2555,6 +2529,23 @@ yypdumpstack (yyGLRStack* yystackp)
   YYFPRINTF (stderr, "\n");
 }
 #endif
+
+#undef yylval
+#undef yychar
+#undef yynerrs]b4_locations_if([
+#undef yylloc])
+
+m4_if(b4_prefix, [yy], [],
+[[/* Substitute the variable and function names.  */
+#define yyparse ]b4_prefix[parse
+#define yylex   ]b4_prefix[lex
+#define yyerror ]b4_prefix[error
+#define yylval  ]b4_prefix[lval
+#define yychar  ]b4_prefix[char
+#define yydebug ]b4_prefix[debug
+#define yynerrs ]b4_prefix[nerrs]b4_locations_if([[
+#define yylloc  ]b4_prefix[lloc]])])[
+
 ]b4_epilogue[]dnl
 b4_output_end()
 
index bb0234a7c51eb8270ac0a80bbc47e743824e6c68..e57308bd82514cbebe68a6457acf4fd7b0d6bb5b 100644 (file)
@@ -1,5 +1,3 @@
-                                                                    -*- C -*-
-
 # C++ GLR skeleton for Bison
 
 # Copyright (C) 2002-2013 Free Software Foundation, Inc.
@@ -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])
+# We require a pure interface.
 m4_define([b4_pure_flag],      [1])
 
-# The header is mandatory.
-b4_defines_if([],
-              [b4_fatal([b4_skeleton[: using %%defines is mandatory]])])
-
 m4_include(b4_pkgdatadir/[c++.m4])
-b4_percent_define_ifdef([[api.location.type]], [],
-                        [m4_include(b4_pkgdatadir/[location.cc])])
+b4_bison_locations_if([m4_include(b4_pkgdatadir/[location.cc])])
 
 m4_define([b4_parser_class_name],
           [b4_percent_define_get([[parser_class_name]])])
@@ -63,25 +55,37 @@ m4_define([b4_parser_class_name],
 # Save the parse parameters.
 m4_define([b4_parse_param_orig], m4_defn([b4_parse_param]))
 
+# b4_parse_param_wrap
+# -------------------
+# New ones.
+m4_ifset([b4_parse_param],
+[m4_define([b4_parse_param_wrap],
+           [[b4_namespace_ref::b4_parser_class_name[& yyparser], [[yyparser]]],]
+m4_defn([b4_parse_param]))],
+[m4_define([b4_parse_param_wrap],
+           [[b4_namespace_ref::b4_parser_class_name[& yyparser], [[yyparser]]]])
+])
+
 
-# b4_yy_symbol_print_generate
-# ---------------------------
+# b4_yy_symbol_print_define
+# -------------------------
 # Bypass the default implementation to generate the "yy_symbol_print"
 # and "yy_symbol_value_print" functions.
-m4_define([b4_yy_symbol_print_generate],
+m4_define([b4_yy_symbol_print_define],
 [[
 /*--------------------.
 | Print this symbol.  |
 `--------------------*/
 
-]b4_c_ansi_function_def([yy_symbol_print],
+]b4_function_define([yy_symbol_print],
     [static void],
-    [[FILE *],               []],
-    [[int yytype],           [yytype]],
+    [[FILE *],      []],
+    [[int yytype],  [yytype]],
     [[const ]b4_namespace_ref::b4_parser_class_name[::semantic_type *yyvaluep],
-                             [yyvaluep]],
+                    [yyvaluep]][]dnl
+b4_locations_if([,
     [[const ]b4_namespace_ref::b4_parser_class_name[::location_type *yylocationp],
-                             [yylocationp]],
+                    [yylocationp]]]),
     b4_parse_param)[
 {
 ]b4_parse_param_use[]dnl
@@ -90,10 +94,9 @@ m4_define([b4_yy_symbol_print_generate],
 ]])[
 
 # Hijack the initial action to initialize the locations.
-]b4_locations_if([b4_percent_define_ifdef([[api.location.type]], [],
-[m4_define([b4_initial_action],
+]b4_bison_locations_if([m4_define([b4_initial_action],
 [yylloc.initialize ();]m4_ifdef([b4_initial_action], [
-m4_defn([b4_initial_action])]))])])[
+m4_defn([b4_initial_action])]))])[
 
 # Hijack the post prologue to insert early definition of YYLLOC_DEFAULT
 # and declaration of yyerror.
@@ -101,43 +104,60 @@ m4_defn([b4_initial_action])]))])])[
 [b4_syncline([@oline@], [@ofile@])[
 ]b4_yylloc_default_define[
 #define YYRHSLOC(Rhs, K) ((Rhs)[K].yystate.yyloc)
-]b4_c_ansi_function_decl([yyerror],
-    [static void],
+]b4_function_declare([yyerror],
+    [static void],b4_locations_if([
     [[const ]b4_namespace_ref::b4_parser_class_name[::location_type *yylocationp],
-                        [yylocationp]],
+                        [yylocationp]],])
     b4_parse_param,
     [[const char* msg], [msg]])])
 
 
+#undef yynerrs
+#undef yychar
+#undef yylval]b4_locations_if([
+#undef yylloc])
+
+m4_if(b4_prefix, [yy], [],
+[[/* Substitute the variable and function names.  */
+#define yyparse ]b4_prefix[parse
+#define yylex   ]b4_prefix[lex
+#define yyerror ]b4_prefix[error
+#define yydebug ]b4_prefix[debug
+]]b4_pure_if([], [[
+#define yylval  ]b4_prefix[lval
+#define yychar  ]b4_prefix[char
+#define yynerrs ]b4_prefix[nerrs]b4_locations_if([[
+#define yylloc  ]b4_prefix[lloc]])]))
+
 # Hijack the epilogue to define implementations (yyerror, parser member
 # functions etc.).
 m4_append([b4_epilogue],
 [b4_syncline([@oline@], [@ofile@])[
+
 /*------------------.
 | Report an error.  |
 `------------------*/
 
-]b4_c_ansi_function_def([yyerror],
-    [static void],
+]b4_function_define([yyerror],
+    [static void],b4_locations_if([
     [[const ]b4_namespace_ref::b4_parser_class_name[::location_type *yylocationp],
-                        [yylocationp]],
+                        [yylocationp]],])
     b4_parse_param,
     [[const char* msg], [msg]])[
 {
 ]b4_parse_param_use[]dnl
-[  yyparser.error (*yylocationp, msg);
+[  yyparser.error (]b4_locations_if([[*yylocationp, ]])[msg);
 }
 
 
 ]b4_namespace_open[
-]dnl In this section, the parse param are the original parse_params.
+]dnl In this section, the parse params are the original parse_params.
 m4_pushdef([b4_parse_param], m4_defn([b4_parse_param_orig]))dnl
 [  /// Build a parser object.
   ]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[
   {
   }
@@ -159,27 +179,27 @@ m4_pushdef([b4_parse_param], m4_defn([b4_parse_param_orig]))dnl
 
   inline void
   ]b4_parser_class_name[::yy_symbol_value_print_ (int yytype,
-                           const semantic_type* yyvaluep,
-                           const location_type* yylocationp)
-  {
-    YYUSE (yylocationp);
+                           const semantic_type* yyvaluep]b4_locations_if([[,
+                           const location_type* yylocationp]])[)
+  {]b4_locations_if([[
+    YYUSE (yylocationp);]])[
     YYUSE (yyvaluep);
     std::ostream& yyoutput = debug_stream ();
     std::ostream& yyo = yyoutput;
     YYUSE (yyo);
-    ]b4_symbol_actions([printers])[
+    ]b4_symbol_actions([printer])[
   }
 
 
   void
   ]b4_parser_class_name[::yy_symbol_print_ (int yytype,
-                           const semantic_type* yyvaluep,
-                           const location_type* yylocationp)
+                           const semantic_type* yyvaluep]b4_locations_if([[,
+                           const location_type* yylocationp]])[)
   {
     *yycdebug_ << (yytype < YYNTOKENS ? "token" : "nterm")
-               << ' ' << yytname[yytype] << " ("
-               << *yylocationp << ": ";
-    yy_symbol_value_print_ (yytype, yyvaluep, yylocationp);
+               << ' ' << yytname[yytype] << " ("]b4_locations_if([[
+               << *yylocationp << ": "]])[;
+    yy_symbol_value_print_ (yytype, yyvaluep]b4_locations_if([[, yylocationp]])[);
     *yycdebug_ << ')';
   }
 
@@ -214,63 +234,31 @@ m4_pushdef([b4_parse_param], m4_defn([b4_parse_param_orig]))dnl
 b4_namespace_close
 ])
 
+# b4_shared_declarations
+# ----------------------
+# Declaration that might either go into the header (if --defines)
+# or open coded in the parser body.
+m4_define([b4_shared_declarations],
+[m4_pushdef([b4_parse_param], m4_defn([b4_parse_param_orig]))dnl
+b4_percent_code_get([[requires]])[
 
-# Let glr.c believe that the user arguments include the parser itself.
-m4_ifset([b4_parse_param],
-[m4_pushdef([b4_parse_param],
-            [[b4_namespace_ref::b4_parser_class_name[& yyparser], [[yyparser]]],]
-m4_defn([b4_parse_param]))],
-[m4_pushdef([b4_parse_param],
-            [[b4_namespace_ref::b4_parser_class_name[& yyparser], [[yyparser]]]])
-])
-m4_include(b4_pkgdatadir/[glr.c])
-m4_popdef([b4_parse_param])
-
-b4_output_begin([b4_spec_defines_file])
-b4_copyright([Skeleton interface for Bison GLR parsers in C++],
-             [2002-2006, 2009-2013])[
-
-/* C++ GLR parser skeleton written by Akim Demaille.  */
-
-]b4_cpp_guard_open([b4_spec_defines_file])[
-
-]b4_percent_code_get([[requires]])[
-
-# include <string>
-# include <iostream>
-]b4_percent_define_ifdef([[api.location.type]], [],
-                         [[# include "location.hh"]])[
+#include <stdexcept>
+#include <string>
+#include <iostream>]b4_defines_if([
+b4_bison_locations_if([[#include "location.hh"]])])[
 
 ]b4_YYDEBUG_define[
 
 ]b4_namespace_open[
+]b4_defines_if([],
+[b4_bison_locations_if([b4_position_define
+b4_location_define])])[
+
   /// A Bison parser.
   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([[api.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[);
@@ -292,42 +280,39 @@ b4_user_stype
     /// 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.
+    /// 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);
-  private:
+    virtual void error (]b4_locations_if([[const location_type& loc, ]])[const std::string& msg);
 
 # if ]b4_api_PREFIX[DEBUG
   public:
     /// \brief Report a symbol value on the debug stream.
     /// \param yytype       The token type.
-    /// \param yyvaluep     Its semantic value.
-    /// \param yylocationp  Its location.
+    /// \param yyvaluep     Its semantic value.]b4_locations_if([[
+    /// \param yylocationp  Its location.]])[
     virtual void yy_symbol_value_print_ (int yytype,
-                                         const semantic_type* yyvaluep,
-                                         const location_type* yylocationp);
+                                         const semantic_type* yyvaluep]b4_locations_if([[,
+                                         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.
+    /// \param yyvaluep     Its semantic value.]b4_locations_if([[
+    /// \param yylocationp  Its location.]])[
     virtual void yy_symbol_print_ (int yytype,
-                                   const semantic_type* yyvaluep,
-                                   const location_type* yylocationp);
+                                   const semantic_type* yyvaluep]b4_locations_if([[,
+                                   const location_type* yylocationp]])[);
   private:
-    /* Debugging.  */
+    // 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
@@ -338,5 +323,23 @@ b4_percent_define_flag_if([[global_tokens_and_yystype]],
 
 ]b4_namespace_close[
 ]b4_percent_code_get([[provides]])[
+]m4_popdef([b4_parse_param])dnl
+])
+
+b4_defines_if(
+[b4_output_begin([b4_spec_defines_file])
+b4_copyright([Skeleton interface for Bison GLR parsers in C++],
+             [2002-2013])[
+
+// C++ GLR parser skeleton written by Akim Demaille.
+
+]b4_cpp_guard_open([b4_spec_defines_file])[
+]b4_shared_declarations[
 ]b4_cpp_guard_close([b4_spec_defines_file])[
-]b4_output_end()
+]b4_output_end()])
+
+# Let glr.c (and b4_shared_declarations) believe that the user
+# arguments include the parser itself.
+m4_pushdef([b4_parse_param], m4_defn([b4_parse_param_wrap]))
+m4_include(b4_pkgdatadir/[glr.c])
+m4_popdef([b4_parse_param])
index 7c2cfef7d71aea19988ab7f13202ba678454ae20..cff774d886f9777fba72c8213e2f429ecbc7673e 100644 (file)
 
 m4_include(b4_pkgdatadir/[c-like.m4])
 
-# b4_comment(TEXT)
-# ----------------
-m4_define([b4_comment], [/* m4_bpatsubst([$1], [
-], [
-   ])  */])
-
 
 # b4_list2(LIST1, LIST2)
-# --------------------------
+# ----------------------
 # 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)
@@ -38,8 +32,8 @@ m4_define([b4_list2],
 # 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])])
 
 
 
@@ -104,12 +98,12 @@ 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)
 # ---------------------
 # Return the smallest int type able to handle numbers ranging from
-# `NAME_min' to `NAME_max' (included).
+# 'NAME_min' to 'NAME_max' (included).
 m4_define([b4_int_type_for],
 [b4_int_type($1_min, $1_max)])
 
@@ -118,27 +112,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)
 # -----------------
@@ -149,13 +161,20 @@ 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]])
+m4_define([b4_yystype], [b4_percent_define_get([[api.value.type]])])
+b4_percent_define_default([[api.value.type]], [[Object]])
 
 # %name-prefix
 m4_define_default([b4_prefix], [[YY]])
@@ -169,6 +188,9 @@ m4_define([b4_lex_throws], [b4_percent_define_get([[lex_throws]])])
 b4_percent_define_default([[throws]], [])
 m4_define([b4_throws], [b4_percent_define_get([[throws]])])
 
+b4_percent_define_default([[init_throws]], [])
+m4_define([b4_init_throws], [b4_percent_define_get([[init_throws]])])
+
 b4_percent_define_default([[api.location.type]], [Location])
 m4_define([b4_location_type], [b4_percent_define_get([[api.location.type]])])
 
@@ -224,16 +246,16 @@ 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($@)])
@@ -246,21 +268,21 @@ 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])
 
 
@@ -270,13 +292,13 @@ 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;
+          ])
 
 
 
@@ -285,15 +307,15 @@ m4_define([b4_constructor_call],
 # 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;])
 
 
 
@@ -301,4 +323,4 @@ m4_define([b4_var_decl],
 # -----------------------
 # Expand to either an empty string or "throws THROWS".
 m4_define([b4_maybe_throws],
-         [m4_ifval($1, [throws $1])])
+          [m4_ifval($1, [throws $1])])
index f6568695bc95473c219b1bf92b361f70a8acadf1..3294f591106d6cbe53c80c32241e1632990861b9 100644 (file)
 
 m4_include(b4_pkgdatadir/[c++.m4])
 
-m4_define([b4_parser_class_name],
-          [b4_percent_define_get([[parser_class_name]])])
+# api.value.type=variant is valid.
+m4_define([b4_value_type_setup_variant])
+
+# b4_integral_parser_table_declare(TABLE-NAME, CONTENT, COMMENT)
+# --------------------------------------------------------------
+# Declare "parser::yy<TABLE-NAME>_" whose contents is CONTENT.
+m4_define([b4_integral_parser_table_declare],
+[m4_ifval([$3], [b4_comment([$3], [  ])
+])dnl
+  static const b4_int_type_for([$2]) yy$1_[[]];dnl
+])
 
-# The header is mandatory.
-b4_defines_if([],
-              [b4_fatal([b4_skeleton[: using %%defines is mandatory]])])
+# b4_integral_parser_table_define(TABLE-NAME, CONTENT, COMMENT)
+# -------------------------------------------------------------
+# Define "parser::yy<TABLE-NAME>_" whose 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_percent_define_ifdef([[api.location.type]], [],
-  [# Backward compatibility.
-  m4_define([b4_location_constructors])
-  m4_include(b4_pkgdatadir/[location.cc])])
-m4_include(b4_pkgdatadir/[stack.hh])
+# b4_symbol_value_template(VAL, [TYPE])
+# -------------------------------------
+# Same as b4_symbol_value, but used in a template method.  It makes
+# a difference when using variants.  Note that b4_value_type_setup_union
+# overrides b4_symbol_value, so we must override it again.
+m4_copy([b4_symbol_value], [b4_symbol_value_template])
+m4_append([b4_value_type_setup_union],
+          [m4_copy_force([b4_symbol_value_union], [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_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;
 
-b4_defines_if(
-[b4_output_begin([b4_spec_defines_file])
-b4_copyright([Skeleton interface for Bison LALR(1) parsers in C++],
-             [2002-2013])
-[
-/**
- ** \file ]b4_spec_defines_file[
- ** Define the ]b4_namespace_ref[::parser class.
- */
+m4_popdef([b4_symbol_value])[]dnl
+b4_dollar_popdef[]dnl
+])])
 
-/* C++ LALR(1) parser skeleton written by Akim Demaille.  */
 
-]b4_cpp_guard_open([b4_spec_defines_file])[
+# b4_lex
+# ------
+# Call yylex.
+m4_define([b4_lex],
+[b4_token_ctor_if(
+[b4_function_call([yylex],
+                  [symbol_type], m4_ifdef([b4_lex_param], b4_lex_param))],
+[b4_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))])])
 
-]b4_percent_code_get([[requires]])[
 
-#include <string>
-#include <iostream>
-#include "stack.hh"
-]b4_percent_define_ifdef([[api.location.type]], [],
-                         [[#include "location.hh"]])[
+m4_pushdef([b4_copyright_years],
+           [2002-2013])
+
+m4_define([b4_parser_class_name],
+          [b4_percent_define_get([[parser_class_name]])])
+
+b4_bison_locations_if([# Backward compatibility.
+   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])])
+
+# b4_shared_declarations
+# ----------------------
+# Declaration that might either go into the header (if --defines)
+# or open coded in the parser body.
+m4_define([b4_shared_declarations],
+[b4_percent_code_get([[requires]])[
+]b4_parse_assert_if([# include <cassert>])[
+# include <vector>
+# include <iostream>
+# include <stdexcept>
+# include <string>]b4_defines_if([[
+# include "stack.hh"
+]b4_bison_locations_if([[# include "location.hh"]])])[
+]b4_variant_if([b4_variant_includes])[
 
 ]b4_YYDEBUG_define[
 
 ]b4_namespace_open[
 
+]b4_defines_if([],
+[b4_stack_define
+b4_bison_locations_if([b4_position_define
+b4_location_define])])[
+
+]b4_variant_if([b4_variant_define])[
+
   /// A Bison parser.
   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([[api.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[ ();
@@ -106,54 +195,32 @@ b4_user_stype
     void set_debug_level (debug_level_type l);
 #endif
 
+    /// 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 (]b4_locations_if([[const location_type& loc, ]])[const std::string& msg);
+
+    /// Report a syntax error.
+    void error (const syntax_error& err);
+
   private:
     /// This class is not copyable.
     ]b4_parser_class_name[ (const ]b4_parser_class_name[&);
     ]b4_parser_class_name[& operator= (const ]b4_parser_class_name[&);
 
-    /// 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);
+    /// State numbers.
+    typedef int state_type;
 
     /// 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);
+    /// \param yystate   the state where the error occurred.
+    /// \param yytoken   the lookahead token type, or yyempty_.
+    virtual std::string yysyntax_error_ (state_type yystate,
+                                         symbol_number_type yytoken) const;
 
-#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
-
-
-    /// 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_;
+    /// 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
@@ -163,38 +230,14 @@ b4_user_stype
     /// \param yyvalue   the value to check
     static bool yy_table_value_is_error_ (int yyvalue);
 
-    /// 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_[];
+    /// Convert a scanner token number \a t to a symbol number.
+    static token_number_type yytranslate_ (]b4_token_ctor_if([token_type], [int])[ t);
 
-    /// 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);])[
@@ -203,98 +246,170 @@ b4_user_stype
     /// 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
 
-    /// Convert a scanner token number \a t to a symbol number.
-    token_number_type yytranslate_ (int t);
+    /// \brief Display a symbol type, value and location.
+    /// \param yyo    The output stream.
+    /// \param yysym  The symbol.
+    template <typename Base>
+    void yy_print_ (std::ostream& yyo, const basic_symbol<Base>& yysym) const;
+#endif
 
     /// \brief Reclaim the memory associated to a symbol.
-    /// \param yymsg        Why this token is reclaimed.
-    ///                     If null, do not display the symbol, just free it.
-    /// \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 Base>
+    void yy_destroy_ (const char* yymsg, basic_symbol<Base>& yysym) const;
+
+  private:
+    /// Type access provider for state based symbols.
+    struct by_state
+    {
+      /// Default constructor.
+      by_state ();
+
+      /// The symbol type as needed by the constructor.
+      typedef state_type kind_type;
+
+      /// Constructor.
+      by_state (kind_type s);
+
+      /// Copy constructor.
+      by_state (const by_state& other);
+
+      /// Steal the symbol type from \a that.
+      void move (by_state& that);
+
+      /// The (internal) type number (corresponding to \a state).
+      /// "empty" when empty.
+      symbol_number_type type_get () const;
+
+      enum { empty = 0 };
+
+      /// The state.
+      state_type state;
+    };
+
+    /// "Internal" symbol: element of the stack.
+    struct stack_symbol_type : basic_symbol<by_state>
+    {
+      /// Superclass.
+      typedef basic_symbol<by_state> super_type;
+      /// Construct an empty symbol.
+      stack_symbol_type ();
+      /// Steal the contents from \a sym to build this.
+      stack_symbol_type (state_type s, symbol_type& sym);
+      /// Assignment, needed by push_back.
+      stack_symbol_type& operator= (const stack_symbol_type& that);
+    };
+
+    /// 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.
+    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.
+    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_;
+    void yypop_ (unsigned int n = 1);
+
+    // Constants.
+    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_token_ctor_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.  */
+ // Redirection for backward compatibility.
 # define ]b4_api_PREFIX[STYPE b4_namespace_ref::b4_parser_class_name::semantic_type
 #endif
 ])[
 ]b4_percent_code_get([[provides]])[
+]])
+
+b4_defines_if(
+[b4_output_begin([b4_spec_defines_file])
+b4_copyright([Skeleton interface for Bison LALR(1) parsers in C++])
+[
+/**
+ ** \file ]b4_spec_defines_file[
+ ** Define the ]b4_namespace_ref[::parser class.
+ */
+
+// C++ LALR(1) parser skeleton written by Akim Demaille.
+
+]b4_cpp_guard_open([b4_spec_defines_file])[
+]b4_shared_declarations[
 ]b4_cpp_guard_close([b4_spec_defines_file])
 b4_output_end()
 ])
 
 
 b4_output_begin([b4_parser_file_name])
-b4_copyright([Skeleton implementation for Bison LALR(1) parsers in C++],
-             [2002-2013])
+b4_copyright([Skeleton implementation for Bison LALR(1) parsers in C++])
 b4_percent_code_get([[top]])[]dnl
 m4_if(b4_prefix, [yy], [],
 [
 // Take the name prefix into account.
 #define yylex   b4_prefix[]lex])[
 
-/* First part of user declarations.  */
+// First part of user declarations.
 ]b4_user_pre_prologue[
 
-]b4_defines_if([[
-#include "@basename(]b4_spec_defines_file[@)"]])[
+]b4_null_define[
+
+]b4_defines_if([[#include "@basename(]b4_spec_defines_file[@)"]],
+               [b4_shared_declarations])[
 
-/* User implementation prologue.  */
+// User implementation prologue.
 ]b4_user_post_prologue[
 ]b4_percent_code_get[
 
-]b4_null_define[
-
 #ifndef YY_
 # if defined YYENABLE_NLS && YYENABLE_NLS
 #  if ENABLE_NLS
-#   include <libintl.h> /* FIXME: INFRINGES ON USER NAME SPACE */
+#   include <libintl.h> // FIXME: INFRINGES ON USER NAME SPACE.
 #   define YY_(msgid) dgettext ("bison-runtime", msgid)
 #  endif
 # endif
@@ -303,55 +418,56 @@ m4_if(b4_prefix, [yy], [],
 # 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))
+// Suppress unused-variable warnings by "using" E.
+#define YYUSE(E) ((void) (E))
 
-/* Enable debugging if requested.  */
+// Enable debugging if requested.
 #if ]b4_api_PREFIX[DEBUG
 
-/* A pseudo ostream that takes yydebug_ into account.  */
+// 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)
-
-#else /* !]b4_api_PREFIX[DEBUG */
+# 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) YYUSE(Type)
-# define YY_REDUCE_PRINT(Rule)        static_cast<void>(0)
-# define YY_STACK_PRINT()             static_cast<void>(0)
+# 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 */
+#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([[
@@ -379,7 +495,7 @@ do {                                        \
             case '\\':
               if (*++yyp != '\\')
                 goto do_not_strip_quotes;
-              /* Fall through.  */
+              // Fall through.
             default:
               yyr += *yyp;
               break;
@@ -401,63 +517,129 @@ do {                                     \
     ]m4_ifset([b4_parse_param], [  ], [ :])[yydebug_ (false),
       yycdebug_ (&std::cerr)]m4_ifset([b4_parse_param], [,])[
 #endif]b4_parse_param_cons[
+  {}
+
+  ]b4_parser_class_name::~b4_parser_class_name[ ()
+  {}
+
+
+  /*---------------.
+  | Symbol types.  |
+  `---------------*/
+
+]b4_token_ctor_if([], [b4_public_types_define])[
+
+  // by_state.
+  inline
+  ]b4_parser_class_name[::by_state::by_state ()
+    : state (empty)
+  {}
+
+  inline
+  ]b4_parser_class_name[::by_state::by_state (const by_state& other)
+    : state (other.state)
+  {}
+
+  inline
+  void
+  ]b4_parser_class_name[::by_state::move (by_state& that)
   {
+    state = that.state;
+    that.state = empty;
   }
 
-  ]b4_parser_class_name::~b4_parser_class_name[ ()
+  inline
+  ]b4_parser_class_name[::by_state::by_state (state_type s)
+    : state (s)
+  {}
+
+  inline
+  ]b4_parser_class_name[::symbol_number_type
+  ]b4_parser_class_name[::by_state::type_get () const
   {
+    return state == empty ? 0 : yystos_[state];
   }
 
-#if ]b4_api_PREFIX[DEBUG
-  /*--------------------------------.
-  | Print this symbol on YYOUTPUT.  |
-  `--------------------------------*/
+  inline
+  ]b4_parser_class_name[::stack_symbol_type::stack_symbol_type ()
+  {}
+
 
-  inline void
-  ]b4_parser_class_name[::yy_symbol_value_print_ (int yytype,
-                          const semantic_type* yyvaluep, const location_type* yylocationp)
+  inline
+  ]b4_parser_class_name[::stack_symbol_type::stack_symbol_type (state_type s, symbol_type& that)
+    : super_type (s]b4_locations_if([, that.location])[)
   {
-    YYUSE (yylocationp);
-    YYUSE (yyvaluep);
-    std::ostream& yyo = debug_stream ();
-    std::ostream& yyoutput = yyo;
-    YYUSE (yyoutput);
-    ]b4_symbol_actions([printers])[
+    ]b4_variant_if([b4_symbol_variant([that.type_get ()],
+                                      [value], [move], [that.value])],
+                   [[value = that.value;]])[
+    // that is emptied.
+    that.type = empty;
+  }
+
+  inline
+  ]b4_parser_class_name[::stack_symbol_type&
+  ]b4_parser_class_name[::stack_symbol_type::operator= (const stack_symbol_type& that)
+  {
+    state = that.state;
+    ]b4_variant_if([b4_symbol_variant([that.type_get ()],
+                                      [value], [copy], [that.value])],
+                   [[value = that.value;]])[]b4_locations_if([
+    location = that.location;])[
+    return *this;
   }
 
 
+  template <typename Base>
+  inline
   void
-  ]b4_parser_class_name[::yy_symbol_print_ (int yytype,
-                          const semantic_type* yyvaluep, const location_type* yylocationp)
+  ]b4_parser_class_name[::yy_destroy_ (const char* yymsg, basic_symbol<Base>& yysym) const
   {
-    *yycdebug_ << (yytype < yyntokens_ ? "token" : "nterm")
-              << ' ' << yytname_[yytype] << " ("
-              << *yylocationp << ": ";
-    yy_symbol_value_print_ (yytype, yyvaluep, yylocationp);
-    *yycdebug_ << ')';
+    if (yymsg)
+      YY_SYMBOL_PRINT (yymsg, yysym);]b4_variant_if([], [
+
+    // User destructor.
+    b4_symbol_actions([destructor], [yysym.type_get ()])])[
   }
-#endif
 
+#if ]b4_api_PREFIX[DEBUG
+  template <typename Base>
   void
-  ]b4_parser_class_name[::yydestruct_ (const char* yymsg,
-                          int yytype, semantic_type* yyvaluep, location_type* yylocationp)
+  ]b4_parser_class_name[::yy_print_ (std::ostream& yyo,
+                                     const basic_symbol<Base>& yysym) const
   {
-    YYUSE (yylocationp);
-    YYUSE (yymsg);
-    YYUSE (yyvaluep);
+    std::ostream& yyoutput = yyo;
+    YYUSE (yyoutput);
+    symbol_number_type yytype = yysym.type_get ();
+    yyo << (yytype < yyntokens_ ? "token" : "nterm")
+        << ' ' << yytname_[yytype] << " ("]b4_locations_if([
+        << yysym.location << ": "])[;
+    ]b4_symbol_actions([printer])[
+    yyo << ')';
+  }
+#endif
 
-    if (yymsg)
-      YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+  inline
+  void
+  ]b4_parser_class_name[::yypush_ (const char* m, state_type s, symbol_type& sym)
+  {
+    stack_symbol_type t (s, sym);
+    yypush_ (m, t);
+  }
 
-    ]b4_symbol_actions([destructors])[
+  inline
+  void
+  ]b4_parser_class_name[::yypush_ (const char* m, stack_symbol_type& s)
+  {
+    if (m)
+      YY_SYMBOL_PRINT (m, s);
+    yystack_.push (s);
   }
 
+  inline
   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
@@ -485,7 +667,17 @@ do {                                       \
   {
     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)
@@ -502,32 +694,27 @@ do {                                      \
   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.
-    static semantic_type yyval_default;
-    semantic_type yylval = yyval_default;
-    /// 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;
 
     // FIXME: This shoud be completely indented.  It is not yet to
@@ -537,100 +724,87 @@ do {                                     \
     YYCDEBUG << "Starting parse" << std::endl;
 
 ]m4_ifdef([b4_initial_action], [
-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
 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_.clear ();
-    yysemantic_stack_.clear ();
-    yylocation_stack_.clear ();
-    yysemantic_stack_.push (yylval);
-    yylocation_stack_.push (yylloc);
+    yystack_.clear ();
+    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_)
+    // Accept?
+    if (yystack_[0].state == yyfinal_)
       goto yyacceptlab;
 
     goto yybackup;
 
-    /* Backup.  */
+    // Backup.
   yybackup:
 
-    /* Try to take a decision without lookahead.  */
-    yyn = yypact_[yystate];
+    // Try to take a decision without lookahead.
+    yyn = yypact_[yystack_[0].state];
     if (yy_pact_value_is_default_ (yyn))
       goto yydefault;
 
-    /* Read a lookahead token.  */
-    if (yychar == yyempty_)
+    // Read a lookahead token.
+    if (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_)
-      {
-       yychar = yytoken = yyeof_;
-       YYCDEBUG << "Now at end of input." << std::endl;
-      }
-    else
-      {
-       yytoken = yytranslate_ (yychar);
-       YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+        try
+          {]b4_token_ctor_if([[
+            symbol_type yylookahead (]b4_lex[);
+            yyla.move (yylookahead);]], [[
+            yyla.type = yytranslate_ (]b4_lex[);]])[
+          }
+        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_get ();
+    if (yyn < 0 || yylast_ < yyn || yycheck_[yyn] != yyla.type_get ())
       goto yydefault;
 
-    /* Reduce or error.  */
+    // 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);
+    // Discard the token being shifted.
+    yyempty = true;
 
-    /* Count tokens shifted since error; after three, turn off error
-       status.  */
+    // 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;
@@ -640,99 +814,85 @@ m4_ifdef([b4_lex_param], [, ]b4_lex_param))[;
   `-----------------------------*/
   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.
+       '$$ = $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
       {
-        ]b4_user_actions[
-      default:
-        break;
+        switch (yyn)
+          {
+]b4_user_actions[
+          default:
+            break;
+          }
       }
-
-    /* User semantic actions sometimes alter yychar, and that requires
-       that yytoken be updated with the new translation.  We take the
-       approach of translating immediately before every use of yytoken.
-       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);
     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_];
+    // Shift the result of the reduction.
+    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 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_join(b4_locations_if([yyla.location]),
+                        [[yysyntax_error_ (yystack_[0].state,
+                                           yyempty ? yyempty_ : yyla.type_get ())]])[);
       }
 
-    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
+
+        // Return failure if at end of input.
+        if (yyla.type_get () == yyeof_)
+          YYABORT;
+        else if (!yyempty)
           {
-            yydestruct_ ("Error: discarding", yytoken, &yylval, &yylloc);
-            yychar = yyempty_;
+            yy_destroy_ ("Error: discarding", yyla);
+            yyempty = true;
           }
       }
 
-    /* Else will try to reuse lookahead token after shifting the error
-       token.  */
+    // Else will try to reuse lookahead token after shifting the error token.
     goto yyerrlab1;
 
 
@@ -745,129 +905,112 @@ m4_ifdef([b4_lex_param], [, ]b4_lex_param))[;
        YYERROR and the label yyerrorlab therefore never appears in user
        code.  */
     if (false)
-      goto yyerrorlab;
-
-    yyerror_range[1] = yylocation_stack_[yylen - 1];
-    /* Do not reclaim the symbols of the rule which action triggered
+      goto yyerrorlab;]b4_locations_if([[
+    yyerror_range[1].location = yystack_[yylen - 1].location;]])b4_variant_if([[
+    /* $$ was initialized before running the user action.  */
+    YY_SYMBOL_PRINT ("Error: discarding", yylhs);
+    yylhs.~stack_symbol_type();]])[
+    /* Do not reclaim the symbols of the rule whose 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.  */
+    // Accept.
   yyacceptlab:
     yyresult = 0;
     goto yyreturn;
 
-    /* Abort.  */
+    // Abort.
   yyabortlab:
     yyresult = 1;
     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
+    /* Do not reclaim the symbols of the rule whose action triggered
        this YYABORT or YYACCEPT.  */
     yypop_ (yylen);
-    while (1 < yystate_stack_.height ())
+    while (1 < yystack_.size ())
       {
-        yydestruct_ ("Cleanup: popping",
-                     yystos_[yystate_stack_[0]],
-                     &yysemantic_stack_[0],
-                     &yylocation_stack_[0]);
+        yy_destroy_ ("Cleanup: popping", yystack_[0]);
         yypop_ ();
       }
 
     return yyresult;
-    }
+  }
     catch (...)
       {
         YYCDEBUG << "Exception caught: cleaning lookahead and stack"
                  << std::endl;
         // Do not try to display the values of the reclaimed symbols,
         // as their printer might throw an exception.
-        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_ (YY_NULL, yytoken, &yylval, &yylloc);
-          }
+        if (!yyempty)
+          yy_destroy_ (YY_NULL, yyla);
 
-        while (1 < yystate_stack_.height ())
+        while (1 < yystack_.size ())
           {
-            yydestruct_ (YY_NULL,
-                         yystos_[yystate_stack_[0]],
-                         &yysemantic_stack_[0],
-                         &yylocation_stack_[0]);
+            yy_destroy_ (YY_NULL, yystack_[0]);
             yypop_ ();
           }
         throw;
       }
   }
 
+  void
+  ]b4_parser_class_name[::error (const syntax_error& yyexc)
+  {
+    error (]b4_join(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],
-                    [int, int])[)
+b4_error_verbose_if([state_type yystate, symbol_number_type yytoken],
+                    [state_type, symbol_number_type])[) const
   {]b4_error_verbose_if([[
     std::string yyres;
     // Number of reported tokens (one for the "unexpected", one per
@@ -892,7 +1035,7 @@ b4_error_verbose_if([int yystate, int yytoken],
          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
@@ -913,7 +1056,7 @@ b4_error_verbose_if([int yystate, int yytoken],
                YYCHECK.  In other words, skip the first -YYN actions for
                this state because they are default actions.  */
             int yyxbegin = yyn < 0 ? -yyn : 0;
-            /* Stay within bounds of both yycheck and yytname.  */
+            // Stay within bounds of both yycheck and yytname.
             int yychecklim = yylast_ - yyn + 1;
             int yyxend = yychecklim < yyntokens_ ? yychecklim : yyntokens_;
             for (int yyx = yyxbegin; yyx < yyxend; ++yyx)
@@ -962,127 +1105,34 @@ b4_error_verbose_if([int yystate, int yytoken],
   }
 
 
-  /* 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.
-     First, the terminals, then, starting at \a yyntokens_, nonterminals.  */
+  // YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+  // First, the terminals, then, starting at \a yyntokens_, nonterminals.
   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;
   }
 
@@ -1092,46 +1142,20 @@ b4_error_verbose_if([int yystate, int yytoken],
   {
     unsigned int yylno = yyrline_[yyrule];
     int yynrhs = yyr2_[yyrule];
-    /* Print the symbols being reduced, and their result.  */
+    // Print the symbols being reduced, and their result.
     *yycdebug_ << "Reducing stack by rule " << yyrule - 1
-              << " (line " << yylno << "):" << std::endl;
-    /* The symbols being reduced.  */
+               << " (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_token_ctor_if([], [b4_yytranslate_define])[
 ]b4_namespace_close[
 ]b4_epilogue[]dnl
 b4_output_end()
+
+
+m4_popdef([b4_copyright_years])dnl
index 7a7f763b7f38cd823f05b240e861d363dbc995aa..204c03fc6367f897167bba0bfd40b5cb4ca61913 100644 (file)
 
 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])
 
 b4_output_begin([b4_parser_file_name])
 b4_copyright([Skeleton implementation for Bison LALR(1) parsers in Java],
@@ -28,14 +36,16 @@ b4_copyright([Skeleton implementation for Bison LALR(1) parsers in Java],
 
 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
@@ -44,9 +54,22 @@ b4_percent_define_get3([extends], [ extends ])dnl
 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([[
   /**
@@ -92,11 +115,6 @@ 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)
   {
@@ -111,6 +129,11 @@ b4_token_enums(b4_tokens)
    * 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.  */
@@ -139,8 +162,8 @@ b4_token_enums(b4_tokens)
      *
      * ]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 {
@@ -156,7 +179,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[
   }
@@ -166,7 +191,9 @@ b4_lexer_if([[
    * 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[
   }
@@ -200,20 +227,35 @@ b4_lexer_if([[
    */
   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)
@@ -229,24 +271,24 @@ b4_lexer_if([[
     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;]])[
@@ -260,7 +302,7 @@ b4_lexer_if([[
     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;
@@ -285,8 +327,8 @@ b4_lexer_if([[
 
       for (int i = 0; i <= height; i++)
         {
-         out.print (' ');
-         out.print (stateStack[i]);
+          out.print (' ');
+          out.print (stateStack[i]);
         }
       out.println ();
     }
@@ -333,7 +375,7 @@ b4_lexer_if([[
     ]b4_locations_if([b4_location_type[ yyloc = yylloc (yystack, yylen);]])[
 
     /* If YYLEN is nonzero, implement the default value of the action:
-       `$$ = $1'.  Otherwise, use the top of the stack.
+       '$$ = $1'.  Otherwise, use the top of the stack.
 
        Otherwise, the following line sets YYVAL to garbage.
        This behavior is undocumented and Bison
@@ -347,8 +389,8 @@ b4_lexer_if([[
 
     switch (yyn)
       {
-       ]b4_user_actions[
-       default: break;
+        ]b4_user_actions[
+        default: break;
       }
 
     yy_symbol_print ("-> $$ =", yyr1_[yyn], yyval]b4_locations_if([, yyloc])[);
@@ -360,7 +402,7 @@ b4_lexer_if([[
     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_];
@@ -369,6 +411,7 @@ b4_lexer_if([[
     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
@@ -387,7 +430,7 @@ b4_lexer_if([[
               break strip_quotes;
 
             case '\\':
-             if (yystr.charAt(++i) != '\\')
+              if (yystr.charAt(++i) != '\\')
                 break strip_quotes;
               /* Fall through.  */
             default:
@@ -403,20 +446,21 @@ b4_lexer_if([[
 
     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 ()) + ")");
   }
 
   /**
@@ -458,8 +502,8 @@ b4_lexer_if([[
 
 ]m4_ifdef([b4_initial_action], [
 b4_dollar_pushdef([yylval], [], [yylloc])dnl
-/* User initialization code.  */
-b4_user_initial_action
+    /* User initialization code.  */
+    b4_user_initial_action
 b4_dollar_popdef])[]dnl
 
   [  /* Initialize the stack.  */
@@ -470,7 +514,7 @@ b4_dollar_popdef])[]dnl
       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)
@@ -485,31 +529,31 @@ b4_dollar_popdef])[]dnl
         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
@@ -521,20 +565,20 @@ b4_dollar_popdef])[]dnl
         /* <= 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_;
@@ -567,7 +611,7 @@ b4_dollar_popdef])[]dnl
       case YYREDUCE:
         yylen = yyr2_[yyn];
         label = yyaction (yyn, yystack, yylen);
-       yystate = yystack.stateAt (0);
+        yystate = yystack.stateAt (0);
         break;
 
       /*------------------------------------.
@@ -586,17 +630,17 @@ b4_dollar_popdef])[]dnl
         ]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
@@ -622,46 +666,46 @@ b4_dollar_popdef])[]dnl
       | 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;
 
@@ -677,15 +721,10 @@ b4_dollar_popdef])[]dnl
 
   // 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
@@ -749,7 +788,7 @@ b4_dollar_popdef])[]dnl
             return res.toString ();
           }
       }
-
+]])[
     return "syntax error";
   }
 
@@ -771,107 +810,20 @@ b4_dollar_popdef])[]dnl
     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],
+     [[YYTOKEN_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)
@@ -883,21 +835,18 @@ b4_dollar_popdef])[]dnl
     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)
   {
@@ -923,5 +872,5 @@ b4_percent_code_get[]dnl
 
 }
 
-b4_epilogue
+b4_epilogue[]dnl
 b4_output_end()
diff --git a/data/local.mk b/data/local.mk
new file mode 100644 (file)
index 0000000..b829052
--- /dev/null
@@ -0,0 +1,45 @@
+## Copyright (C) 2002, 2005-2013 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
index f5011c66ffbd13f54571b421334cee0b5dd440f7..987843b26cd55e9a7a51850dbedc6d1a185d8597 100644 (file)
@@ -1,6 +1,6 @@
 # C++ skeleton for Bison
 
-# Copyright (C) 2002-2007, 2009-2013 Free Software Foundation, Inc.
+# Copyright (C) 2002-2013 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
 # 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_pushdef([b4_copyright_years],
+           [2002-2013])
 
-b4_output_begin([b4_dir_prefix[]position.hh])
-b4_copyright([Positions for Bison parsers in C++],
-             [2002-2007, 2009-2013])[
-
-/**
- ** \file ]b4_dir_prefix[position.hh
- ** Define the ]b4_namespace_ref[::position class.
- */
-
-]b4_cpp_guard_open([b4_dir_prefix[]position.hh])[
-
-# include <algorithm> // std::max
-# include <iostream>
-# include <string>
-
-]b4_null_define[
-
-]b4_namespace_open[
-  /// Abstract a position.
+# b4_position_define
+# ------------------
+# Define class position.
+m4_define([b4_position_define],
+[[  /// Abstract a position.
   class position
   {
   public:
@@ -144,28 +132,13 @@ b4_copyright([Positions for Bison parsers in C++],
       ostr << *pos.filename << ':';
     return ostr << pos.line << '.' << pos.column;
   }
+]])
 
-]b4_namespace_close[
-]b4_cpp_guard_close([b4_dir_prefix[]position.hh])
-b4_output_end()
-
-
-b4_output_begin([b4_dir_prefix[]location.hh])
-b4_copyright([Locations for Bison parsers in C++],
-             [2002-2007, 2009-2013])[
 
-/**
- ** \file ]b4_dir_prefix[location.hh
- ** Define the ]b4_namespace_ref[::location class.
- */
-
-]b4_cpp_guard_open([b4_dir_prefix[]location.hh])[
-
-# include "position.hh"
-
-]b4_namespace_open[
-
-  /// Abstract a location.
+# b4_location_define
+# ------------------
+m4_define([b4_location_define],
+[[  /// Abstract a location.
   class location
   {
   public:
@@ -280,20 +253,64 @@ b4_copyright([Locations for Bison parsers in C++],
   inline std::basic_ostream<YYChar>&
   operator<< (std::basic_ostream<YYChar>& ostr, const location& loc)
   {
-    position last = loc.end - 1;
-    ostr << loc.begin;
-    if (last.filename
-       && (!loc.begin.filename
-           || *loc.begin.filename != *last.filename))
-      ostr << '-' << last;
-    else if (loc.begin.line != last.line)
-      ostr << '-' << last.line  << '.' << last.column;
-    else if (loc.begin.column != last.column)
-      ostr << '-' << last.column;
+    unsigned int end_col = 0 < loc.end.column ? loc.end.column - 1 : 0;
+    ostr << loc.begin// << "(" << loc.end << ") "
+;
+    if (loc.end.filename
+        && (!loc.begin.filename
+            || *loc.begin.filename != *loc.end.filename))
+      ostr << '-' << loc.end.filename << ':' << loc.end.line << '.' << end_col;
+    else if (loc.begin.line < loc.end.line)
+      ostr << '-' << loc.end.line << '.' << end_col;
+    else if (loc.begin.column < end_col)
+      ostr << '-' << end_col;
     return ostr;
   }
+]])
+
 
+b4_defines_if([
+b4_output_begin([b4_dir_prefix[]position.hh])
+b4_copyright([Positions for Bison parsers in C++])[
+
+/**
+ ** \file ]b4_dir_prefix[position.hh
+ ** Define the ]b4_namespace_ref[::position class.
+ */
+
+]b4_cpp_guard_open([b4_dir_prefix[]position.hh])[
+
+# include <algorithm> // std::max
+# include <iostream>
+# include <string>
+
+]b4_null_define[
+
+]b4_namespace_open[
+]b4_position_define[
 ]b4_namespace_close[
+]b4_cpp_guard_close([b4_dir_prefix[]position.hh])
+b4_output_end()
+
+
+b4_output_begin([b4_dir_prefix[]location.hh])
+b4_copyright([Locations for Bison parsers in C++])[
+
+/**
+ ** \file ]b4_dir_prefix[location.hh
+ ** Define the ]b4_namespace_ref[::location class.
+ */
 
+]b4_cpp_guard_open([b4_dir_prefix[]location.hh])[
+
+# include "position.hh"
+
+]b4_namespace_open[
+]b4_location_define[
+]b4_namespace_close[
 ]b4_cpp_guard_close([b4_dir_prefix[]location.hh])
 b4_output_end()
+])
+
+
+m4_popdef([b4_copyright_years])
index 317a0612c2ac1708151822994e26123ae5a58a8c..aa64d63d842cce563540a8254251dc1135ba9e5c 100644 (file)
 m4_pushdef([b4_copyright_years],
            [2002-2013])
 
-b4_output_begin([b4_dir_prefix[]stack.hh])
-b4_copyright([Stack handling for Bison parsers in C++],
-             [2002-2013])[
-
-/**
- ** \file ]b4_dir_prefix[stack.hh
- ** Define the ]b4_namespace_ref[::stack class.
- */
-
-]b4_cpp_guard_open([b4_dir_prefix[]stack.hh])[
-
-# include <deque>
-
-]b4_namespace_open[
-  template <class T, class S = std::deque<T> >
+# b4_stack_define
+# ---------------
+m4_define([b4_stack_define],
+[[  template <class T, class S = std::vector<T> >
   class stack
   {
   public:
@@ -40,33 +29,39 @@ b4_copyright([Stack handling for Bison parsers in C++],
     typedef typename S::reverse_iterator iterator;
     typedef typename S::const_reverse_iterator const_iterator;
 
-    stack () : seq_ ()
+    stack ()
+      : seq_ ()
     {
     }
 
-    stack (unsigned int n) : seq_ (n)
+    stack (unsigned int n)
+      : seq_ (n)
     {
     }
 
     inline
     T&
-    operator [] (unsigned int i)
+    operator[] (unsigned int i)
     {
-      return seq_[i];
+      return seq_[seq_.size () - 1 - i];
     }
 
     inline
     const T&
-    operator [] (unsigned int i) const
+    operator[] (unsigned int i) const
     {
-      return seq_[i];
+      return seq_[seq_.size () - 1 - i];
     }
 
+    /// Steal the contents of \a t.
+    ///
+    /// Close to move-semantics.
     inline
     void
-    push (const T& t)
+    push (T& t)
     {
-      seq_.push_front (t);
+      seq_.push_back (T());
+      operator[](0).move (t);
     }
 
     inline
@@ -74,7 +69,7 @@ b4_copyright([Stack handling for Bison parsers in C++],
     pop (unsigned int n = 1)
     {
       for (; n; --n)
-        seq_.pop_front ();
+        seq_.pop_back ();
     }
 
     void
@@ -84,18 +79,30 @@ b4_copyright([Stack handling for Bison parsers in C++],
     }
 
     inline
-    unsigned int
-    height () const
+    typename S::size_type
+    size () const
     {
       return seq_.size ();
     }
 
-    inline const_iterator begin () const { return seq_.rbegin (); }
-    inline const_iterator end () const { return seq_.rend (); }
+    inline
+    const_iterator
+    begin () const
+    {
+      return seq_.rbegin ();
+    }
+
+    inline
+    const_iterator
+    end () const
+    {
+      return seq_.rend ();
+    }
 
   private:
     stack (const stack&);
     stack& operator= (const stack&);
+    /// The wrapped container.
     S seq_;
   };
 
@@ -121,9 +128,27 @@ b4_copyright([Stack handling for Bison parsers in C++],
     const S& stack_;
     unsigned int range_;
   };
+]])
+
+b4_defines_if(
+[b4_output_begin([b4_dir_prefix[]stack.hh])
+b4_copyright([Stack handling for Bison parsers in C++])[
+
+/**
+ ** \file ]b4_dir_prefix[stack.hh
+ ** Define the ]b4_namespace_ref[::stack class.
+ */
+
+]b4_cpp_guard_open([b4_dir_prefix[]stack.hh])[
+
+# include <vector>
+
+]b4_namespace_open[
+]b4_stack_define[
 ]b4_namespace_close[
 
 ]b4_cpp_guard_close([b4_dir_prefix[]stack.hh])
 b4_output_end()
+])
 
 m4_popdef([b4_copyright_years])
diff --git a/data/variant.hh b/data/variant.hh
new file mode 100644 (file)
index 0000000..ac4f7a7
--- /dev/null
@@ -0,0 +1,362 @@
+# C++ skeleton for Bison
+
+# Copyright (C) 2002-2013 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/>.
+
+
+## --------- ##
+## variant.  ##
+## --------- ##
+
+# b4_symbol_variant(YYTYPE, YYVAL, ACTION, [ARGS])
+# ------------------------------------------------
+# Run some ACTION ("build", or "destroy") on YYVAL of symbol type
+# YYTYPE.
+m4_define([b4_symbol_variant],
+[m4_pushdef([b4_dollar_dollar],
+            [$2.$3< $][3 > (m4_shift3($@))])dnl
+  switch ($1)
+    {
+b4_type_foreach([b4_type_action_])[]dnl
+      default:
+        break;
+    }
+m4_popdef([b4_dollar_dollar])dnl
+])
+
+
+# _b4_char_sizeof_counter
+# -----------------------
+# A counter used by _b4_char_sizeof_dummy to create fresh symbols.
+m4_define([_b4_char_sizeof_counter],
+[0])
+
+# _b4_char_sizeof_dummy
+# ---------------------
+# At each call return a new C++ identifier.
+m4_define([_b4_char_sizeof_dummy],
+[m4_define([_b4_char_sizeof_counter], m4_incr(_b4_char_sizeof_counter))dnl
+dummy[]_b4_char_sizeof_counter])
+
+
+# b4_char_sizeof(SYMBOL-NUMS)
+# ---------------------------
+# To be mapped on the list of type names to produce:
+#
+#    char dummy1[sizeof(type_name_1)];
+#    char dummy2[sizeof(type_name_2)];
+#
+# for defined type names.
+m4_define([b4_char_sizeof],
+[b4_symbol_if([$1], [has_type],
+[
+m4_map([      b4_symbol_tag_comment], [$@])dnl
+      char _b4_char_sizeof_dummy@{sizeof(b4_symbol([$1], [type]))@};
+])])
+
+
+# b4_variant_includes
+# -------------------
+# The needed includes for variants support.
+m4_define([b4_variant_includes],
+[b4_parse_assert_if([[#include <typeinfo>]])[
+#ifndef YYASSERT
+# include <cassert>
+# define YYASSERT assert
+#endif
+]])
+
+# b4_variant_define
+# -----------------
+# Define "variant".
+m4_define([b4_variant_define],
+[[  /// A char[S] buffer to store and retrieve objects.
+  ///
+  /// Sort of a variant, but does not keep track of the nature
+  /// of the stored data, since that knowledge is available
+  /// via the current state.
+  template <size_t S>
+  struct variant
+  {
+    /// Type of *this.
+    typedef variant<S> self_type;
+
+    /// Empty construction.
+    variant ()]b4_parse_assert_if([
+      : yytname_ (YY_NULL)])[
+    {}
+
+    /// Construct and fill.
+    template <typename T>
+    variant (const T& t)]b4_parse_assert_if([
+      : yytname_ (typeid (T).name ())])[
+    {
+      YYASSERT (sizeof (T) <= S);
+      new (yyas_<T> ()) T (t);
+    }
+
+    /// Destruction, allowed only if empty.
+    ~variant ()
+    {]b4_parse_assert_if([
+      YYASSERT (!yytname_);
+    ])[}
+
+    /// Instantiate an empty \a T in here.
+    template <typename T>
+    T&
+    build ()
+    {]b4_parse_assert_if([
+      YYASSERT (!yytname_);
+      YYASSERT (sizeof (T) <= S);
+      yytname_ = typeid (T).name ();])[
+      return *new (yyas_<T> ()) T;
+    }
+
+    /// Instantiate a \a T in here from \a t.
+    template <typename T>
+    T&
+    build (const T& t)
+    {]b4_parse_assert_if([
+      YYASSERT (!yytname_);
+      YYASSERT (sizeof (T) <= S);
+      yytname_ = typeid (T).name ();])[
+      return *new (yyas_<T> ()) T (t);
+    }
+
+    /// Accessor to a built \a T.
+    template <typename T>
+    T&
+    as ()
+    {]b4_parse_assert_if([
+      YYASSERT (yytname_ == typeid (T).name ());
+      YYASSERT (sizeof (T) <= S);])[
+      return *yyas_<T> ();
+    }
+
+    /// Const accessor to a built \a T (for %printer).
+    template <typename T>
+    const T&
+    as () const
+    {]b4_parse_assert_if([
+      YYASSERT (yytname_ == typeid (T).name ());
+      YYASSERT (sizeof (T) <= S);])[
+      return *yyas_<T> ();
+    }
+
+    /// Swap the content with \a other, of same type.
+    ///
+    /// Both variants must be built beforehand, because swapping the actual
+    /// data requires reading it (with as()), and this is not possible on
+    /// unconstructed variants: it would require some dynamic testing, which
+    /// should not be the variant's responsability.
+    /// Swapping between built and (possibly) non-built is done with
+    /// variant::move ().
+    template <typename T>
+    void
+    swap (self_type& other)
+    {]b4_parse_assert_if([
+      YYASSERT (yytname_);
+      YYASSERT (yytname_ == other.yytname_);])[
+      std::swap (as<T> (), other.as<T> ());
+    }
+
+    /// Move the content of \a other to this.
+    ///
+    /// Destroys \a other.
+    template <typename T>
+    void
+    move (self_type& other)
+    {]b4_parse_assert_if([
+      YYASSERT (!yytname_);])[
+      build<T> ();
+      swap<T> (other);
+      other.destroy<T> ();
+    }
+
+    /// Copy the content of \a other to this.
+    template <typename T>
+    void
+    copy (const self_type& other)
+    {
+      build<T> (other.as<T> ());
+    }
+
+    /// Destroy the stored \a T.
+    template <typename T>
+    void
+    destroy ()
+    {
+      as<T> ().~T ();]b4_parse_assert_if([
+      yytname_ = YY_NULL;])[
+    }
+
+  private:
+    /// Prohibit blind copies.
+    self_type& operator=(const self_type&);
+    variant (const self_type&);
+
+    /// Accessor to raw memory as \a T.
+    template <typename T>
+    T*
+    yyas_ ()
+    {
+      void *yyp = yybuffer_.yyraw;
+      return static_cast<T*> (yyp);
+     }
+
+    /// Const accessor to raw memory as \a T.
+    template <typename T>
+    const T*
+    yyas_ () const
+    {
+      const void *yyp = yybuffer_.yyraw;
+      return static_cast<const T*> (yyp);
+     }
+
+    union
+    {
+      /// Strongest alignment constraints.
+      long double yyalign_me;
+      /// A buffer large enough to store any of the semantic values.
+      char yyraw[S];
+    } yybuffer_;]b4_parse_assert_if([
+
+    /// Whether the content is built: if defined, the name of the stored type.
+    const char *yytname_;])[
+  };
+]])
+
+
+## -------------------------- ##
+## Adjustments for variants.  ##
+## -------------------------- ##
+
+
+# b4_value_type_declare
+# ---------------------
+# Declare semantic_type.
+m4_define([b4_value_type_declare],
+[[    /// An auxiliary type to compute the largest semantic type.
+    union union_type
+    {]b4_type_foreach([b4_char_sizeof])[};
+
+    /// Symbol semantic values.
+    typedef variant<sizeof(union_type)> semantic_type;][]dnl
+])
+
+
+# How the semantic value is extracted when using variants.
+
+# b4_symbol_value(VAL, [TYPE])
+# ----------------------------
+m4_define([b4_symbol_value],
+[m4_ifval([$2],
+          [$1.as< $2 > ()],
+          [$1])])
+
+# b4_symbol_value_template(VAL, [TYPE])
+# -------------------------------------
+# Same as b4_symbol_value, but used in a template method.
+m4_define([b4_symbol_value_template],
+[m4_ifval([$2],
+          [$1.template as< $2 > ()],
+          [$1])])
+
+
+
+## ------------- ##
+## make_SYMBOL.  ##
+## ------------- ##
+
+
+# b4_symbol_constructor_declare_(SYMBOL-NUMBER)
+# ---------------------------------------------
+# Declare the overloaded version of make_symbol for the (common) type of
+# these SYMBOL-NUMBERS.  Use at class-level.
+m4_define([b4_symbol_constructor_declare_],
+[b4_symbol_if([$1], [is_token], [b4_symbol_if([$1], [has_id],
+[    static inline
+    symbol_type
+    make_[]b4_symbol_([$1], [id]) (dnl
+b4_join(b4_symbol_if([$1], [has_type],
+                     [const b4_symbol([$1], [type])& v]),
+        b4_locations_if([const location_type& l])));
+
+])])])
+
+
+# b4_symbol_constructor_declare
+# -----------------------------
+# Declare symbol constructors for all the value types.
+# Use at class-level.
+m4_define([b4_symbol_constructor_declare],
+[    // Symbol constructors declarations.
+b4_symbol_foreach([b4_symbol_constructor_declare_])])
+
+
+
+# b4_symbol_constructor_define_(SYMBOL-NUMBER)
+# --------------------------------------------
+# Define symbol constructor for this SYMBOL-NUMBER.
+m4_define([b4_symbol_constructor_define_],
+[b4_symbol_if([$1], [is_token], [b4_symbol_if([$1], [has_id],
+[  b4_parser_class_name::symbol_type
+  b4_parser_class_name::make_[]b4_symbol_([$1], [id]) (dnl
+b4_join(b4_symbol_if([$1], [has_type],
+                     [const b4_symbol([$1], [type])& v]),
+        b4_locations_if([const location_type& l])))
+  {
+    return symbol_type (b4_join([token::b4_symbol([$1], [id])],
+                                b4_symbol_if([$1], [has_type], [v]),
+                                b4_locations_if([l])));
+
+  }
+
+])])])
+
+
+# b4_basic_symbol_constructor_declare
+# -----------------------------------
+# Generate a constructor declaration for basic_symbol from given type.
+m4_define([b4_basic_symbol_constructor_declare],
+[[
+  basic_symbol (]b4_join(
+          [typename Base::kind_type t],
+          b4_symbol_if([$1], [has_type], const b4_symbol([$1], [type])[ v]),
+          b4_locations_if([const location_type& l]))[);
+]])
+
+# b4_basic_symbol_constructor_define
+# ----------------------------------
+# Generate a constructor implementation for basic_symbol from given type.
+m4_define([b4_basic_symbol_constructor_define],
+[[
+  template <typename Base>
+  ]b4_parser_class_name[::basic_symbol<Base>::basic_symbol (]b4_join(
+          [typename Base::kind_type t],
+          b4_symbol_if([$1], [has_type], const b4_symbol([$1], [type])[ v]),
+          b4_locations_if([const location_type& l]))[)
+    : Base (t)
+    , value (]b4_symbol_if([$1], [has_type], [v])[)]b4_locations_if([
+    , location (l)])[
+  {}
+]])
+
+# b4_symbol_constructor_define
+# ----------------------------
+# Define the overloaded versions of make_symbol for all the value types.
+m4_define([b4_symbol_constructor_define],
+[  // Implementation of make_symbol for each symbol type.
+b4_symbol_foreach([b4_symbol_constructor_define_])])
index 3d7939f6f087370d4c5a08420062ed3aeccc704d..93bec59989345afa569beff8257ef7f1bfbdd93b 100644 (file)
     <xsl:with-param name="dst" select="@state"/>
     <xsl:with-param name="style">
       <xsl:choose>
-       <xsl:when test="@symbol = 'error'">
-         <xsl:text>dotted</xsl:text>
-       </xsl:when>
-       <xsl:when test="@type = 'shift'">
-         <xsl:text>solid</xsl:text>
-       </xsl:when>
-       <xsl:otherwise>
-         <xsl:text>dashed</xsl:text>
-       </xsl:otherwise>
+        <xsl:when test="@symbol = 'error'">
+          <xsl:text>dotted</xsl:text>
+        </xsl:when>
+        <xsl:when test="@type = 'shift'">
+          <xsl:text>solid</xsl:text>
+        </xsl:when>
+        <xsl:otherwise>
+          <xsl:text>dashed</xsl:text>
+        </xsl:otherwise>
       </xsl:choose>
     </xsl:with-param>
     <xsl:with-param name="label">
       <xsl:if test="not(@symbol = 'error')">
-       <xsl:value-of select="@symbol"/>
+        <xsl:value-of select="@symbol"/>
       </xsl:if>
     </xsl:with-param>
   </xsl:call-template>
index d479a8e0a63eff9a5d7228084ae8d75e63a7deb1..c4651d4de67dacd523f714da3e025645570a872c 100644 (file)
     <xsl:text>&#10;</xsl:text>
     <xsl:apply-templates select="transition[@type = $type]">
       <xsl:with-param name="pad">
-       <xsl:call-template name="max-width-symbol">
-         <xsl:with-param name="node" select="transition[@type = $type]"/>
-       </xsl:call-template>
+        <xsl:call-template name="max-width-symbol">
+          <xsl:with-param name="node" select="transition[@type = $type]"/>
+        </xsl:call-template>
       </xsl:with-param>
     </xsl:apply-templates>
   </xsl:if>
     <xsl:text>&#10;</xsl:text>
     <xsl:apply-templates select="error">
       <xsl:with-param name="pad">
-       <xsl:call-template name="max-width-symbol">
-         <xsl:with-param name="node" select="error"/>
-       </xsl:call-template>
+        <xsl:call-template name="max-width-symbol">
+          <xsl:with-param name="node" select="error"/>
+        </xsl:call-template>
       </xsl:with-param>
     </xsl:apply-templates>
   </xsl:if>
     <xsl:text>&#10;</xsl:text>
     <xsl:apply-templates select="reduction">
       <xsl:with-param name="pad">
-       <xsl:call-template name="max-width-symbol">
-         <xsl:with-param name="node" select="reduction"/>
-       </xsl:call-template>
+        <xsl:call-template name="max-width-symbol">
+          <xsl:with-param name="node" select="reduction"/>
+        </xsl:call-template>
       </xsl:with-param>
     </xsl:apply-templates>
   </xsl:if>
 <xsl:template match="item">
   <xsl:param name="pad"/>
   <xsl:param name="prev-rule-number"
-            select="preceding-sibling::item[1]/@rule-number"/>
+             select="preceding-sibling::item[1]/@rule-number"/>
   <xsl:apply-templates
     select="key('bison:ruleByNumber', current()/@rule-number)"
   >
   <xsl:choose>
     <xsl:when test="$itemset != 'true' and $prev-lhs = lhs[text()]">
       <xsl:call-template name="lpad">
-       <xsl:with-param name="str" select="'|'"/>
-       <xsl:with-param name="pad" select="number(string-length(lhs[text()])) + 1"/>
+        <xsl:with-param name="str" select="'|'"/>
+        <xsl:with-param name="pad" select="number(string-length(lhs[text()])) + 1"/>
       </xsl:call-template>
     </xsl:when>
     <xsl:when test="$itemset = 'true' and $prev-lhs = lhs[text()]">
       <xsl:call-template name="lpad">
-       <xsl:with-param name="str" select="'|'"/>
-       <xsl:with-param name="pad" select="number(string-length(lhs[text()])) + 1"/>
+        <xsl:with-param name="str" select="'|'"/>
+        <xsl:with-param name="pad" select="number(string-length(lhs[text()])) + 1"/>
       </xsl:call-template>
     </xsl:when>
     <xsl:otherwise>
       <xsl:value-of select="@rule"/>
       <xsl:text> (</xsl:text>
       <xsl:value-of
-         select="key('bison:ruleByNumber', current()/@rule)/lhs[text()]"/>
+          select="key('bison:ruleByNumber', current()/@rule)/lhs[text()]"/>
       <xsl:text>)</xsl:text>
     </xsl:otherwise>
   </xsl:choose>
   <xsl:variable name="longest">
     <xsl:for-each select="$node">
       <xsl:sort data-type="number" select="string-length(@symbol)"
-               order="descending"/>
+                order="descending"/>
       <xsl:if test="position() = 1">
-       <xsl:value-of select="string-length(@symbol)"/>
+        <xsl:value-of select="string-length(@symbol)"/>
       </xsl:if>
     </xsl:for-each>
   </xsl:variable>
     </xsl:when>
     <xsl:otherwise>
       <xsl:call-template name="space">
-       <xsl:with-param name="repeat" select="$diff"/>
+        <xsl:with-param name="repeat" select="$diff"/>
       </xsl:call-template>
       <xsl:value-of select="$str"/>
     </xsl:otherwise>
     <xsl:otherwise>
       <xsl:value-of select="$str"/>
       <xsl:call-template name="space">
-       <xsl:with-param name="repeat" select="$diff"/>
+        <xsl:with-param name="repeat" select="$diff"/>
       </xsl:call-template>
     </xsl:otherwise>
   </xsl:choose>
index 4e747b26a5aa4bf2ce43f6d2613004d668f0e473..d2cfed4ccd5f27dea43fc9c50437ef370da870ff 100644 (file)
 <xsl:import href="bison.xsl"/>
 
 <xsl:output method="xml" encoding="UTF-8"
-           doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
-           doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
-           indent="yes"/>
+            doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
+            doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
+            indent="yes"/>
 
 <xsl:template match="/">
   <html>
     <head>
       <title>
-       <xsl:value-of select="bison-xml-report/filename"/>
-       <xsl:text> - GNU Bison XML Automaton Report</xsl:text>
+        <xsl:value-of select="bison-xml-report/filename"/>
+        <xsl:text> - GNU Bison XML Automaton Report</xsl:text>
       </title>
       <style type="text/css"><![CDATA[
       body {
         font-family: "Nimbus Sans L", Arial, sans-serif;
-       font-size: 9pt;
+        font-size: 9pt;
       }
       a:link {
-       color: #1f00ff;
-       text-decoration: none;
+        color: #1f00ff;
+        text-decoration: none;
       }
       a:visited {
-       color: #1f00ff;
-       text-decoration: none;
+        color: #1f00ff;
+        text-decoration: none;
       }
       a:hover {
-       color: red;
+        color: red;
       }
       #menu a {
         text-decoration: underline;
     <li>
       <a href="#reductions">Reductions</a>
       <ul class="lower-alpha">
-       <li><a href="#nonterminals_useless_in_grammar">Nonterminals useless in grammar</a></li>
-       <li><a href="#terminals_unused_in_grammar">Terminals unused in grammar</a></li>
-       <li><a href="#rules_useless_in_grammar">Rules useless in grammar</a></li>
-       <xsl:if test="grammar/rules/rule[@usefulness='useless-in-parser']">
-         <li><a href="#rules_useless_in_parser">Rules useless in parser due to conflicts</a></li>
-       </xsl:if>
+        <li><a href="#nonterminals_useless_in_grammar">Nonterminals useless in grammar</a></li>
+        <li><a href="#terminals_unused_in_grammar">Terminals unused in grammar</a></li>
+        <li><a href="#rules_useless_in_grammar">Rules useless in grammar</a></li>
+        <xsl:if test="grammar/rules/rule[@usefulness='useless-in-parser']">
+          <li><a href="#rules_useless_in_parser">Rules useless in parser due to conflicts</a></li>
+        </xsl:if>
       </ul>
     </li>
     <li><a href="#conflicts">Conflicts</a></li>
     <li>
       <a href="#grammar">Grammar</a>
       <ul class="lower-alpha">
-       <li><a href="#grammar">Itemset</a></li>
-       <li><a href="#terminals">Terminal symbols</a></li>
-       <li><a href="#nonterminals">Nonterminal symbols</a></li>
+        <li><a href="#grammar">Itemset</a></li>
+        <li><a href="#terminals">Terminal symbols</a></li>
+        <li><a href="#nonterminals">Nonterminal symbols</a></li>
       </ul>
     </li>
     <li><a href="#automaton">Automaton</a></li>
   <xsl:if test="nonterminal[@usefulness='useless-in-grammar']">
     <p class="pre">
       <xsl:for-each select="nonterminal[@usefulness='useless-in-grammar']">
-       <xsl:text>   </xsl:text>
-       <xsl:value-of select="@name"/>
-       <xsl:text>&#10;</xsl:text>
+        <xsl:text>   </xsl:text>
+        <xsl:value-of select="@name"/>
+        <xsl:text>&#10;</xsl:text>
       </xsl:for-each>
       <xsl:text>&#10;&#10;</xsl:text>
     </p>
     <p class="pre">
       <xsl:for-each select="terminal[@usefulness='unused-in-grammar']">
         <xsl:sort select="@symbol-number" data-type="number"/>
-       <xsl:text>   </xsl:text>
-       <xsl:value-of select="@name"/>
-       <xsl:text>&#10;</xsl:text>
+        <xsl:text>   </xsl:text>
+        <xsl:value-of select="@name"/>
+        <xsl:text>&#10;</xsl:text>
       </xsl:for-each>
       <xsl:text>&#10;&#10;</xsl:text>
     </p>
   <h3>
     <a>
       <xsl:attribute name="name">
-       <xsl:value-of select="concat('state_', @number)"/>
+        <xsl:value-of select="concat('state_', @number)"/>
       </xsl:attribute>
     </a>
     <xsl:text>state </xsl:text>
     <xsl:text>&#10;</xsl:text>
     <xsl:apply-templates select="transition[@type = $type]">
       <xsl:with-param name="pad">
-       <xsl:call-template name="max-width-symbol">
-         <xsl:with-param name="node" select="transition[@type = $type]"/>
-       </xsl:call-template>
+        <xsl:call-template name="max-width-symbol">
+          <xsl:with-param name="node" select="transition[@type = $type]"/>
+        </xsl:call-template>
       </xsl:with-param>
     </xsl:apply-templates>
   </xsl:if>
     <xsl:text>&#10;</xsl:text>
     <xsl:apply-templates select="error">
       <xsl:with-param name="pad">
-       <xsl:call-template name="max-width-symbol">
-         <xsl:with-param name="node" select="error"/>
-       </xsl:call-template>
+        <xsl:call-template name="max-width-symbol">
+          <xsl:with-param name="node" select="error"/>
+        </xsl:call-template>
       </xsl:with-param>
     </xsl:apply-templates>
   </xsl:if>
     <xsl:text>&#10;</xsl:text>
     <xsl:apply-templates select="reduction">
       <xsl:with-param name="pad">
-       <xsl:call-template name="max-width-symbol">
-         <xsl:with-param name="node" select="reduction"/>
-       </xsl:call-template>
+        <xsl:call-template name="max-width-symbol">
+          <xsl:with-param name="node" select="reduction"/>
+        </xsl:call-template>
       </xsl:with-param>
     </xsl:apply-templates>
   </xsl:if>
 <xsl:template match="item">
   <xsl:param name="pad"/>
   <xsl:param name="prev-rule-number"
-            select="preceding-sibling::item[1]/@rule-number"/>
+             select="preceding-sibling::item[1]/@rule-number"/>
   <xsl:apply-templates
     select="key('bison:ruleByNumber', current()/@rule-number)"
   >
   <xsl:if test="$itemset != 'true'">
     <a>
       <xsl:attribute name="name">
-       <xsl:value-of select="concat('rule_', @number)"/>
+        <xsl:value-of select="concat('rule_', @number)"/>
       </xsl:attribute>
     </a>
   </xsl:if>
   <xsl:choose>
     <xsl:when test="$itemset = 'true'">
       <a>
-       <xsl:attribute name="href">
-         <xsl:value-of select="concat('#rule_', @number)"/>
-       </xsl:attribute>
-       <xsl:call-template name="lpad">
-         <xsl:with-param name="str" select="string(@number)"/>
-         <xsl:with-param name="pad" select="number($pad)"/>
-       </xsl:call-template>
+        <xsl:attribute name="href">
+          <xsl:value-of select="concat('#rule_', @number)"/>
+        </xsl:attribute>
+        <xsl:call-template name="lpad">
+          <xsl:with-param name="str" select="string(@number)"/>
+          <xsl:with-param name="pad" select="number($pad)"/>
+        </xsl:call-template>
       </a>
     </xsl:when>
     <xsl:otherwise>
       <xsl:call-template name="lpad">
-       <xsl:with-param name="str" select="string(@number)"/>
-       <xsl:with-param name="pad" select="number($pad)"/>
+        <xsl:with-param name="str" select="string(@number)"/>
+        <xsl:with-param name="pad" select="number($pad)"/>
       </xsl:call-template>
     </xsl:otherwise>
   </xsl:choose>
   <xsl:choose>
     <xsl:when test="$itemset != 'true' and $prev-lhs = lhs[text()]">
       <xsl:call-template name="lpad">
-       <xsl:with-param name="str" select="'|'"/>
-       <xsl:with-param name="pad" select="number(string-length(lhs[text()])) + 2"/>
+        <xsl:with-param name="str" select="'|'"/>
+        <xsl:with-param name="pad" select="number(string-length(lhs[text()])) + 2"/>
       </xsl:call-template>
     </xsl:when>
     <xsl:when test="$itemset = 'true' and $prev-lhs = lhs[text()]">
       <xsl:call-template name="lpad">
-       <xsl:with-param name="str" select="'|'"/>
-       <xsl:with-param name="pad" select="number(string-length(lhs[text()])) + 2"/>
+        <xsl:with-param name="str" select="'|'"/>
+        <xsl:with-param name="pad" select="number(string-length(lhs[text()])) + 2"/>
       </xsl:call-template>
     </xsl:when>
     <xsl:otherwise>
       <span class="i">
-       <xsl:value-of select="lhs"/>
+        <xsl:value-of select="lhs"/>
       </span>
       <xsl:text> &#8594;</xsl:text>
     </xsl:otherwise>
   <xsl:choose>
     <xsl:when test="@type = 'shift'">
       <a>
-       <xsl:attribute name="href">
-         <xsl:value-of select="concat('#state_', @state)"/>
-       </xsl:attribute>
-       <xsl:value-of select="concat('shift, and go to state ', @state)"/>
+        <xsl:attribute name="href">
+          <xsl:value-of select="concat('#state_', @state)"/>
+        </xsl:attribute>
+        <xsl:value-of select="concat('shift, and go to state ', @state)"/>
       </a>
     </xsl:when>
     <xsl:when test="@type = 'goto'">
       <a>
-       <xsl:attribute name="href">
-         <xsl:value-of select="concat('#state_', @state)"/>
-       </xsl:attribute>
-       <xsl:value-of select="concat('go to state ', @state)"/>
+        <xsl:attribute name="href">
+          <xsl:value-of select="concat('#state_', @state)"/>
+        </xsl:attribute>
+        <xsl:value-of select="concat('go to state ', @state)"/>
       </a>
     </xsl:when>
   </xsl:choose>
     </xsl:when>
     <xsl:otherwise>
       <a>
-       <xsl:attribute name="href">
-         <xsl:value-of select="concat('#rule_', @rule)"/>
-       </xsl:attribute>
-       <xsl:value-of select="concat('reduce using rule ', @rule)"/>
+        <xsl:attribute name="href">
+          <xsl:value-of select="concat('#rule_', @rule)"/>
+        </xsl:attribute>
+        <xsl:value-of select="concat('reduce using rule ', @rule)"/>
       </a>
       <xsl:text> (</xsl:text>
       <xsl:value-of
   <xsl:variable name="longest">
     <xsl:for-each select="$node">
       <xsl:sort data-type="number" select="string-length(@symbol)"
-               order="descending"/>
+                order="descending"/>
       <xsl:if test="position() = 1">
-       <xsl:value-of select="string-length(@symbol)"/>
+        <xsl:value-of select="string-length(@symbol)"/>
       </xsl:if>
     </xsl:for-each>
   </xsl:variable>
     </xsl:when>
     <xsl:otherwise>
       <xsl:call-template name="space">
-       <xsl:with-param name="repeat" select="$diff"/>
+        <xsl:with-param name="repeat" select="$diff"/>
       </xsl:call-template>
       <xsl:value-of select="$str"/>
     </xsl:otherwise>
     <xsl:otherwise>
       <xsl:value-of select="$str"/>
       <xsl:call-template name="space">
-       <xsl:with-param name="repeat" select="$diff"/>
+        <xsl:with-param name="repeat" select="$diff"/>
       </xsl:call-template>
     </xsl:otherwise>
   </xsl:choose>
index 360892315284edee098385630c7d5dcd986a9803..74fadd1d725b02596e7d9c4a2b6e7fd73f7722a4 100644 (file)
@@ -1,10 +1,12 @@
                                                              -*- C -*-
-
 # Yacc compatible skeleton for Bison
 
 # Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation,
 # Inc.
 
+m4_pushdef([b4_copyright_years],
+           [1984, 1989-1990, 2000-2013])
+
 # 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
@@ -95,17 +97,8 @@ m4_define([b4_yyerror_arg_loc_if],
 # Arguments passed to yyerror: user args plus yylloc.
 m4_define([b4_yyerror_args],
 [b4_yyerror_arg_loc_if([&yylloc, ])dnl
-m4_ifset([b4_parse_param], [b4_c_args(b4_parse_param), ])])
-
+m4_ifset([b4_parse_param], [b4_args(b4_parse_param), ])])
 
-# b4_lex_param
-# ------------
-# Accumulate in b4_lex_param all the yylex arguments.
-# b4_lex_param arrives quoted twice, but we want to keep only one level.
-m4_define([b4_lex_param],
-m4_dquote(b4_pure_if([[[[YYSTYPE *]], [[&yylval]]][]dnl
-b4_locations_if([, [[YYLTYPE *], [&yylloc]]])m4_ifdef([b4_lex_param], [, ])])dnl
-m4_ifdef([b4_lex_param], b4_lex_param)))
 
 
 ## ------------ ##
@@ -127,7 +120,7 @@ m4_define([b4_int_type],
 
        m4_eval([0 <= $1]),                [1], [unsigned int],
 
-                                              [int])])
+                                               [int])])
 
 
 ## ----------------- ##
@@ -139,7 +132,7 @@ m4_define([b4_int_type],
 # --------------------
 # 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])
@@ -147,8 +140,7 @@ m4_define([b4_lhs_value],
 # 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])])
 
 
 ## ----------- ##
@@ -167,7 +159,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])@})])
 
 
 ## -------------- ##
@@ -230,9 +222,9 @@ m4_define([b4_declare_parser_state_variables], [b4_pure_if([[
     int yyerrstatus;
 
     /* The stacks and their tools:
-       `yyss': related to states.
-       `yyvs': related to semantic values.]b4_locations_if([[
-       `yyls': related to locations.]])[
+       'yyss': related to states.
+       'yyvs': related to semantic values.]b4_locations_if([[
+       'yyls': related to locations.]])[
 
        Refer to the stacks through separate pointers, to allow yyoverflow
        to reallocate them elsewhere.  */
@@ -274,19 +266,19 @@ enum { YYPUSH_MORE = 4 };
 
 typedef struct ]b4_prefix[pstate ]b4_prefix[pstate;
 
-]b4_pull_if([b4_c_function_decl([b4_prefix[parse]], [[int]], b4_parse_param)
-])b4_c_function_decl([b4_prefix[push_parse]], [[int]],
+]b4_pull_if([b4_function_declare([b4_prefix[parse]], [[int]], b4_parse_param)
+])b4_function_declare([b4_prefix[push_parse]], [[int]],
   [[b4_prefix[pstate *ps]], [[ps]]]b4_pure_if([,
   [[[int pushed_char]], [[pushed_char]]],
   [[b4_api_PREFIX[STYPE const *pushed_val]], [[pushed_val]]]b4_locations_if([,
   [[b4_api_PREFIX[LTYPE *pushed_loc]], [[pushed_loc]]]])])m4_ifset([b4_parse_param], [,
   b4_parse_param]))
-b4_pull_if([b4_c_function_decl([b4_prefix[pull_parse]], [[int]],
+b4_pull_if([b4_function_declare([b4_prefix[pull_parse]], [[int]],
   [[b4_prefix[pstate *ps]], [[ps]]]m4_ifset([b4_parse_param], [,
   b4_parse_param]))])
-b4_c_function_decl([b4_prefix[pstate_new]], [b4_prefix[pstate *]],
+b4_function_declare([b4_prefix[pstate_new]], [b4_prefix[pstate *]],
                     [[[void]], []])
-b4_c_function_decl([b4_prefix[pstate_delete]], [[void]],
+b4_function_declare([b4_prefix[pstate_delete]], [[void]],
                    [[b4_prefix[pstate *ps]], [[ps]]])dnl
 ])
 
@@ -294,13 +286,7 @@ b4_c_function_decl([b4_prefix[pstate_delete]], [[void]],
 # -------------------
 # When not the push parser.
 m4_define([b4_declare_yyparse_],
-[[#ifdef YYPARSE_PARAM
-]b4_c_function_decl(b4_prefix[parse], [int],
-                    [[void *YYPARSE_PARAM], [YYPARSE_PARAM]])[
-#else /* ! YYPARSE_PARAM */
-]b4_c_function_decl(b4_prefix[parse], [int], b4_parse_param)[
-#endif /* ! YYPARSE_PARAM */]dnl
-])
+[b4_function_declare(b4_prefix[parse], [int], b4_parse_param)])
 
 
 # b4_declare_yyparse
@@ -319,21 +305,19 @@ 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]])[
 ]b4_cpp_guard_close([b4_spec_defines_file])[]dnl
 ])
 
-
 ## -------------- ##
 ## Output files.  ##
 ## -------------- ##
 
 b4_output_begin([b4_parser_file_name])
-b4_copyright([Bison implementation for Yacc-like parsers in C],
-             [1984, 1989-1990, 2000-2013])[
+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.  */
@@ -361,11 +345,12 @@ m4_if(b4_api_prefix, [yy], [],
 #define yypstate        ]b4_prefix[pstate]])[
 #define yylex           ]b4_prefix[lex
 #define yyerror         ]b4_prefix[error
-#define yylval          ]b4_prefix[lval
-#define yychar          ]b4_prefix[char
 #define yydebug         ]b4_prefix[debug
-#define yynerrs         ]b4_prefix[nerrs]b4_locations_if([[
-#define yylloc          ]b4_prefix[lloc]])])[
+#define yynerrs         ]b4_prefix[nerrs
+]]b4_pure_if([], [[
+#define yylval          ]b4_prefix[lval
+#define yychar          ]b4_prefix[char]b4_locations_if([[
+#define yylloc          ]b4_prefix[lloc]])]))[
 
 /* Copy the first part of user declarations.  */
 ]b4_user_pre_prologue[
@@ -377,7 +362,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
 
 ]m4_ifval(m4_quote(b4_spec_defines_file),
@@ -402,10 +387,8 @@ typedef unsigned char yytype_uint8;
 
 #ifdef YYTYPE_INT8
 typedef YYTYPE_INT8 yytype_int8;
-#elif ]b4_c_modern[
-typedef signed char yytype_int8;
 #else
-typedef short int yytype_int8;
+typedef signed char yytype_int8;
 #endif
 
 #ifdef YYTYPE_UINT16
@@ -425,7 +408,7 @@ typedef short int yytype_int16;
 #  define YYSIZE_T __SIZE_TYPE__
 # elif defined size_t
 #  define YYSIZE_T size_t
-# elif ! defined YYSIZE_T && ]b4_c_modern[
+# elif ! defined YYSIZE_T
 #  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
 #  define YYSIZE_T size_t
 # else
@@ -449,16 +432,6 @@ typedef short int yytype_int16;
 
 ]b4_attribute_define[
 
-/* Identity function, used to suppress warnings about constant conditions.  */
-#ifndef lint
-# define YYID(N) (N)
-#else
-]b4_c_function_def([YYID], [static int], [[int yyi], [yyi]])[
-{
-  return yyi;
-}
-#endif
-
 #if ]b4_lac_if([[1]], [[! defined yyoverflow || YYERROR_VERBOSE]])[
 
 /* The parser invokes alloca or malloc; define the necessary symbols.  */]dnl
@@ -477,7 +450,7 @@ b4_push_if([], [b4_lac_if([], [[
 #    define alloca _alloca
 #   else
 #    define YYSTACK_ALLOC alloca
-#    if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && ]b4_c_modern[
+#    if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS
 #     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
       /* Use EXIT_SUCCESS as a witness for stdlib.h.  */
 #     ifndef EXIT_SUCCESS
@@ -489,8 +462,8 @@ b4_push_if([], [b4_lac_if([], [[
 # endif]])])[
 
 # ifdef YYSTACK_ALLOC
-   /* Pacify GCC's `empty if-body' warning.  */
-#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+   /* Pacify GCC's 'empty if-body' warning.  */
+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
 #  ifndef YYSTACK_ALLOC_MAXIMUM
     /* The OS might guarantee only one guard page at the bottom of the stack,
        and a page size can be as small as 4096 bytes.  So we cannot safely
@@ -506,7 +479,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
@@ -514,13 +487,13 @@ b4_push_if([], [b4_lac_if([], [[
 #  endif
 #  ifndef YYMALLOC
 #   define YYMALLOC malloc
-#   if ! defined malloc && ! defined EXIT_SUCCESS && ]b4_c_modern[
+#   if ! defined malloc && ! defined EXIT_SUCCESS
 void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
 #   endif
 #  endif
 #  ifndef YYFREE
 #   define YYFREE free
-#   if ! defined free && ! defined EXIT_SUCCESS && ]b4_c_modern[
+#   if ! defined free && ! defined EXIT_SUCCESS
 void free (void *); /* INFRINGES ON USER NAME SPACE */
 #   endif
 #  endif
@@ -531,8 +504,8 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */
 
 #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
@@ -562,16 +535,16 @@ 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);                          \
-      }                                                                        \
-    while (YYID (0))
+# 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 (0)
 
 #endif
 
@@ -590,7 +563,7 @@ union yyalloc
           for (yyi = 0; yyi < (Count); yyi++)   \
             (Dst)[yyi] = (Src)[yyi];            \
         }                                       \
-      while (YYID (0))
+      while (0)
 #  endif
 # endif
 #endif /* !YYCOPY_NEEDED */
@@ -606,41 +579,27 @@ union yyalloc
 #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[
@@ -653,105 +612,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)
 
@@ -769,26 +658,18 @@ do                                                              \
   else                                                          \
     {                                                           \
       yyerror (]b4_yyerror_args[YY_("syntax error: cannot back up")); \
-      YYERROR;                                                 \
-    }                                                          \
-while (YYID (0))
+      YYERROR;                                                  \
+    }                                                           \
+while (0)
 
 /* Error token number */
-#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_yy_location_print_define[
-
-/* YYLEX -- calling `yylex' with the right arguments.  */
-#ifdef YYLEX_PARAM
-# define YYLEX yylex (]b4_pure_if([&yylval[]b4_locations_if([, &yylloc]), ])[YYLEX_PARAM)
-#else
-# define YYLEX ]b4_c_function_call([yylex], [int], b4_lex_param)[
-#endif
 
 /* Enable debugging if requested.  */
 #if ]b4_api_PREFIX[DEBUG
@@ -798,33 +679,35 @@ while (YYID (0))
 #  define YYFPRINTF fprintf
 # endif
 
-# 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");                                                  \
-    }                                                                    \
-} while (YYID (0))
-
-]b4_yy_symbol_print_generate([b4_c_function_def])[
+# define YYDPRINTF(Args)                        \
+do {                                            \
+  if (yydebug)                                  \
+    YYFPRINTF Args;                             \
+} while (0)
+
+]b4_yy_location_print_define[
+
+# 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 (0)
+
+]b4_yy_symbol_print_define[
 
 /*------------------------------------------------------------------.
 | yy_stack_print -- Print the state stack from its BOTTOM up to its |
 | TOP (included).                                                   |
 `------------------------------------------------------------------*/
 
-]b4_c_function_def([yy_stack_print], [static void],
-                  [[yytype_int16 *yybottom], [yybottom]],
-                  [[yytype_int16 *yytop],    [yytop]])[
+]b4_function_define([yy_stack_print], [static void],
+                   [[yytype_int16 *yybottom], [yybottom]],
+                   [[yytype_int16 *yytop],    [yytop]])[
 {
   YYFPRINTF (stderr, "Stack now");
   for (; yybottom <= yytop; yybottom++)
@@ -835,45 +718,47 @@ do {                                                                        \
   YYFPRINTF (stderr, "\n");
 }
 
-# define YY_STACK_PRINT(Bottom, Top)                           \
-do {                                                           \
-  if (yydebug)                                                 \
-    yy_stack_print ((Bottom), (Top));                          \
-} while (YYID (0))
+# define YY_STACK_PRINT(Bottom, Top)                            \
+do {                                                            \
+  if (yydebug)                                                  \
+    yy_stack_print ((Bottom), (Top));                           \
+} while (0)
 
 
 /*------------------------------------------------.
 | Report that the YYRULE is going to be reduced.  |
 `------------------------------------------------*/
 
-]b4_c_function_def([yy_reduce_print], [static void],
-                  [[YYSTYPE *yyvsp], [yyvsp]],
+]b4_function_define([yy_reduce_print], [static void],
+                   [[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[); \
-} while (YYID (0))
+# define YY_REDUCE_PRINT(Rule)          \
+do {                                    \
+  if (yydebug)                          \
+    yy_reduce_print (yyssp, yyvsp, ]b4_locations_if([yylsp, ])[Rule]b4_user_args[); \
+} while (0)
 
 /* Nonzero means print parse trace.  It is left uninitialized so that
    multiple parsers can coexist.  */
@@ -887,7 +772,7 @@ int yydebug;
 
 
 /* YYINITDEPTH -- initial size of the parser's stacks.  */
-#ifndef        YYINITDEPTH
+#ifndef YYINITDEPTH
 # define YYINITDEPTH ]b4_stack_depth_init[
 #endif
 
@@ -1007,7 +892,7 @@ do {                                                             \
           goto yyerrlab;                                         \
       }                                                          \
     }                                                            \
-} while (YYID (0))
+} while (0)
 
 /* Discard any previous initial lookahead context because of Event,
    which may be a lookahead change or an invalidation of the currently
@@ -1030,7 +915,7 @@ do {                                                                     \
                    Event "\n");                                          \
       yy_lac_established = 0;                                            \
     }                                                                    \
-} while (YYID (0))
+} while (0)
 #else
 # define YY_LAC_DISCARD(Event) yy_lac_established = 0
 #endif
@@ -1146,7 +1031,7 @@ yy_lac (yytype_int16 *yyesa, yytype_int16 **yyes,
 #   define yystrlen strlen
 #  else
 /* Return the length of YYSTR.  */
-]b4_c_function_def([yystrlen], [static YYSIZE_T],
+]b4_function_define([yystrlen], [static YYSIZE_T],
    [[const char *yystr], [yystr]])[
 {
   YYSIZE_T yylen;
@@ -1163,7 +1048,7 @@ yy_lac (yytype_int16 *yyesa, yytype_int16 **yyes,
 #  else
 /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
    YYDEST.  */
-]b4_c_function_def([yystpcpy], [static char *],
+]b4_function_define([yystpcpy], [static char *],
    [[char *yydest], [yydest]], [[const char *yysrc], [yysrc]])[
 {
   char *yyd = yydest;
@@ -1194,27 +1079,27 @@ yytnamerr (char *yyres, const char *yystr)
       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: ;
     }
 
@@ -1252,10 +1137,6 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
   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
@@ -1390,7 +1271,7 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
 }
 #endif /* YYERROR_VERBOSE */
 
-]b4_yydestruct_generate([b4_c_function_def])[
+]b4_yydestruct_define[
 
 ]b4_pure_if([], [
 
@@ -1405,13 +1286,13 @@ struct yypstate
 
 static char yypstate_allocated = 0;]])b4_pull_if([
 
-b4_c_function_def([[yyparse]], [[int]], b4_parse_param)[
+b4_function_define([[yyparse]], [[int]], b4_parse_param)[
 {
   return yypull_parse (YY_NULL]m4_ifset([b4_parse_param],
-                                  [[, ]b4_c_args(b4_parse_param)])[);
+                                  [[, ]b4_args(b4_parse_param)])[);
 }
 
-]b4_c_function_def([[yypull_parse]], [[int]],
+]b4_function_define([[yypull_parse]], [[int]],
   [[[yypstate *yyps]], [[yyps]]]m4_ifset([b4_parse_param], [,
   b4_parse_param]))[
 {
@@ -1435,9 +1316,9 @@ b4_c_function_def([[yyparse]], [[int]], b4_parse_param)[
         }
     }
   do {
-    yychar = YYLEX;
+    yychar = ]b4_lex[;
     yystatus =
-      yypush_parse (yyps_local]b4_pure_if([[, yychar, &yylval]b4_locations_if([[, &yylloc]])])m4_ifset([b4_parse_param], [, b4_c_args(b4_parse_param)])[);
+      yypush_parse (yyps_local]b4_pure_if([[, yychar, &yylval]b4_locations_if([[, &yylloc]])])m4_ifset([b4_parse_param], [, b4_args(b4_parse_param)])[);
   } while (yystatus == YYPUSH_MORE);
   if (!yyps)
     yypstate_delete (yyps_local);
@@ -1445,7 +1326,7 @@ b4_c_function_def([[yyparse]], [[int]], b4_parse_param)[
 }]])[
 
 /* Initialize the parser data structure.  */
-]b4_c_function_def([[yypstate_new]], [[yypstate *]])[
+]b4_function_define([[yypstate_new]], [[yypstate *]])[
 {
   yypstate *yyps;]b4_pure_if([], [[
   if (yypstate_allocated)
@@ -1458,7 +1339,7 @@ b4_c_function_def([[yyparse]], [[int]], b4_parse_param)[
   return yyps;
 }
 
-]b4_c_function_def([[yypstate_delete]], [[void]],
+]b4_function_define([[yypstate_delete]], [[void]],
                    [[[yypstate *yyps]], [[yyps]]])[
 {
 #ifndef yyoverflow
@@ -1496,7 +1377,7 @@ b4_c_function_def([[yyparse]], [[int]], b4_parse_param)[
 | yypush_parse.  |
 `---------------*/
 
-]b4_c_function_def([[yypush_parse]], [[int]],
+]b4_function_define([[yypush_parse]], [[int]],
   [[[yypstate *yyps]], [[yyps]]]b4_pure_if([,
   [[[int yypushed_char]], [[yypushed_char]]],
   [[[YYSTYPE const *yypushed_val]], [[yypushed_val]]]b4_locations_if([,
@@ -1508,12 +1389,7 @@ b4_c_function_def([[yyparse]], [[int]], b4_parse_param)[
 | yyparse.  |
 `----------*/
 
-#ifdef YYPARSE_PARAM
-]b4_c_function_def([yyparse], [int],
-                   [[void *YYPARSE_PARAM], [YYPARSE_PARAM]])[
-#else /* ! YYPARSE_PARAM */
-]b4_c_function_def([yyparse], [int], b4_parse_param)[
-#endif]])[
+]b4_function_define([yyparse], [int], b4_parse_param)])[
 {]b4_pure_if([b4_declare_scanner_communication_variables
 ])b4_push_if([b4_pure_if([], [[
   int yypushed_char = yychar;
@@ -1597,26 +1473,26 @@ b4_locations_if([[  yylsp[0] = ]b4_push_if([b4_pure_if([*])yypushed_loc], [yyllo
 
 #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
@@ -1624,23 +1500,23 @@ b4_locations_if([[  yylsp[0] = ]b4_push_if([b4_pure_if([*])yypushed_loc], [yyllo
 # 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 */
@@ -1650,10 +1526,10 @@ b4_locations_if([[  yylsp[0] = ]b4_push_if([b4_pure_if([*])yypushed_loc], [yyllo
       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));
@@ -1701,7 +1577,7 @@ yyread_pushed_token:]])[
         yylval = *yypushed_val;]b4_locations_if([[
       if (yypushed_loc)
         yylloc = *yypushed_loc;]])])], [[
-      yychar = YYLEX;]])[
+      yychar = ]b4_lex[;]])[
     }
 
   if (yychar <= YYEOF)
@@ -1772,7 +1648,7 @@ yyreduce:
   yylen = yyr2[yyn];
 
   /* If YYLEN is nonzero, implement the default value of the action:
-     `$$ = $1'.
+     '$$ = $1'.
 
      Otherwise, the following line sets YYVAL to garbage.
      This behavior is undocumented and Bison
@@ -1820,7 +1696,7 @@ yyreduce:
   *++yyvsp = yyval;]b4_locations_if([
   *++yylsp = yyloc;])[
 
-  /* Now `shift' the result of the reduction.  Determine what state
+  /* Now 'shift' the result of the reduction.  Determine what state
      that goes to, based on the state we popped back to and the rule
      number reduced by.  */
 
@@ -1835,9 +1711,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.  */
@@ -1891,20 +1767,20 @@ yyerrlab:
   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
@@ -1924,7 +1800,7 @@ yyerrorlab:
      goto yyerrorlab;
 
 ]b4_locations_if([[  yyerror_range[1] = yylsp[1-yylen];
-]])[  /* Do not reclaim the symbols of the rule which action triggered
+]])[  /* Do not reclaim the symbols of the rule whose action triggered
      this YYERROR.  */
   YYPOPSTACK (yylen);
   yylen = 0;
@@ -1937,29 +1813,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);
@@ -2019,14 +1895,14 @@ yyreturn:
       yydestruct ("Cleanup: discarding lookahead",
                   yytoken, &yylval]b4_locations_if([, &yylloc])[]b4_user_args[);
     }
-  /* Do not reclaim the symbols of the rule which action triggered
+  /* Do not reclaim the symbols of the rule whose action triggered
      this YYABORT or YYACCEPT.  */
   YYPOPSTACK (yylen);
   YY_STACK_PRINT (yyss, yyssp);
   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
@@ -2042,19 +1918,15 @@ yypushreturn:]])[
   if (yymsg != yymsgbuf)
     YYSTACK_FREE (yymsg);
 #endif
-  /* Make sure YYID is used.  */
-  return YYID (yyresult);
+  return yyresult;
 }
-
-
 ]b4_epilogue[]dnl
 b4_output_end()
 
 b4_defines_if(
 [b4_output_begin([b4_spec_defines_file])[
-]b4_copyright([Bison interface for Yacc-like parsers in C],
-              [1984, 1989-1990, 2000-2013])[
+]b4_copyright([Bison interface for Yacc-like parsers in C])[
 
 ]b4_shared_declarations[
 ]b4_output_end()
-])
+])# b4_defines_if
diff --git a/djgpp/local.mk b/djgpp/local.mk
new file mode 100644 (file)
index 0000000..f42d9c9
--- /dev/null
@@ -0,0 +1,27 @@
+## Copyright (C) 2008-2013 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/>.
+
+EXTRA_DIST +=                                  \
+  djgpp/Makefile.maint                         \
+  djgpp/README.in                              \
+  djgpp/config.bat                             \
+  djgpp/config.sed                             \
+  djgpp/config.site                            \
+  djgpp/config_h.sed                           \
+  djgpp/djunpack.bat                           \
+  djgpp/fnchange.lst                           \
+  djgpp/subpipe.c                              \
+  djgpp/subpipe.h                              \
+  djgpp/testsuite.sed
index 0fb0cca860e709a93f047e372d1cb5a4a7a76ca2..8abfdb94108eeea5de3bab8f5c3bc8c4d53120d5 100644 (file)
@@ -1,13 +1,12 @@
 /*~
 /.dirstamp
-/Makefile
-/Makefile.in
 /bison.1
 /bison.aux
 /bison.cp
 /bison.cps
 /bison.dvi
 /bison.fn
+/bison.help
 /bison.html
 /bison.info
 /bison.ky
index e36a1cee0875571aab8740679246321f71236f5d..6662644956ce1c6f7f79245d8273c89b746be888 100644 (file)
@@ -1,21 +1,30 @@
-# Doxyfile 1.3.4               -*- Makefile -*-
+# Doxyfile 1.8.3
 
 # This file describes the settings to be used by the documentation system
-# doxygen (www.doxygen.org) for a project
+# doxygen (www.doxygen.org) for a project.
 #
-# All text after a hash (#) is considered a comment and will be ignored
+# All text after a hash (#) is considered a comment and will be ignored.
 # The format is:
 #       TAG = value [value, ...]
 # For lists items can also be appended using:
 #       TAG += value [value, ...]
-# Values that contain spaces should be placed between quotes (" ")
+# Values that contain spaces should be placed between quotes (" ").
 
 #---------------------------------------------------------------------------
 # Project related configuration options
 #---------------------------------------------------------------------------
 
-# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
-# by quotes) that should identify the project.
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING      = UTF-8
+
+# The PROJECT_NAME tag is a single word (or sequence of words) that should
+# identify the project. Note that if you do not use Doxywizard you need
+# to put quotes around the project name if it contains spaces.
 
 PROJECT_NAME           = "@PACKAGE_NAME@"
 
@@ -25,34 +34,49 @@ PROJECT_NAME           = "@PACKAGE_NAME@"
 
 PROJECT_NUMBER         = "@PACKAGE_VERSION@"
 
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer
+# a quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF = "Generate a deterministic LR or generalized LR (GLR) \
+parser employing LALR(1), IELR(1), or canonical LR(1) parser tables."
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is
+# included in the documentation. The maximum height of the logo should not
+# exceed 55 pixels and the maximum width should not exceed 200 pixels.
+# Doxygen will copy the logo to the output directory.
+
+PROJECT_LOGO           =
+
 # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
 # base path where the generated documentation will be put.
 # If a relative path is entered, it will be relative to the location
 # where doxygen was started. If left blank the current directory will be used.
 
-OUTPUT_DIRECTORY       = .
+OUTPUT_DIRECTORY       = @top_builddir@/doc
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS         = NO
 
 # The OUTPUT_LANGUAGE tag is used to specify the language in which all
 # documentation generated by doxygen is written. Doxygen will use this
 # information to generate all constant output in the proper language.
 # The default language is English, other supported languages are:
-# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch,
-# Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en
-# (Japanese with English messages), Korean, Norwegian, Polish, Portuguese,
-# Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian.
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
+# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
+# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak,
+# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
 
 OUTPUT_LANGUAGE        = English
 
-# This tag can be used to specify the encoding used in the generated output.
-# The encoding is not always determined by the language that is chosen,
-# but also whether or not the output is meant for Windows or non-Windows users.
-# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES
-# forces the Windows encoding (this is the default for the Windows binary),
-# whereas setting the tag to NO uses a Unix-style encoding (the default for
-# all platforms other than Windows).
-
-USE_WINDOWS_ENCODING   = NO
-
 # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
 # include brief member descriptions after the members that are listed in
 # the file and class documentation (similar to JavaDoc).
@@ -67,16 +91,28 @@ BRIEF_MEMBER_DESC      = YES
 
 REPEAT_BRIEF           = YES
 
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF       =
+
 # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
 # Doxygen will generate a detailed section even if there is only a brief
 # description.
 
 ALWAYS_DETAILED_SEC    = YES
 
-# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited
-# members of a class in the documentation of that class as if those members were
-# ordinary class members. Constructors, destructors and assignment operators of
-# the base classes will not be shown.
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
 
 INLINE_INHERITED_MEMB  = YES
 
@@ -89,12 +125,25 @@ FULL_PATH_NAMES        = NO
 # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
 # can be used to strip a user-defined part of the path. Stripping is
 # only done if one of the specified strings matches the left-hand part of
-# the path. It is allowed to use relative paths in the argument list.
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip. Note that you specify absolute paths here, but also
+# relative paths, which will be relative from the directory where doxygen is
+# started.
 
 STRIP_FROM_PATH        =
 
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH    =
+
 # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
-# (but less readable) file names. This can be useful is your file systems
+# (but less readable) file names. This can be useful if your file system
 # doesn't support long names like on DOS, Mac, or CD-ROM.
 
 SHORT_NAMES            = NO
@@ -102,11 +151,19 @@ SHORT_NAMES            = NO
 # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
 # will interpret the first line (until the first dot) of a JavaDoc-style
 # comment as the brief description. If set to NO, the JavaDoc
-# comments will behave just like the Qt-style comments (thus requiring an
-# explict @brief command for a brief description.
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
 
 JAVADOC_AUTOBRIEF      = NO
 
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF           = NO
+
 # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
 # treat a multi-line C++ special comment block (i.e. a block of //! or ///
 # comments) as a brief description. This used to be the default behaviour.
@@ -115,25 +172,17 @@ JAVADOC_AUTOBRIEF      = NO
 
 MULTILINE_CPP_IS_BRIEF = NO
 
-# If the DETAILS_AT_TOP tag is set to YES then Doxygen
-# will output the detailed description near the top, like JavaDoc.
-# If set to NO, the detailed description appears after the member
-# documentation.
-
-DETAILS_AT_TOP         = NO
-
 # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
 # member inherits the documentation from any documented member that it
-# reimplements.
+# re-implements.
 
 INHERIT_DOCS           = YES
 
-# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
-# tag is set to YES, then doxygen will reuse the documentation of the first
-# member in the group (if any) for the other members of the group. By default
-# all members of a group must be documented explicitly.
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
 
-DISTRIBUTE_GROUP_DOC   = NO
+SEPARATE_MEMBER_PAGES  = NO
 
 # The TAB_SIZE tag can be used to set the number of spaces in a tab.
 # Doxygen uses this value to replace tabs by spaces in code fragments.
@@ -149,20 +198,104 @@ TAB_SIZE               = 8
 
 ALIASES                =
 
-# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
-# only. Doxygen will then generate output that is more tailored for C.
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding
+# "class=itcl::class" will allow you to use the command class in the
+# itcl::class meaning.
+
+TCL_SUBST              =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
 # For instance, some of the names that are used will be different. The list
 # of all members will be omitted, etc.
 
 OPTIMIZE_OUTPUT_FOR_C  = NO
 
-# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources
-# only. Doxygen will then generate output that is more tailored for Java.
-# For instance, namespaces will be presented as packages, qualified scopes
-# will look different, etc.
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for
+# Java. For instance, namespaces will be presented as packages, qualified
+# scopes will look different, etc.
 
 OPTIMIZE_OUTPUT_JAVA   = NO
 
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources only. Doxygen will then generate output that is more tailored for
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN   = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL   = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension,
+# and language is one of the parsers supported by doxygen: IDL, Java,
+# Javascript, CSharp, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL, C,
+# C++. For instance to make doxygen treat .inc files as Fortran files (default
+# is PHP), and .f files as C (default is Fortran), use: inc=Fortran f=C. Note
+# that for custom extensions you also need to set FILE_PATTERNS otherwise the
+# files are not read by doxygen.
+
+EXTENSION_MAPPING      =
+
+# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all
+# comments according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you
+# can mix doxygen, HTML, and XML commands with Markdown formatting.
+# Disable only in case of backward compatibilities issues.
+
+MARKDOWN_SUPPORT       = YES
+
+# When enabled doxygen tries to link words that correspond to documented classes,
+# or namespaces to their corresponding documentation. Such a link can be
+# prevented in individual cases by by putting a % sign in front of the word or
+# globally by setting AUTOLINK_SUPPORT to NO.
+
+AUTOLINK_SUPPORT       = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also makes the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT    = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT        = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
+# Doxygen will parse them like normal C++ but will assume all classes use public
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT            = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES (the
+# default) will make doxygen replace the get and set methods by a property in
+# the documentation. This will only work if the methods are indeed getting or
+# setting a simple type. If this is not the case, or you want to show the
+# methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT   = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
 # Set the SUBGROUPING tag to YES (the default) to allow class member groups of
 # the same type (for instance a group of public functions) to be put as a
 # subgroup of that type (e.g. under the Public Functions section). Set it to
@@ -171,6 +304,59 @@ OPTIMIZE_OUTPUT_JAVA   = NO
 
 SUBGROUPING            = YES
 
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and
+# unions are shown inside the group in which they are included (e.g. using
+# @ingroup) instead of on a separate page (for HTML and Man pages) or
+# section (for LaTeX and RTF).
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and
+# unions with only public data fields will be shown inline in the documentation
+# of the scope in which they are defined (i.e. file, namespace, or group
+# documentation), provided this scope is documented. If set to NO (the default),
+# structs, classes, and unions are shown on a separate page (for HTML and Man
+# pages) or section (for LaTeX and RTF).
+
+INLINE_SIMPLE_STRUCTS  = NO
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
+# is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically
+# be useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT   = NO
+
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
+# determine which symbols to keep in memory and which to flush to disk.
+# When the cache is full, less often used symbols will be written to disk.
+# For small to medium size projects (<1000 input files) the default value is
+# probably good enough. For larger projects a too small cache size can cause
+# doxygen to be busy swapping symbols to and from disk most of the time
+# causing a significant performance penalty.
+# If the system has enough physical memory increasing the cache will improve the
+# performance by keeping more symbols in memory. Note that the value works on
+# a logarithmic scale so increasing the size by one will roughly double the
+# memory usage. The cache size is given by this formula:
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols.
+
+SYMBOL_CACHE_SIZE      = 0
+
+# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be
+# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given
+# their name and scope. Since this can be an expensive process and often the
+# same symbol appear multiple times in the code, doxygen keeps a cache of
+# pre-resolved symbols. If the cache is too small doxygen will become slower.
+# If the cache is too large, memory is wasted. The cache size is given by this
+# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols.
+
+LOOKUP_CACHE_SIZE      = 0
+
 #---------------------------------------------------------------------------
 # Build related configuration options
 #---------------------------------------------------------------------------
@@ -187,6 +373,11 @@ EXTRACT_ALL            = YES
 
 EXTRACT_PRIVATE        = YES
 
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# scope will be included in the documentation.
+
+EXTRACT_PACKAGE        = NO
+
 # If the EXTRACT_STATIC tag is set to YES all static members of a file
 # will be included in the documentation.
 
@@ -198,6 +389,21 @@ EXTRACT_STATIC         = YES
 
 EXTRACT_LOCAL_CLASSES  = YES
 
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base
+# name of the file that contains the anonymous namespace. By default
+# anonymous namespaces are hidden.
+
+EXTRACT_ANON_NSPACES   = NO
+
 # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
 # undocumented members of documented classes, files or namespaces.
 # If set to NO (the default) these members will be included in the
@@ -238,7 +444,7 @@ INTERNAL_DOCS          = NO
 # file names in lower-case letters. If set to YES upper-case letters are also
 # allowed. This is useful if you have classes or files whose names only differ
 # in case and if your file system supports case sensitive file names. Windows
-# users are advised to set this option to NO.
+# and Mac users are advised to set this option to NO.
 
 CASE_SENSE_NAMES       = YES
 
@@ -254,6 +460,12 @@ HIDE_SCOPE_NAMES       = NO
 
 SHOW_INCLUDE_FILES     = YES
 
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen
+# will list include files with double quotes in the documentation
+# rather than with sharp brackets.
+
+FORCE_LOCAL_INCLUDES   = NO
+
 # If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
 # is inserted in the documentation for inline members.
 
@@ -266,6 +478,48 @@ INLINE_INFO            = YES
 
 SORT_MEMBER_DOCS       = YES
 
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen
+# will sort the (brief and detailed) documentation of class members so that
+# constructors and destructors are listed first. If set to NO (the default)
+# the constructors will appear in the respective orders defined by
+# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS.
+# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO
+# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
+# hierarchy of group names into alphabetical order. If set to NO (the default)
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES       = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to
+# do proper type resolution of all parameters of a function it will reject a
+# match between the prototype and the implementation of a member function even
+# if there is only one candidate or it is obvious which candidate to choose
+# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen
+# will still accept a match between prototype and implementation in such cases.
+
+STRICT_PROTO_MATCHING  = NO
+
 # The GENERATE_TODOLIST tag can be used to enable (YES) or
 # disable (NO) the todo list. This list is created by putting \todo
 # commands in the documentation.
@@ -291,15 +545,16 @@ GENERATE_BUGLIST       = YES
 GENERATE_DEPRECATEDLIST= YES
 
 # The ENABLED_SECTIONS tag can be used to enable conditional
-# documentation sections, marked by \if sectionname ... \endif.
+# documentation sections, marked by \if section-label ... \endif
+# and \cond section-label ... \endcond blocks.
 
 ENABLED_SECTIONS       =
 
 # The MAX_INITIALIZER_LINES tag determines the maximum number of lines
-# the initial value of a variable or define consists of for it to appear in
+# the initial value of a variable or macro consists of for it to appear in
 # the documentation. If the initializer consists of more lines than specified
 # here it will be hidden. Use a value of 0 to hide initializers completely.
-# The appearance of the initializer of individual variables and defines in the
+# The appearance of the initializer of individual variables and macros in the
 # documentation can be controlled using \showinitializer or \hideinitializer
 # command in the documentation regardless of this setting.
 
@@ -311,6 +566,49 @@ MAX_INITIALIZER_LINES  = 30
 
 SHOW_USED_FILES        = YES
 
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
+# This will remove the Files entry from the Quick Index and from the
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES             = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
+# Namespaces page.
+# This will remove the Namespaces entry from the Quick Index
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES        = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER    =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option.
+# You can optionally specify a file name after the option, if omitted
+# DoxygenLayout.xml will be used as the name of the layout file.
+
+LAYOUT_FILE            =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files
+# containing the references data. This must be a list of .bib files. The
+# .bib extension is automatically appended if omitted. Using this command
+# requires the bibtex tool to be installed. See also
+# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style
+# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this
+# feature you need bibtex and perl available in the search path. Do not use
+# file names with spaces, bibtex cannot handle them.
+
+CITE_BIB_FILES         =
+
 #---------------------------------------------------------------------------
 # configuration options related to warning and progress messages
 #---------------------------------------------------------------------------
@@ -339,10 +637,20 @@ WARN_IF_UNDOCUMENTED   = YES
 
 WARN_IF_DOC_ERROR      = YES
 
+# The WARN_NO_PARAMDOC option can be enabled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC       = NO
+
 # The WARN_FORMAT tag determines the format of the warning messages that
 # doxygen can produce. The string should contain the $file, $line, and $text
 # tags, which will be replaced by the file and line number from which the
-# warning originated and the warning text.
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
 
 WARN_FORMAT            = "$file:$line: $text"
 
@@ -362,19 +670,28 @@ WARN_LOGFILE           =
 # with spaces.
 
 INPUT                  = @top_srcdir@/src \
-                        @top_builddir@/src
+                         @top_builddir@/src
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+# also the default input encoding. Doxygen uses libiconv (or the iconv built
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
+# the list of possible encodings.
+
+INPUT_ENCODING         = UTF-8
 
 # If the value of the INPUT tag contains directories, you can use the
 # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
 # and *.h) to filter out the source-files in the directories. If left
 # blank the following patterns are tested:
-# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp
-# *.h++ *.idl *.odl *.cs *.php *.php3 *.inc
+# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh
+# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py
+# *.f90 *.f *.for *.vhd *.vhdl
 
 FILE_PATTERNS          = *.c \
                          *.h \
-                        *.l \
-                        *.y
+                         *.l \
+                         *.y
 
 # The RECURSIVE tag can be used to turn specify whether or not subdirectories
 # should be searched for input files as well. Possible values are YES and NO.
@@ -382,26 +699,38 @@ FILE_PATTERNS          = *.c \
 
 RECURSIVE              = YES
 
-# The EXCLUDE tag can be used to specify files and/or directories that should
+# The EXCLUDE tag can be used to specify files and/or directories that should be
 # excluded from the INPUT source files. This way you can easily exclude a
 # subdirectory from a directory tree whose root is specified with the INPUT tag.
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
 
-EXCLUDE                = @top_srcdir@/src/scan-gram.c \
-                        @top_srcdir@/src/scan-skel.c \
-                        @top_builddir@/src/parse-*.[ch]
+EXCLUDE                = @top_builddir@/src/scan-gram.c \
+                         @top_builddir@/src/scan-skel.c \
+                         @top_srcdir@/src/parse-*.[ch]
 
-# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
-# directories that are symbolic links (a Unix file system feature) are
-# excluded from the input.
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
 
 EXCLUDE_SYMLINKS       = YES
 
 # If the value of the INPUT tag contains directories, you can use the
 # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
-# certain files from those directories.
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
 
 EXCLUDE_PATTERNS       =
 
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS        =
+
 # The EXAMPLE_PATH tag can be used to specify one or more files or
 # directories that contain example code fragments that are included (see
 # the \include command).
@@ -434,21 +763,51 @@ IMAGE_PATH             =
 # is the value of the INPUT_FILTER tag, and <input-file> is the name of an
 # input file. Doxygen will then use the output that the filter program writes
 # to standard output.
+# If FILTER_PATTERNS is specified, this tag will be
+# ignored.
 
 INPUT_FILTER           =
 
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis.
+# Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match.
+# The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty or if
+# non of the patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS        =
+
 # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
 # INPUT_FILTER) will be used to filter the input files when producing source
 # files to browse (i.e. when SOURCE_BROWSER is set to YES).
 
 FILTER_SOURCE_FILES    = NO
 
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any)
+# and it is also possible to disable source filtering for a specific pattern
+# using *.ext= (so without naming a filter). This option only has effect when
+# FILTER_SOURCE_FILES is enabled.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MD_FILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page (index.html).
+# This can be useful if you have a project on for instance GitHub and want reuse
+# the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
 #---------------------------------------------------------------------------
 # configuration options related to source browsing
 #---------------------------------------------------------------------------
 
 # If the SOURCE_BROWSER tag is set to YES then a list of source files will
 # be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
 
 SOURCE_BROWSER         = NO
 
@@ -459,22 +818,38 @@ INLINE_SOURCES         = NO
 
 # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
 # doxygen to hide any special comment blocks from generated source code
-# fragments. Normal C and C++ comments will always remain visible.
+# fragments. Normal C, C++ and Fortran comments will always remain visible.
 
 STRIP_CODE_COMMENTS    = YES
 
-# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# If the REFERENCED_BY_RELATION tag is set to YES
 # then for each documented function all documented
 # functions referencing it will be listed.
 
 REFERENCED_BY_RELATION = YES
 
-# If the REFERENCES_RELATION tag is set to YES (the default)
+# If the REFERENCES_RELATION tag is set to YES
 # then for each documented function all documented entities
 # called/used by that function will be listed.
 
 REFERENCES_RELATION    = YES
 
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code.
+# Otherwise they will link to the documentation.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS              = NO
+
 # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
 # will generate a verbatim copy of the header file for each class for
 # which an include is specified. Set to NO to disable this.
@@ -527,7 +902,14 @@ HTML_FILE_EXTENSION    = .html
 
 # The HTML_HEADER tag can be used to specify a personal HTML header for
 # each generated HTML page. If it is left blank doxygen will generate a
-# standard header.
+# standard header. Note that when using a custom header you are responsible
+#  for the proper inclusion of any scripts and style sheets that doxygen
+# needs, which is dependent on the configuration options used.
+# It is advised to generate a default header using "doxygen -w html
+# header.html footer.html stylesheet.css YourConfigFile" and then modify
+# that header. Note that the header is subject to change so you typically
+# have to redo this when upgrading to a newer version of doxygen or when
+# changing the value of configuration settings such as GENERATE_TREEVIEW!
 
 HTML_HEADER            =
 
@@ -539,20 +921,120 @@ HTML_FOOTER            =
 
 # The HTML_STYLESHEET tag can be used to specify a user-defined cascading
 # style sheet that is used by each HTML page. It can be used to
-# fine-tune the look of the HTML output. If the tag is left blank doxygen
-# will generate a default style sheet
+# fine-tune the look of the HTML output. If left blank doxygen will
+# generate a default style sheet. Note that it is recommended to use
+# HTML_EXTRA_STYLESHEET instead of this one, as it is more robust and this
+# tag will in the future become obsolete.
 
 HTML_STYLESHEET        =
 
-# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
-# files or namespaces will be aligned in HTML using tables. If set to
-# NO a bullet list will be used.
+# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional
+# user-defined cascading style sheet that is included after the standard
+# style sheets created by doxygen. Using this option one can overrule
+# certain style aspects. This is preferred over using HTML_STYLESHEET
+# since it does not replace the standard style sheet and is therefor more
+# robust against future updates. Doxygen will copy the style sheet file to
+# the output directory.
+
+HTML_EXTRA_STYLESHEET  =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that
+# the files will be copied as-is; there are no commands or markers available.
+
+HTML_EXTRA_FILES       =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
+# Doxygen will adjust the colors in the style sheet and background images
+# according to this color. Hue is specified as an angle on a colorwheel,
+# see http://en.wikipedia.org/wiki/Hue for more information.
+# For instance the value 0 represents red, 60 is yellow, 120 is green,
+# 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
+# The allowed range is 0 to 359.
+
+HTML_COLORSTYLE_HUE    = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of
+# the colors in the HTML output. For a value of 0 the output will use
+# grayscales only. A value of 255 will produce the most vivid colors.
+
+HTML_COLORSTYLE_SAT    = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to
+# the luminance component of the colors in the HTML output. Values below
+# 100 gradually make the output lighter, whereas values above 100 make
+# the output darker. The value divided by 100 is the actual gamma applied,
+# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2,
+# and 100 does not change the gamma.
+
+HTML_COLORSTYLE_GAMMA  = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting
+# this to NO can help when comparing the output of multiple runs.
+
+HTML_TIMESTAMP         = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+
+HTML_DYNAMIC_SECTIONS  = NO
 
-HTML_ALIGN_MEMBERS     = YES
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of
+# entries shown in the various tree structured indices initially; the user
+# can expand and collapse entries dynamically later on. Doxygen will expand
+# the tree to such a level that at most the specified number of entries are
+# visible (unless a fully collapsed tree already exceeds this amount).
+# So setting the number of entries 1 will produce a full collapsed tree by
+# default. 0 is a special value representing an infinite number of entries
+# and will result in a full expanded tree by default.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files
+# will be generated that can be used as input for Apple's Xcode 3
+# integrated development environment, introduced with OSX 10.5 (Leopard).
+# To create a documentation set, doxygen will generate a Makefile in the
+# HTML output directory. Running make will produce the docset in that
+# directory and running "make install" will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
+# it at startup.
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+
+GENERATE_DOCSET        = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
+# feed. A documentation feed provides an umbrella under which multiple
+# documentation sets from a single provider (such as a company or product suite)
+# can be grouped.
+
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
+# should uniquely identify the documentation set bundle. This should be a
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+
+# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely
+# identify the documentation publisher. This should be a reverse domain-name
+# style string, e.g. com.mycompany.MyDocSet.documentation.
+
+DOCSET_PUBLISHER_ID    = org.doxygen.Publisher
+
+# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
+
+DOCSET_PUBLISHER_NAME  = Publisher
 
 # If the GENERATE_HTMLHELP tag is set to YES, additional index files
 # will be generated that can be used as input for tools like the
-# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
 # of the generated HTML documentation.
 
 GENERATE_HTMLHELP      = NO
@@ -560,7 +1042,7 @@ GENERATE_HTMLHELP      = NO
 # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
 # be used to specify the file name of the resulting .chm file. You
 # can add a path in front of the file if the result should not be
-# written to the html output dir.
+# written to the html output directory.
 
 CHM_FILE               =
 
@@ -577,6 +1059,12 @@ HHC_LOCATION           =
 
 GENERATE_CHI           = NO
 
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
+# content.
+
+CHM_INDEX_ENCODING     =
+
 # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
 # controls whether a binary table of contents is generated (YES) or a
 # normal table of contents (NO) in the .chm file.
@@ -588,32 +1076,218 @@ BINARY_TOC             = NO
 
 TOC_EXPAND             = NO
 
-# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
-# top of each HTML page. The value NO (the default) enables the index and
-# the value YES disables it.
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated
+# that can be used as input for Qt's qhelpgenerator to generate a
+# Qt Compressed Help (.qch) of the generated HTML documentation.
 
-DISABLE_INDEX          = NO
+GENERATE_QHP           = NO
 
-# This tag can be used to set the number of enum values (range [1..20])
-# that doxygen will group on one line in the generated HTML documentation.
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
+# be used to specify the file name of the resulting .qch file.
+# The path specified is relative to the HTML output folder.
 
-ENUM_VALUES_PER_LINE   = 4
+QCH_FILE               =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#namespace
+
+QHP_NAMESPACE          = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+
+QHP_VIRTUAL_FOLDER     = doc
+
+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to
+# add. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#custom-filters
+
+QHP_CUST_FILTER_NAME   =
+
+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see
+# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">
+# Qt Help Project / Custom Filters</a>.
+
+QHP_CUST_FILTER_ATTRS  =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's
+# filter section matches.
+# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">
+# Qt Help Project / Filter Attributes</a>.
+
+QHP_SECT_FILTER_ATTRS  =
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
+# be used to specify the location of Qt's qhelpgenerator.
+# If non-empty doxygen will try to run qhelpgenerator on the generated
+# .qhp file.
+
+QHG_LOCATION           =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files
+#  will be generated, which together with the HTML files, form an Eclipse help
+# plugin. To install this plugin and make it available under the help contents
+# menu in Eclipse, the contents of the directory containing the HTML and XML
+# files needs to be copied into the plugins directory of eclipse. The name of
+# the directory within the plugins directory should be the same as
+# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before
+# the help appears.
 
-# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
-# generated containing a tree-like index structure (just like the one that
+GENERATE_ECLIPSEHELP   = NO
+
+# A unique identifier for the eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have
+# this name.
+
+ECLIPSE_DOC_ID         = org.doxygen.Project
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs)
+# at top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it. Since the tabs have the same information as the
+# navigation tree you can set this option to NO if you already set
+# GENERATE_TREEVIEW to YES.
+
+DISABLE_INDEX          = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information.
+# If the tag value is set to YES, a side panel will be generated
+# containing a tree-like index structure (just like the one that
 # is generated for HTML Help). For this to work a browser that supports
-# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
-# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
-# probably better off using the HTML help feature.
+# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
+# Windows users are probably better off using the HTML help feature.
+# Since the tree basically has the same information as the tab index you
+# could consider to set DISABLE_INDEX to NO when enabling this option.
 
 GENERATE_TREEVIEW      = YES
 
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values
+# (range [0,1..20]) that doxygen will group on one line in the generated HTML
+# documentation. Note that a value of 0 will completely suppress the enum
+# values from appearing in the overview section.
+
+ENUM_VALUES_PER_LINE   = 4
+
 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
 # used to set the initial width (in pixels) of the frame in which the tree
 # is shown.
 
 TREEVIEW_WIDTH         = 250
 
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open
+# links to external symbols imported via tag files in a separate window.
+
+EXT_LINKS_IN_WINDOW    = NO
+
+# Use this tag to change the font size of Latex formulas included
+# as images in the HTML documentation. The default is 10. Note that
+# when you change the font size after a successful doxygen run you need
+# to manually remove any form_*.png images from the HTML output directory
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE       = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are
+# not supported properly for IE 6.0, but are supported on all modern browsers.
+# Note that when changing this option you need to delete any form_*.png files
+# in the HTML output before the changes have effect.
+
+FORMULA_TRANSPARENT    = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax
+# (see http://www.mathjax.org) which uses client side Javascript for the
+# rendering instead of using prerendered bitmaps. Use this if you do not
+# have LaTeX installed or if you want to formulas look prettier in the HTML
+# output. When enabled you may also need to install MathJax separately and
+# configure the path to it using the MATHJAX_RELPATH option.
+
+USE_MATHJAX            = NO
+
+# When MathJax is enabled you can set the default output format to be used for
+# thA MathJax output. Supported types are HTML-CSS, NativeMML (i.e. MathML) and
+# SVG. The default value is HTML-CSS, which is slower, but has the best
+# compatibility.
+
+MATHJAX_FORMAT         = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the
+# HTML output directory using the MATHJAX_RELPATH option. The destination
+# directory should contain the MathJax.js script. For instance, if the mathjax
+# directory is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to
+# the MathJax Content Delivery Network so you can quickly see the result without
+# installing MathJax.
+# However, it is strongly recommended to install a local
+# copy of MathJax from http://www.mathjax.org before deployment.
+
+MATHJAX_RELPATH        = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension
+# names that should be enabled during MathJax rendering.
+
+MATHJAX_EXTENSIONS     =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box
+# for the HTML output. The underlying search engine uses javascript
+# and DHTML and should work on any modern browser. Note that when using
+# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets
+# (GENERATE_DOCSET) there is already a search function so this one should
+# typically be disabled. For large projects the javascript based search engine
+# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
+
+SEARCHENGINE           = NO
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using Javascript.
+# There are two flavours of web server based search depending on the
+# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for
+# searching and an index file used by the script. When EXTERNAL_SEARCH is
+# enabled the indexing and searching needs to be provided by external tools.
+# See the manual for details.
+
+SERVER_BASED_SEARCH    = NO
+
+# When EXTERNAL_SEARCH is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain
+# the search results. Doxygen ships with an example indexer (doxyindexer) and
+# search engine (doxysearch.cgi) which are based on the open source search engine
+# library Xapian. See the manual for configuration details.
+
+EXTERNAL_SEARCH        = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will returned the search results when EXTERNAL_SEARCH is enabled.
+# Doxygen ships with an example search engine (doxysearch) which is based on
+# the open source search engine library Xapian. See the manual for configuration
+# details.
+
+SEARCHENGINE_URL       =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+
+SEARCHDATA_FILE        = searchdata.xml
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through other
+# doxygen projects that are not otherwise connected via tags files, but are
+# all added to the same search index. Each project needs to have a tag file set
+# via GENERATE_TAGFILE. The search mapping then maps the name of the tag file
+# to a relative location where the documentation can be found,
+# similar to the
+# TAGFILES option but without actually processing the tag file.
+# The format is: EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+
+EXTRA_SEARCH_MAPPINGS  =
+
 #---------------------------------------------------------------------------
 # configuration options related to the LaTeX output
 #---------------------------------------------------------------------------
@@ -631,6 +1305,9 @@ LATEX_OUTPUT           = latex
 
 # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
 # invoked. If left blank `latex' will be used as the default command name.
+# Note that when enabling USE_PDFLATEX this option is only used for
+# generating bitmaps for formulas in the HTML output, but not in the
+# Makefile that is written to the output directory.
 
 LATEX_CMD_NAME         = latex
 
@@ -647,7 +1324,7 @@ MAKEINDEX_CMD_NAME     = makeindex
 COMPACT_LATEX          = NO
 
 # The PAPER_TYPE tag can be used to set the paper type that is used
-# by the printer. Possible values are: a4, a4wide, letter, legal and
+# by the printer. Possible values are: a4, letter, legal and
 # executive. If left blank a4wide will be used.
 
 PAPER_TYPE             = a4wide
@@ -664,6 +1341,13 @@ EXTRA_PACKAGES         =
 
 LATEX_HEADER           =
 
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for
+# the generated latex document. The footer should contain everything after
+# the last chapter. If it is left blank doxygen will generate a
+# standard footer. Notice: only use this tag if you know what you are doing!
+
+LATEX_FOOTER           =
+
 # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
 # is prepared for conversion to pdf (using ps2pdf). The pdf file will
 # contain links (just like the HTML output) instead of page references
@@ -690,12 +1374,25 @@ LATEX_BATCHMODE        = YES
 
 LATEX_HIDE_INDICES     = NO
 
+# If LATEX_SOURCE_CODE is set to YES then doxygen will include
+# source code with syntax highlighting in the LaTeX output.
+# Note that which sources are shown also depends on other settings
+# such as SOURCE_BROWSER.
+
+LATEX_SOURCE_CODE      = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See
+# http://en.wikipedia.org/wiki/BibTeX for more info.
+
+LATEX_BIB_STYLE        = plain
+
 #---------------------------------------------------------------------------
 # configuration options related to the RTF output
 #---------------------------------------------------------------------------
 
 # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
-# The RTF output is optimised for Word 97 and may not look very pretty with
+# The RTF output is optimized for Word 97 and may not look very pretty with
 # other RTF readers or editors.
 
 GENERATE_RTF           = NO
@@ -721,8 +1418,8 @@ COMPACT_RTF            = NO
 
 RTF_HYPERLINKS         = NO
 
-# Load stylesheet definitions from file. Syntax is similar to doxygen's
-# config file, i.e. a series of assigments. You only have to provide
+# Load style sheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
 # replacements, missing definitions are set to their default value.
 
 RTF_STYLESHEET_FILE    =
@@ -766,9 +1463,7 @@ MAN_LINKS              = NO
 
 # If the GENERATE_XML tag is set to YES Doxygen will
 # generate an XML file that captures the structure of
-# the code including all documentation. Note that this
-# feature is still experimental and incomplete at the
-# moment.
+# the code including all documentation.
 
 GENERATE_XML           = NO
 
@@ -790,6 +1485,13 @@ XML_SCHEMA             =
 
 XML_DTD                =
 
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING     = YES
+
 #---------------------------------------------------------------------------
 # configuration options for the AutoGen Definitions output
 #---------------------------------------------------------------------------
@@ -821,8 +1523,10 @@ GENERATE_PERLMOD       = NO
 PERLMOD_LATEX          = NO
 
 # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
-# nicely formatted so it can be parsed by a human reader.  This is useful
-# if you want to understand what is going on.  On the other hand, if this
+# nicely formatted so it can be parsed by a human reader.
+# This is useful
+# if you want to understand what is going on.
+# On the other hand, if this
 # tag is set to NO the size of the Perl module output will be much smaller
 # and Perl will parse it just the same.
 
@@ -854,12 +1558,12 @@ MACRO_EXPANSION        = NO
 
 # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
 # then the macro expansion is limited to the macros specified with the
-# PREDEFINED and EXPAND_AS_PREDEFINED tags.
+# PREDEFINED and EXPAND_AS_DEFINED tags.
 
 EXPAND_ONLY_PREDEF     = NO
 
 # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
-# in the INCLUDE_PATH (see below) will be search if a #include is found.
+# pointed to by INCLUDE_PATH will be searched when a #include is found.
 
 SEARCH_INCLUDES        = YES
 
@@ -867,7 +1571,9 @@ SEARCH_INCLUDES        = YES
 # contain include files that are not input files but should be processed by
 # the preprocessor.
 
-INCLUDE_PATH           =
+INCLUDE_PATH           = @top_srcdir@ \
+                         @top_srcdir@/lib \
+                         @top_builddir@/lib
 
 # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
 # patterns (like *.h and *.hpp) to filter out the header-files in the
@@ -880,43 +1586,43 @@ INCLUDE_FILE_PATTERNS  =
 # are defined before the preprocessor is started (similar to the -D option of
 # gcc). The argument of the tag is a list of macros of the form: name
 # or name=definition (no spaces). If the definition and the = are
-# omitted =1 is assumed.
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
 
 PREDEFINED             =
 
 # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
 # this tag can be used to specify a list of macro names that should be expanded.
 # The macro definition that is found in the sources will be used.
-# Use the PREDEFINED tag if you want to use a different macro definition.
+# Use the PREDEFINED tag if you want to use a different macro definition that
+# overrules the definition found in the source code.
 
 EXPAND_AS_DEFINED      =
 
 # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
-# doxygen's preprocessor will remove all function-like macros that are alone
-# on a line, have an all uppercase name, and do not end with a semicolon. Such
-# function macros are typically used for boiler-plate code, and will confuse the
-# parser if not removed.
+# doxygen's preprocessor will remove all references to function-like macros
+# that are alone on a line, have an all uppercase name, and do not end with a
+# semicolon, because these will confuse the parser if not removed.
 
 SKIP_FUNCTION_MACROS   = YES
 
 #---------------------------------------------------------------------------
-# Configuration::addtions related to external references
+# Configuration::additions related to external references
 #---------------------------------------------------------------------------
 
-# The TAGFILES option can be used to specify one or more tagfiles.
-# Optionally an initial location of the external documentation
-# can be added for each tagfile. The format of a tag file without
-# this location is as follows:
-#   TAGFILES = file1 file2 ...
+# The TAGFILES option can be used to specify one or more tagfiles. For each
+# tag file the location of the external documentation should be added. The
+# format of a tag file without this location is as follows:
+#
+# TAGFILES = file1 file2 ...
 # Adding location for the tag files is done as follows:
-#   TAGFILES = file1=loc1 "file2 = loc2" ...
-# where "loc1" and "loc2" can be relative or absolute paths or
-# URLs. If a location is present for each tag, the installdox tool
-# does not have to be run to correct the links.
-# Note that each tag file must have a unique name
-# (where the name does NOT include the path)
-# If a tag file is not located in the directory in which doxygen
-# is run, you must also specify the path to the tagfile here.
+#
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths
+# or URLs. Note that each tag file must have a unique name (where the name does
+# NOT include the path). If a tag file is not located in the directory in which
+# doxygen is run, you must also specify the path to the tagfile here.
 
 TAGFILES               =
 
@@ -947,13 +1653,22 @@ PERL_PATH              = @PERL@
 #---------------------------------------------------------------------------
 
 # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
-# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or
-# super classes. Setting the tag to NO turns the diagrams off. Note that this
-# option is superceded by the HAVE_DOT option below. This is only a fallback. It is
-# recommended to install and use dot, since it yields more powerful graphs.
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option also works with HAVE_DOT disabled, but it is recommended to
+# install and use dot, since it yields more powerful graphs.
 
 CLASS_DIAGRAMS         = YES
 
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH            =
+
 # If set to YES, the inheritance and collaboration graphs will hide
 # inheritance and usage relations if the target is undocumented
 # or is not a class.
@@ -967,10 +1682,38 @@ HIDE_UNDOC_RELATIONS   = YES
 
 HAVE_DOT               = YES
 
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is
+# allowed to run in parallel. When set to 0 (the default) doxygen will
+# base this on the number of processors available in the system. You can set it
+# explicitly to a value larger than 0 to get control over the balance
+# between CPU load and processing speed.
+
+DOT_NUM_THREADS        = 0
+
+# By default doxygen will use the Helvetica font for all dot files that
+# doxygen generates. When you want a differently looking font you can specify
+# the font name using DOT_FONTNAME. You need to make sure dot is able to find
+# the font, which can be done by putting it in a standard location or by setting
+# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the
+# directory containing the font.
+
+DOT_FONTNAME           = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
+# The default size is 10pt.
+
+DOT_FONTSIZE           = 10
+
+# By default doxygen will tell dot to use the Helvetica font.
+# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to
+# set the path where dot can find it.
+
+DOT_FONTPATH           =
+
 # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
 # will generate a graph for each documented class showing the direct and
 # indirect inheritance relations. Setting this tag to YES will force the
-# the CLASS_DIAGRAMS tag to NO.
+# CLASS_DIAGRAMS tag to NO.
 
 CLASS_GRAPH            = YES
 
@@ -981,12 +1724,26 @@ CLASS_GRAPH            = YES
 
 COLLABORATION_GRAPH    = YES
 
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS           = YES
+
 # If the UML_LOOK tag is set to YES doxygen will generate inheritance and
 # collaboration diagrams in a style similar to the OMG's Unified Modeling
 # Language.
 
 UML_LOOK               = NO
 
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside
+# the class node. If there are many fields or methods and many nodes the
+# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS
+# threshold limits the number of items for each type to make the size more
+# managable. Set this to 0 for no limit. Note that the threshold may be
+# exceeded by 50% before the limit is enforced.
+
+UML_LIMIT_NUM_FIELDS   = 10
+
 # If set to YES, the inheritance and collaboration graphs will show the
 # relations between templates and their instances.
 
@@ -1006,27 +1763,53 @@ INCLUDE_GRAPH          = YES
 
 INCLUDED_BY_GRAPH      = YES
 
-# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will
-# generate a call dependency graph for every global function or class method.
-# Note that enabling this option will significantly increase the time of a run.
-# So in most cases it will be better to enable call graphs for selected
-# functions only using the \callgraph command.
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then
+# doxygen will generate a call dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable call graphs
+# for selected functions only using the \callgraph command.
 
 CALL_GRAPH             = NO
 
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
+# doxygen will generate a caller dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable caller
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH           = NO
+
 # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
-# will graphical hierarchy of all classes instead of a textual one.
+# will generate a graphical hierarchy of all classes instead of a textual one.
 
 GRAPHICAL_HIERARCHY    = YES
 
+# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH        = YES
+
 # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
-# generated by dot. Possible values are png, jpg, or gif
-# If left blank png will be used.
+# generated by dot. Possible values are svg, png, jpg, or gif.
+# If left blank png will be used. If you choose svg you need to set
+# HTML_FILE_EXTENSION to xhtml in order to make the SVG files
+# visible in IE 9+ (other browsers do not have this requirement).
 
 DOT_IMAGE_FORMAT       = png
 
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+# Note that this requires a modern browser other than Internet Explorer.
+# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you
+# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files
+# visible. Older versions of IE do not have SVG support.
+
+INTERACTIVE_SVG        = NO
+
 # The tag DOT_PATH can be used to specify the path where the dot tool can be
-# found. If left blank, it is assumed the dot tool can be found on the path.
+# found. If left blank, it is assumed the dot tool can be found in the path.
 
 DOT_PATH               =
 
@@ -1036,35 +1819,47 @@ DOT_PATH               =
 
 DOTFILE_DIRS           =
 
-# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width
-# (in pixels) of the graphs generated by dot. If a graph becomes larger than
-# this value, doxygen will try to truncate the graph, so that it fits within
-# the specified constraint. Beware that most browsers cannot cope with very
-# large images.
-
-MAX_DOT_GRAPH_WIDTH    = 1024
-
-# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height
-# (in pixels) of the graphs generated by dot. If a graph becomes larger than
-# this value, doxygen will try to truncate the graph, so that it fits within
-# the specified constraint. Beware that most browsers cannot cope with very
-# large images.
-
-MAX_DOT_GRAPH_HEIGHT   = 1024
-
-# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of
-# the graphs generated by dot. A depth value of 3 means that only
-# nodes reachable from the root by following a path via at most 3
-# edges will be shown. Nodes that lay further from the root node will
-# be omitted. Note that setting this option to 1 or 2 may greatly
-# reduce the computation time needed for large code bases. Also note
-# that a graph may be further truncated if the graph's image
-# dimensions are not sufficient to fit the graph (see
-# MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT).  If 0 is used for the
-# depth value (the default), the graph is not depth-constrained.
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the
+# \mscfile command).
+
+MSCFILE_DIRS           =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the
+# number of direct children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES    = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
 
 MAX_DOT_GRAPH_DEPTH    = 0
 
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not
+# seem to support this out of the box. Warning: Depending on the platform used,
+# enabling this option may lead to badly anti-aliased labels on the edges of
+# a graph (i.e. they become hard to read).
+
+DOT_TRANSPARENT        = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS      = NO
+
 # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
 # generate a legend page explaining the meaning of the various boxes and
 # arrows in the dot generated graphs.
@@ -1076,12 +1871,3 @@ GENERATE_LEGEND        = YES
 # the various graphs.
 
 DOT_CLEANUP            = YES
-
-#---------------------------------------------------------------------------
-# Configuration::addtions related to the search engine
-#---------------------------------------------------------------------------
-
-# The SEARCHENGINE tag specifies whether or not a search engine should be
-# used. If set to NO the values of all tags below this one will be ignored.
-
-SEARCHENGINE           = NO
diff --git a/doc/Makefile.am b/doc/Makefile.am
deleted file mode 100644 (file)
index d364a9b..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-## Process this file with automake to produce Makefile.in -*-Makefile-*-
-
-## Copyright (C) 2001-2003, 2005-2013 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/>.
-
-AM_MAKEINFOFLAGS = --no-split
-info_TEXINFOS = bison.texi
-bison_TEXINFOS = $(srcdir)/cross-options.texi gpl-3.0.texi fdl.texi
-
-CLEANFILES = bison.fns
-CLEANDIRS = *.t2d
-clean-local:
-       rm -rf $(CLEANDIRS)
-
-CROSS_OPTIONS_PL = $(top_srcdir)/build-aux/cross-options.pl
-$(srcdir)/cross-options.texi: $(top_srcdir)/src/getargs.c $(CROSS_OPTIONS_PL)
-       $(AM_V_GEN)mv -f $@ $@~ || : >$@~
-       $(AM_V_at)rm -f $@.tmp
-       $(AM_V_at)cd $(top_builddir)/src && $(MAKE) $(AM_MAKEFLAGS) bison
-       $(AM_V_at)$(top_builddir)/src/bison --help \
-         | $(PERL) $(CROSS_OPTIONS_PL) $(top_srcdir)/src/scan-gram.l >$@.tmp
-       $(AM_V_at)diff -u $@~ $@.tmp || true
-       $(AM_V_at)mv $@.tmp $@
-MAINTAINERCLEANFILES = $(srcdir)/cross-options.texi
-
-## ---------- ##
-## Ref card.  ##
-## ---------- ##
-
-EXTRA_DIST = refcard.tex
-CLEANFILES += refcard.dvi refcard.log refcard.ps
-
-refcard.dvi: refcard.tex
-       $(AM_V_GEN)tex refcard.tex
-
-refcard.ps: refcard.dvi
-
-
-## ----------- ##
-## Man Pages.  ##
-## ----------- ##
-
-dist_man_MANS = $(srcdir)/bison.1
-
-EXTRA_DIST += $(dist_man_MANS:.1=.x) common.x
-MAINTAINERCLEANFILES += $(dist_man_MANS)
-
-# Depend on configure to get version number changes.
-common_dep = $(top_srcdir)/configure $(srcdir)/common.x
-srcsrcdir = $(top_srcdir)/bin
-$(srcdir)/bison.1:      $(common_dep) $(top_srcdir)/src/getargs.c
-
-# Differences to ignore when comparing the man page (the date).
-remove_time_stamp = \
-  sed 's/^\(\.TH[^"]*"[^"]*"[^"]*\)"[^"]*"/\1/'
-
-MOSTLYCLEANFILES = $(srcdir)/*.t
-
-SUFFIXES = .x .1
-
-PREPATH = $(top_builddir)/src
-.x.1:
-       $(AM_V_GEN)program=`expr "/$*" : '.*/\(.*\)'` &&                \
-       save_IFS=$IFS;                                                  \
-       IFS=$(PATH_SEPARATOR);                                          \
-       for dir in $(PREPATH); do                                       \
-         IFS=$save_IFS;                                                \
-         echo cd $$dir '&&' $(MAKE) $(AM_MAKEFLAGS) $$program &&       \
-         (cd $$dir && $(MAKE) $(AM_MAKEFLAGS) $$program) || exit;      \
-       done
-       $(AM_V_at)PATH="$(PREPATH)$(PATH_SEPARATOR)$$PATH";                  \
-       export PATH;                                                         \
-       $(HELP2MAN)                                                          \
-           --include=$*.x                                                   \
-           --include=$(srcdir)/common.x                                     \
-           --output=$@.t `echo '$*' | sed 's,.*/,,'`
-       $(AM_V_at)if $(remove_time_stamp) $@ >$@a.t 2>/dev/null &&           \
-          $(remove_time_stamp) $@.t | cmp $@a.t - >/dev/null 2>&1; then     \
-               touch $@;                                                    \
-       else                                                                 \
-               mv $@.t $@;                                                  \
-       fi
-       $(AM_V_at)rm -f $@*.t
-
-nodist_man_MANS = yacc.1
-
-## ------------------------------ ##
-## Graphviz examples generation.  ##
-## ------------------------------ ##
-
-CLEANDIRS += figs
-FIGS_DOT = figs/example.dot figs/example-reduce.dot figs/example-shift.dot
-EXTRA_DIST +=                                                          \
-  figs/example.y                                                       \
-  $(FIGS_DOT)                                                          \
-  $(FIGS_DOT:.dot=.eps) $(FIGS_DOT:.dot=.pdf) $(FIGS_DOT:.dot=.png)
-SUFFIXES += .dot .eps .pdf .png
-
-bison.dvi:  $(FIGS_DOT:.dot=.eps)
-bison.html: $(FIGS_DOT:.dot=.png)
-bison.pdf:  $(FIGS_DOT:.dot=.pdf)
-
-.dot.eps:
-       $(AM_V_GEN) $(MKDIR_P) `echo "./$@" | sed -e 's,/[^/]*$$,,'`
-       $(AM_V_at) $(DOT) -Gmargin=0 -Teps $< >$@.tmp
-       $(AM_V_at) mv $@.tmp $@
-
-.dot.pdf:
-       $(AM_V_GEN) $(MKDIR_P) `echo "./$@" | sed -e 's,/[^/]*$$,,'`
-       $(AM_V_at) $(DOT) -Gmargin=0 -Tpdf $< >$@.tmp
-       $(AM_V_at) mv $@.tmp $@
-
-.dot.png:
-       $(AM_V_GEN) $(MKDIR_P) `echo "./$@" | sed -e 's,/[^/]*$$,,'`
-       $(AM_V_at) $(DOT) -Gmargin=0 -Tpng $< >$@.tmp
-       $(AM_V_at) mv $@.tmp $@
-
-## -------------- ##
-## Doxygenation.  ##
-## -------------- ##
-
-DOXYGEN = doxygen
-
-.PHONY: doc html
-
-doc: html
-
-html-local: Doxyfile
-       $(DOXYGEN)
-
-edit = sed -e 's,@PACKAGE_NAME\@,$(PACKAGE_NAME),g' \
-          -e 's,@PACKAGE_VERSION\@,$(PACKAGE_VERSION),g' \
-          -e 's,@top_builddir\@,$(top_builddir),g' \
-          -e 's,@top_srcdir\@,$(top_srcdir),g'
-
-EXTRA_DIST += Doxyfile.in
-CLEANFILES += Doxyfile
-# Sed is used to generate Doxyfile from Doxyfile.in instead of
-# configure, because the former is way faster than the latter.
-Doxyfile: $(srcdir)/Doxyfile.in
-       $(AM_V_GEN)$(edit) $(srcdir)/Doxyfile.in >Doxyfile
-
-CLEANDIRS += html latex
index f4f3b8a6b534161b668bfe9c003603f8d51b0db1..250e94d8c74699655f5246b84c99d97cf718cef0 100644 (file)
@@ -135,7 +135,8 @@ Writing GLR Parsers
 
 * 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
@@ -162,9 +163,9 @@ Reverse Polish Notation Calculator
 
 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}
 
@@ -177,13 +178,14 @@ 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
 
 * Grammar Outline::    Overall layout of the grammar file.
 * Symbols::            Terminal and nonterminal symbols.
 * Rules::              How to write grammar rules.
-* Recursion::          Writing recursive rules.
 * Semantics::          Semantic values and actions.
 * Tracking Locations:: Locations and actions.
 * Named References::   Using named references in actions.
@@ -198,10 +200,20 @@ Outline of a Bison Grammar
 * Grammar Rules::         Syntax and usage of the grammar rules section.
 * Epilogue::              Syntax and usage of the epilogue.
 
+Grammar Rules
+
+* Rules Syntax::   Syntax of the rules.
+* Empty Rules::    Symbols that can match the empty string.
+* Recursion::      Writing recursive rules.
+
+
 Defining Language Semantics
 
 * Value Type::        Specifying one data type for all semantic values.
 * Multiple Types::    Specifying several alternative data types.
+* Type Generation::   Generating the semantic value type.
+* Union Decl::        Declaring the set of all semantic value types.
+* Structured Value Type::  Providing a structured semantic value type.
 * Actions::           An action is the semantic definition of a grammar rule.
 * Action Types::      Specifying data types for actions to operate on.
 * Mid-Rule Actions::  Most actions go at the end of a rule.
@@ -225,7 +237,6 @@ Bison Declarations
 * Require Decl::      Requiring a Bison version.
 * Token Decl::        Declaring terminal symbols.
 * Precedence Decl::   Declaring terminals with precedence and associativity.
-* Union Decl::        Declaring the set of all semantic value types.
 * Type Decl::         Declaring the choice of type for a nonterminal symbol.
 * Initial Action Decl::  Code run before parsing starts.
 * Destructor Decl::   Declaring how symbols are freed.
@@ -279,7 +290,8 @@ The Bison Parser Algorithm
 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.
 * Non Operators::     Using precedence for general conflicts.
@@ -779,7 +791,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
 
@@ -897,10 +910,7 @@ parses a vastly simplified form of Pascal type declarations.
 @end group
 
 %%
-
-@group
 type_decl: TYPE ID '=' type ';' ;
-@end group
 
 @group
 type:
@@ -1005,7 +1015,7 @@ Let's consider an example, vastly simplified from a C++ grammar.
 %%
 
 prog:
-  /* Nothing.  */
+  %empty
 | prog stmt   @{ printf ("\n"); @}
 ;
 
@@ -1147,6 +1157,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.
@@ -1180,6 +1194,7 @@ For example, if a semantic action might be deferred, you should never write it
 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}
@@ -1187,11 +1202,78 @@ 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.
+
+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.
 
-Also, see @ref{Location Default Action, ,Default Action for Locations}, which
-describes a special usage of @code{YYLLOC_DEFAULT} in GLR parsers.
+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
@@ -1460,16 +1542,20 @@ The source code for this calculator is named @file{rpcalc.y}.  The
 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.  */
 
+@group
 %@{
-  #define YYSTYPE double
+  #include <stdio.h>
   #include <math.h>
   int yylex (void);
   void yyerror (char const *);
 %@}
+@end group
 
+%define api.value.type @{double@}
 %token NUM
 
 %% /* Grammar rules and actions follow.  */
@@ -1478,14 +1564,6 @@ calculator.  As in C, comments are placed between @samp{/*@dots{}*/}.
 The declarations section (@pxref{Prologue, , The prologue}) contains two
 preprocessor directives and two forward declarations.
 
-The @code{#define} directive defines the macro @code{YYSTYPE}, thus
-specifying the C data type for semantic values of both tokens and
-groupings (@pxref{Value Type, ,Data Types of Semantic Values}).  The
-Bison parser will use whatever type @code{YYSTYPE} is defined as; if you
-don't define it, @code{int} is the default.  Because we specify
-@code{double}, each token and each expression has an associated value,
-which is a floating point number.
-
 The @code{#include} directive is used to declare the exponentiation
 function @code{pow}.
 
@@ -1495,24 +1573,35 @@ before they are used.  These functions will be defined in the
 epilogue, but the parser calls them so they must be declared in the
 prologue.
 
-The second section, Bison declarations, provides information to Bison
-about the token types (@pxref{Bison Declarations, ,The Bison
-Declarations Section}).  Each terminal symbol that is not a
-single-character literal must be declared here.  (Single-character
-literals normally don't need to be declared.)  In this example, all the
-arithmetic operators are designated by single-character literals, so the
-only terminal symbol that needs to be declared is @code{NUM}, the token
-type for numeric constants.
+The second section, Bison declarations, provides information to Bison about
+the tokens and their types (@pxref{Bison Declarations, ,The Bison
+Declarations Section}).
+
+The @code{%define} directive defines the variable @code{api.value.type},
+thus specifying the C data type for semantic values of both tokens and
+groupings (@pxref{Value Type, ,Data Types of Semantic Values}).  The Bison
+parser will use whatever type @code{api.value.type} is defined as; if you
+don't define it, @code{int} is the default.  Because we specify
+@samp{@{double@}}, each token and each expression has an associated value,
+which is a floating point number.  C code can use @code{YYSTYPE} to refer to
+the value @code{api.value.type}.
+
+Each terminal symbol that is not a single-character literal must be
+declared.  (Single-character literals normally don't need to be declared.)
+In this example, all the arithmetic operators are designated by
+single-character literals, so the only terminal symbol that needs to be
+declared is @code{NUM}, the token type for numeric constants.
 
 @node Rpcalc Rules
 @subsection Grammar Rules for @code{rpcalc}
 
 Here are the grammar rules for the reverse polish notation calculator.
 
+@comment file: rpcalc.y
 @example
 @group
 input:
-  /* empty */
+  %empty
 | input line
 ;
 @end group
@@ -1557,9 +1646,9 @@ main job of most actions.  The semantic values of the components of the
 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
@@ -1569,7 +1658,7 @@ Consider the definition of @code{input}:
 
 @example
 input:
-  /* empty */
+  %empty
 | input line
 ;
 @end example
@@ -1584,8 +1673,9 @@ The first alternative is empty because there are no symbols between the
 colon and the first @samp{|}; this means that @code{input} can match an
 empty string of input (no tokens).  We write the rules this way because it
 is legitimate to type @kbd{Ctrl-d} right after you start the calculator.
-It's conventional to put an empty alternative first and write the comment
-@samp{/* empty */} in it.
+It's conventional to put an empty alternative first and to use the
+(optional) @code{%empty} directive, or to write the comment @samp{/* empty
+*/} in it (@pxref{Empty Rules}).
 
 The second alternate rule (@code{input line}) handles all nontrivial input.
 It means, ``After reading any number of lines, read one more line if
@@ -1714,15 +1804,16 @@ therefore, @code{NUM} becomes a macro for @code{yylex} to use.
 
 The semantic value of the token (if it has one) is stored into the
 global variable @code{yylval}, which is where the Bison parser will look
-for it.  (The C data type of @code{yylval} is @code{YYSTYPE}, which was
-defined at the beginning of the grammar; @pxref{Rpcalc Declarations,
-,Declarations for @code{rpcalc}}.)
+for it.  (The C data type of @code{yylval} is @code{YYSTYPE}, whose value
+was defined at the beginning of the grammar via @samp{%define api.value.type
+@{double@}}; @pxref{Rpcalc Declarations,,Declarations for @code{rpcalc}}.)
 
 A token type code of zero is returned if the end-of-input is encountered.
 (Bison recognizes any nonpositive value as indicating end-of-input.)
 
 Here is the code for the lexical analyzer:
 
+@comment file: rpcalc.y
 @example
 @group
 /* The lexical analyzer returns a double floating point
@@ -1771,6 +1862,7 @@ In keeping with the spirit of this example, the controlling function is
 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
@@ -1791,10 +1883,9 @@ always @code{"syntax error"}).  It is up to the programmer to supply
 @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>
-@end group
 
 @group
 /* Called by yyparse on error.  */
@@ -1875,15 +1966,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
@@ -1904,7 +1995,6 @@ parentheses nested to arbitrary depth.  Here is the Bison code for
 
 @group
 %@{
-  #define YYSTYPE double
   #include <math.h>
   #include <stdio.h>
   int yylex (void);
@@ -1914,17 +2004,18 @@ parentheses nested to arbitrary depth.  Here is the Bison code for
 
 @group
 /* Bison declarations.  */
+%define api.value.type @{double@}
 %token NUM
 %left '-' '+'
 %left '*' '/'
-%left NEG     /* negation--unary minus */
-%right '^'    /* exponentiation */
+%precedence NEG   /* negation--unary minus */
+%right '^'        /* exponentiation */
 @end group
 
 %% /* The grammar follows.  */
 @group
 input:
-  /* empty */
+  %empty
 | input line
 ;
 @end group
@@ -1961,15 +2052,16 @@ In the second section (Bison declarations), @code{%left} declares token
 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
@@ -2062,18 +2154,18 @@ the same as the declarations for the infix notation calculator.
 /* Location tracking calculator.  */
 
 %@{
-  #define YYSTYPE int
   #include <math.h>
   int yylex (void);
   void yyerror (char const *);
 %@}
 
 /* Bison declarations.  */
+%define api.value.type int
 %token NUM
 
 %left '-' '+'
 %left '*' '/'
-%left NEG
+%precedence NEG
 %right '^'
 
 %% /* The grammar follows.  */
@@ -2103,7 +2195,7 @@ wrong expressions or subexpressions.
 @example
 @group
 input:
-  /* empty */
+  %empty
 | input line
 ;
 @end group
@@ -2274,19 +2366,23 @@ to create named variables, store values in them, and use them later.
 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
 
@@ -2296,6 +2392,8 @@ Note that multiple assignment and nested function calls are permitted.
 * 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
@@ -2307,29 +2405,25 @@ Here are the C and Bison declarations for the multi-function calculator.
 @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 *);
 %@}
 @end group
 
-@group
-%union @{
-  double    val;   /* For returning numbers.  */
-  symrec  *tptr;   /* For returning symbol-table pointers.  */
-@}
-@end group
-%token <val>  NUM        /* Simple double precision number.  */
-%token <tptr> VAR FNCT   /* Variable and function.  */
-%type  <val>  exp
+%define api.value.type union /* Generate YYSTYPE from these types:  */
+%token <double>  NUM         /* Simple double precision number.  */
+%token <symrec*> VAR FNCT    /* Symbol table pointer: variable and function.  */
+%type  <double>  exp
 
 @group
-%right '='
+%precedence '='
 %left '-' '+'
 %left '*' '/'
-%left NEG     /* negation--unary minus */
-%right '^'    /* exponentiation */
+%precedence NEG /* negation--unary minus */
+%right '^'      /* exponentiation */
 @end group
 @end example
 
@@ -2337,23 +2431,23 @@ The above grammar introduces only two new features of the Bison language.
 These features allow semantic values to have various data types
 (@pxref{Multiple Types, ,More Than One Value Type}).
 
-The @code{%union} declaration specifies the entire list of possible types;
-this is instead of defining @code{YYSTYPE}.  The allowable types are now
-double-floats (for @code{exp} and @code{NUM}) and pointers to entries in
-the symbol table.  @xref{Union Decl, ,The Collection of Value Types}.
-
-Since values can now have various types, it is necessary to associate a
-type with each grammar symbol whose semantic value is used.  These symbols
-are @code{NUM}, @code{VAR}, @code{FNCT}, and @code{exp}.  Their
-declarations are augmented with information about their data type (placed
-between angle brackets).
-
-The Bison construct @code{%type} is used for declaring nonterminal
-symbols, just as @code{%token} is used for declaring token types.  We
-have not used @code{%type} before because nonterminal symbols are
-normally declared implicitly by the rules that define them.  But
-@code{exp} must be declared explicitly so we can specify its value type.
-@xref{Type Decl, ,Nonterminal Symbols}.
+The special @code{union} value assigned to the @code{%define} variable
+@code{api.value.type} specifies that the symbols are defined with their data
+types.  Bison will generate an appropriate definition of @code{YYSTYPE} to
+store these values.
+
+Since values can now have various types, it is necessary to associate a type
+with each grammar symbol whose semantic value is used.  These symbols are
+@code{NUM}, @code{VAR}, @code{FNCT}, and @code{exp}.  Their declarations are
+augmented with their data type (placed between angle brackets).  For
+instance, values of @code{NUM} are stored in @code{double}.
+
+The Bison construct @code{%type} is used for declaring nonterminal symbols,
+just as @code{%token} is used for declaring token types.  Previously we did
+not use @code{%type} before because nonterminal symbols are normally
+declared implicitly by the rules that define them.  But @code{exp} must be
+declared explicitly so we can specify its value type.  @xref{Type Decl,
+,Nonterminal Symbols}.
 
 @node Mfcalc Rules
 @subsection Grammar Rules for @code{mfcalc}
@@ -2367,7 +2461,7 @@ those which mention @code{VAR} or @code{FNCT}, are new.
 %% /* The grammar follows.  */
 @group
 input:
-  /* empty */
+  %empty
 | input line
 ;
 @end group
@@ -2437,7 +2531,7 @@ struct symrec
 @group
 typedef struct symrec symrec;
 
-/* The symbol table: a chain of `struct symrec'.  */
+/* The symbol table: a chain of 'struct symrec'.  */
 extern symrec *sym_table;
 
 symrec *putsym (char const *, int);
@@ -2445,23 +2539,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)
-@{
-  fprintf (stderr, "%s\n", s);
-@}
-@end group
-
 @group
 struct init
 @{
@@ -2473,23 +2555,24 @@ 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
 
 @group
-/* The symbol table: a chain of `struct symrec'.  */
+/* The symbol table: a chain of 'struct symrec'.  */
 symrec *sym_table;
 @end group
 
 @group
 /* Put arithmetic functions in table.  */
+static
 void
 init_table (void)
 @{
@@ -2501,15 +2584,6 @@ 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
@@ -2549,13 +2623,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
@@ -2573,9 +2650,7 @@ operators in @code{yylex}.
 
 @comment file: mfcalc.y: 3
 @example
-@group
 #include <ctype.h>
-@end group
 
 @group
 int
@@ -2596,11 +2671,18 @@ yylex (void)
   if (c == '.' || isdigit (c))
     @{
       ungetc (c, stdin);
-      scanf ("%lf", &yylval.val);
+      scanf ("%lf", &yylval.NUM);
       return NUM;
     @}
 @end group
+@end example
+
+@noindent
+Bison generated a definition of @code{YYSTYPE} with a member named
+@code{NUM} to store value of @code{NUM} symbols.
 
+@comment file: mfcalc.y: 3
+@example
 @group
   /* Char starts an identifier => read the name.       */
   if (isalpha (c))
@@ -2612,7 +2694,6 @@ yylex (void)
       symrec *s;
       int i;
 @end group
-
       if (!symbuf)
         symbuf = (char *) malloc (length + 1);
 
@@ -2643,7 +2724,7 @@ yylex (void)
       s = getsym (symbuf);
       if (s == 0)
         s = putsym (symbuf, VAR);
-      yylval.tptr = s;
+      *((symrec**) &yylval) = s;
       return s->type;
     @}
 
@@ -2653,6 +2734,9 @@ yylex (void)
 @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):
@@ -2718,7 +2802,6 @@ The Bison grammar file conventionally has a name ending in @samp{.y}.
 * Grammar Outline::    Overall layout of the grammar file.
 * Symbols::            Terminal and nonterminal symbols.
 * Rules::              How to write grammar rules.
-* Recursion::          Writing recursive rules.
 * Semantics::          Semantic values and actions.
 * Tracking Locations:: Locations and actions.
 * Named References::   Using named references in actions.
@@ -2788,21 +2871,27 @@ can be done with two @var{Prologue} blocks, one before and one after the
 @code{%union} declaration.
 
 @example
+@group
 %@{
   #define _GNU_SOURCE
   #include <stdio.h>
   #include "ptypes.h"
 %@}
+@end group
 
+@group
 %union @{
   long int n;
   tree t;  /* @r{@code{tree} is defined in @file{ptypes.h}.} */
 @}
+@end group
 
+@group
 %@{
   static void print_token_value (FILE *, int, YYSTYPE);
   #define YYPRINT(F, N, L) print_token_value (F, N, L)
 %@}
+@end group
 
 @dots{}
 @end example
@@ -2834,21 +2923,27 @@ location, or it can be one of @code{requires}, @code{provides},
 Look again at the example of the previous section:
 
 @example
+@group
 %@{
   #define _GNU_SOURCE
   #include <stdio.h>
   #include "ptypes.h"
 %@}
+@end group
 
+@group
 %union @{
   long int n;
   tree t;  /* @r{@code{tree} is defined in @file{ptypes.h}.} */
 @}
+@end group
 
+@group
 %@{
   static void print_token_value (FILE *, int, YYSTYPE);
   #define YYPRINT(F, N, L) print_token_value (F, N, L)
 %@}
+@end group
 
 @dots{}
 @end example
@@ -2886,7 +2981,7 @@ Let's go ahead and add the new @code{YYLTYPE} definition and the
   #include <stdio.h>
 
   /* WARNING: The following code really belongs
-   * in a `%code requires'; see below.  */
+   * in a '%code requires'; see below.  */
 
   #include "ptypes.h"
   #define YYLTYPE YYLTYPE
@@ -2900,16 +2995,20 @@ Let's go ahead and add the new @code{YYLTYPE} definition and the
   @} YYLTYPE;
 @}
 
+@group
 %union @{
   long int n;
   tree t;  /* @r{@code{tree} is defined in @file{ptypes.h}.} */
 @}
+@end group
 
+@group
 %code @{
   static void print_token_value (FILE *, int, YYSTYPE);
   #define YYPRINT(F, N, L) print_token_value (F, N, L)
   static void trace_token (enum yytokentype token, YYLTYPE loc);
 @}
+@end group
 
 @dots{}
 @end example
@@ -3320,7 +3419,18 @@ value of the error token is 256, unless you explicitly assigned 256 to
 one of your tokens with a @code{%token} declaration.
 
 @node Rules
-@section Syntax of Grammar Rules
+@section Grammar Rules
+
+A Bison grammar is a list of rules.
+
+@menu
+* Rules Syntax::   Syntax of the rules.
+* Empty Rules::    Symbols that can match the empty string.
+* Recursion::      Writing recursive rules.
+@end menu
+
+@node Rules Syntax
+@subsection Syntax of Grammar Rules
 @cindex rule syntax
 @cindex grammar rule syntax
 @cindex syntax of grammar rules
@@ -3328,9 +3438,7 @@ one of your tokens with a @code{%token} declaration.
 A Bison grammar rule has the following general form:
 
 @example
-@group
 @var{result}: @var{components}@dots{};
-@end group
 @end example
 
 @noindent
@@ -3341,9 +3449,7 @@ are put together by this rule (@pxref{Symbols}).
 For example,
 
 @example
-@group
 exp: exp '+' exp;
-@end group
 @end example
 
 @noindent
@@ -3398,33 +3504,57 @@ be joined with the vertical-bar character @samp{|} as follows:
 @noindent
 They are still considered distinct rules even when joined in this way.
 
-If @var{components} in a rule is empty, it means that @var{result} can
-match the empty string.  For example, here is how to define a
-comma-separated sequence of zero or more @code{exp} groupings:
+@node Empty Rules
+@subsection Empty Rules
+@cindex empty rule
+@cindex rule, empty
+@findex %empty
+
+A rule is said to be @dfn{empty} if its right-hand side (@var{components})
+is empty.  It means that @var{result} can match the empty string.  For
+example, here is how to define an optional semicolon:
+
+@example
+semicolon.opt: | ";";
+@end example
+
+@noindent
+It is easy not to see an empty rule, especially when @code{|} is used.  The
+@code{%empty} directive allows to make explicit that a rule is empty on
+purpose:
 
 @example
 @group
-expseq:
-  /* empty */
-| expseq1
+semicolon.opt:
+  %empty
+| ";"
 ;
 @end group
+@end example
 
+Flagging a non-empty rule with @code{%empty} is an error.  If run with
+@option{-Wempty-rule}, @command{bison} will report empty rules without
+@code{%empty}.  Using @code{%empty} enables this warning, unless
+@option{-Wno-empty-rule} was specified.
+
+The @code{%empty} directive is a Bison extension, it does not work with
+Yacc.  To remain compatible with POSIX Yacc, it is customary to write a
+comment @samp{/* empty */} in each rule with no components:
+
+@example
 @group
-expseq1:
-  exp
-| expseq1 ',' exp
+semicolon.opt:
+  /* empty */
+| ";"
 ;
 @end group
 @end example
 
-@noindent
-It is customary to write a comment @samp{/* empty */} in each rule
-with no components.
 
 @node Recursion
-@section Recursive Rules
+@subsection Recursive Rules
 @cindex recursive rule
+@cindex rule, recursive
 
 A rule is called @dfn{recursive} when its @var{result} nonterminal
 appears also on its right hand side.  Nearly all Bison grammars need to
@@ -3512,6 +3642,9 @@ the numbers associated with @var{x} and @var{y}.
 @menu
 * Value Type::        Specifying one data type for all semantic values.
 * Multiple Types::    Specifying several alternative data types.
+* Type Generation::   Generating the semantic value type.
+* Union Decl::        Declaring the set of all semantic value types.
+* Structured Value Type::  Providing a structured semantic value type.
 * Actions::           An action is the semantic definition of a grammar rule.
 * Action Types::      Specifying data types for actions to operate on.
 * Mid-Rule Actions::  Most actions go at the end of a rule.
@@ -3533,17 +3666,38 @@ Notation Calculator}).
 
 Bison normally uses the type @code{int} for semantic values if your
 program uses the same data type for all language constructs.  To
-specify some other type, define @code{YYSTYPE} as a macro, like this:
+specify some other type, define the @code{%define} variable
+@code{api.value.type} like this:
+
+@example
+%define api.value.type @{double@}
+@end example
+
+@noindent
+or
+
+@example
+%define api.value.type @{struct semantic_type@}
+@end example
+
+The value of @code{api.value.type} should be a type name that does not
+contain parentheses or square brackets.
+
+Alternatively, instead of relying of Bison's @code{%define} support, you may
+rely on the C/C++ preprocessor and define @code{YYSTYPE} as a macro, like
+this:
 
 @example
 #define YYSTYPE double
 @end example
 
 @noindent
-@code{YYSTYPE}'s replacement list should be a type name
-that does not contain parentheses or square brackets.
 This macro definition must go in the prologue of the grammar file
-(@pxref{Grammar Outline, ,Outline of a Bison Grammar}).
+(@pxref{Grammar Outline, ,Outline of a Bison Grammar}).  If compatibility
+with POSIX Yacc matters to you, use this.  Note however that Bison cannot
+know @code{YYSTYPE}'s value, not even whether it is defined, so there are
+services it cannot provide.  Besides this works only for languages that have
+a preprocessor.
 
 @node Multiple Types
 @subsection More Than One Value Type
@@ -3559,11 +3713,25 @@ requires you to do two things:
 
 @itemize @bullet
 @item
-Specify the entire collection of possible data types, either by using the
-@code{%union} Bison declaration (@pxref{Union Decl, ,The Collection of
-Value Types}), or by using a @code{typedef} or a @code{#define} to
-define @code{YYSTYPE} to be a union type whose member names are
-the type tags.
+Specify the entire collection of possible data types.  There are several
+options:
+@itemize @bullet
+@item
+let Bison compute the union type from the tags you assign to symbols;
+
+@item
+use the @code{%union} Bison declaration (@pxref{Union Decl, ,The Union
+Declaration});
+
+@item
+define the @code{%define} variable @code{api.value.type} to be a union type
+whose members are the type tags (@pxref{Structured Value Type,, Providing a
+Structured Semantic Value Type});
+
+@item
+use a @code{typedef} or a @code{#define} to define @code{YYSTYPE} to be a
+union type whose member names are the type tags.
+@end itemize
 
 @item
 Choose one of those types for each symbol (terminal or nonterminal) for
@@ -3573,6 +3741,164 @@ and for groupings with the @code{%type} Bison declaration (@pxref{Type
 Decl, ,Nonterminal Symbols}).
 @end itemize
 
+@node Type Generation
+@subsection Generating the Semantic Value Type
+@cindex declaring value types
+@cindex value types, declaring
+@findex %define api.value.type union
+
+The special value @code{union} of the @code{%define} variable
+@code{api.value.type} instructs Bison that the tags used with the
+@code{%token} and @code{%type} directives are genuine types, not names of
+members of @code{YYSTYPE}.
+
+For example:
+
+@example
+%define api.value.type union
+%token <int> INT "integer"
+%token <int> 'n'
+%type <int> expr
+%token <char const *> ID "identifier"
+@end example
+
+@noindent
+generates an appropriate value of @code{YYSTYPE} to support each symbol
+type.  The name of the member of @code{YYSTYPE} for tokens than have a
+declared identifier @var{id} (such as @code{INT} and @code{ID} above, but
+not @code{'n'}) is @code{@var{id}}.  The other symbols have unspecified
+names on which you should not depend; instead, relying on C casts to access
+the semantic value with the appropriate type:
+
+@example
+/* For an "integer".  */
+yylval.INT = 42;
+return INT;
+
+/* For an 'n', also declared as int.  */
+*((int*)&yylval) = 42;
+return 'n';
+
+/* For an "identifier".  */
+yylval.ID = "42";
+return ID;
+@end example
+
+If the @code{%define} variable @code{api.token.prefix} is defined
+(@pxref{%define Summary,,api.token.prefix}), then it is also used to prefix
+the union member names.  For instance, with @samp{%define api.token.prefix
+TOK_}:
+
+@example
+/* For an "integer".  */
+yylval.TOK_INT = 42;
+return TOK_INT;
+@end example
+
+This Bison extension cannot work if @code{%yacc} (or
+@option{-y}/@option{--yacc}) is enabled, as POSIX mandates that Yacc
+generate tokens as macros (e.g., @samp{#define INT 258}, or @samp{#define
+TOK_INT 258}).
+
+This feature is new, and user feedback would be most welcome.
+
+A similar feature is provided for C++ that in addition overcomes C++
+limitations (that forbid non-trivial objects to be part of a @code{union}):
+@samp{%define api.value.type variant}, see @ref{C++ Variants}.
+
+@node Union Decl
+@subsection The Union Declaration
+@cindex declaring value types
+@cindex value types, declaring
+@findex %union
+
+The @code{%union} declaration specifies the entire collection of possible
+data types for semantic values.  The keyword @code{%union} is followed by
+braced code containing the same thing that goes inside a @code{union} in C@.
+
+For example:
+
+@example
+@group
+%union @{
+  double val;
+  symrec *tptr;
+@}
+@end group
+@end example
+
+@noindent
+This says that the two alternative types are @code{double} and @code{symrec
+*}.  They are given names @code{val} and @code{tptr}; these names are used
+in the @code{%token} and @code{%type} declarations to pick one of the types
+for a terminal or nonterminal symbol (@pxref{Type Decl, ,Nonterminal Symbols}).
+
+As an extension to POSIX, a tag is allowed after the @code{%union}.  For
+example:
+
+@example
+@group
+%union value @{
+  double val;
+  symrec *tptr;
+@}
+@end group
+@end example
+
+@noindent
+specifies the union tag @code{value}, so the corresponding C type is
+@code{union value}.  If you do not specify a tag, it defaults to
+@code{YYSTYPE}.
+
+As another extension to POSIX, you may specify multiple @code{%union}
+declarations; their contents are concatenated.  However, only the first
+@code{%union} declaration can specify a tag.
+
+Note that, unlike making a @code{union} declaration in C, you need not write
+a semicolon after the closing brace.
+
+@node Structured Value Type
+@subsection Providing a Structured Semantic Value Type
+@cindex declaring value types
+@cindex value types, declaring
+@findex %union
+
+Instead of @code{%union}, you can define and use your own union type
+@code{YYSTYPE} if your grammar contains at least one @samp{<@var{type}>}
+tag.  For example, you can put the following into a header file
+@file{parser.h}:
+
+@example
+@group
+union YYSTYPE @{
+  double val;
+  symrec *tptr;
+@};
+@end group
+@end example
+
+@noindent
+and then your grammar can use the following instead of @code{%union}:
+
+@example
+@group
+%@{
+#include "parser.h"
+%@}
+%define api.value.type "union YYSTYPE"
+%type <val> expr
+%token <tptr> ID
+@end group
+@end example
+
+Actually, you may also provide a @code{struct} rather that a @code{union},
+which may be handy if you want to track information for every symbol (such
+as preceding comments).
+
+The type you provide may even be structured and include pointers, in which
+case the type tags you provide may be composite, with @samp{.} and @samp{->}
+operators.
+
 @node Actions
 @subsection Actions
 @cindex action
@@ -3647,9 +3973,7 @@ difference with tools like Flex, for which @samp{|} stands for either
 following example, the action is triggered only when @samp{b} is found:
 
 @example
-@group
 a-or-b: 'a'|'b'   @{ a_or_b_found = 1; @};
-@end group
 @end example
 
 @cindex default action
@@ -3676,7 +4000,7 @@ foo:
 
 @group
 bar:
-  /* empty */    @{ previous_expr = $0; @}
+  %empty    @{ previous_expr = $0; @}
 ;
 @end group
 @end example
@@ -3853,16 +4177,20 @@ declare a destructor for that symbol:
 @group
 %type <context> let
 %destructor @{ pop_context ($$); @} let
+@end group
 
 %%
 
+@group
 stmt:
   let stmt
     @{
       $$ = $2;
       pop_context ($let);
     @};
+@end group
 
+@group
 let:
   "let" '(' var ')'
     @{
@@ -3897,9 +4225,9 @@ exp: @{ a(); @} "b" @{ c(); @} @{ d(); @} "e" @{ f(); @};
 is translated into:
 
 @example
-$@@1: /* empty */ @{ a(); @};
-$@@2: /* empty */ @{ c(); @};
-$@@3: /* empty */ @{ d(); @};
+$@@1: %empty @{ a(); @};
+$@@2: %empty @{ c(); @};
+$@@3: %empty @{ d(); @};
 exp: $@@1 "b" $@@2 $@@3 "e" @{ f(); @};
 @end example
 
@@ -3918,9 +4246,9 @@ exp: @{ a(); @} "b" @{ $$ = c(); @} @{ d(); @} "e" @{ f = $1; @};
 is translated into
 
 @example
-@@1: /* empty */ @{ a(); @};
-@@2: /* empty */ @{ $$ = c(); @};
-$@@3: /* empty */ @{ d(); @};
+@@1: %empty @{ a(); @};
+@@2: %empty @{ $$ = c(); @};
+$@@3: %empty @{ d(); @};
 exp: @@1 "b" @@2 $@@3 "e" @{ f = $1; @}
 @end example
 
@@ -4029,7 +4357,7 @@ serves as a subroutine:
 @example
 @group
 subroutine:
-  /* empty */  @{ prepare_for_local_variables (); @}
+  %empty  @{ prepare_for_local_variables (); @}
 ;
 @end group
 
@@ -4136,8 +4464,7 @@ exp:
       else
         @{
           $$ = 1;
-          fprintf (stderr,
-                   "Division by zero, l%d,c%d-l%d,c%d",
+          fprintf (stderr, "%d.%d-%d.%d: division by zero",
                    @@3.first_line, @@3.first_column,
                    @@3.last_line, @@3.last_column);
         @}
@@ -4164,8 +4491,7 @@ exp:
       else
         @{
           $$ = 1;
-          fprintf (stderr,
-                   "Division by zero, l%d,c%d-l%d,c%d",
+          fprintf (stderr, "%d.%d-%d.%d: division by zero",
                    @@3.first_line, @@3.first_column,
                    @@3.last_line, @@3.last_column);
         @}
@@ -4373,7 +4699,6 @@ and Context-Free Grammars}).
 * Require Decl::      Requiring a Bison version.
 * Token Decl::        Declaring terminal symbols.
 * Precedence Decl::   Declaring terminals with precedence and associativity.
-* Union Decl::        Declaring the set of all semantic value types.
 * Type Decl::         Declaring the choice of type for a nonterminal symbol.
 * Initial Action Decl::  Code run before parsing starts.
 * Destructor Decl::   Declaring how symbols are freed.
@@ -4418,7 +4743,8 @@ Bison will convert this into a @code{#define} directive in
 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}.
@@ -4494,7 +4820,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
@@ -4530,6 +4857,10 @@ left-associativity (grouping @var{x} with @var{y} first) and
 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
@@ -4550,87 +4881,6 @@ For example:
 %left  OR 134 "<=" 135 // Declares 134 for OR and 135 for "<=".
 @end example
 
-@node Union Decl
-@subsection The Collection of Value Types
-@cindex declaring value types
-@cindex value types, declaring
-@findex %union
-
-The @code{%union} declaration specifies the entire collection of
-possible data types for semantic values.  The keyword @code{%union} is
-followed by braced code containing the same thing that goes inside a
-@code{union} in C@.
-
-For example:
-
-@example
-@group
-%union @{
-  double val;
-  symrec *tptr;
-@}
-@end group
-@end example
-
-@noindent
-This says that the two alternative types are @code{double} and @code{symrec
-*}.  They are given names @code{val} and @code{tptr}; these names are used
-in the @code{%token} and @code{%type} declarations to pick one of the types
-for a terminal or nonterminal symbol (@pxref{Type Decl, ,Nonterminal Symbols}).
-
-As an extension to POSIX, a tag is allowed after the
-@code{union}.  For example:
-
-@example
-@group
-%union value @{
-  double val;
-  symrec *tptr;
-@}
-@end group
-@end example
-
-@noindent
-specifies the union tag @code{value}, so the corresponding C type is
-@code{union value}.  If you do not specify a tag, it defaults to
-@code{YYSTYPE}.
-
-As another extension to POSIX, you may specify multiple
-@code{%union} declarations; their contents are concatenated.  However,
-only the first @code{%union} declaration can specify a tag.
-
-Note that, unlike making a @code{union} declaration in C, you need not write
-a semicolon after the closing brace.
-
-Instead of @code{%union}, you can define and use your own union type
-@code{YYSTYPE} if your grammar contains at least one
-@samp{<@var{type}>} tag.  For example, you can put the following into
-a header file @file{parser.h}:
-
-@example
-@group
-union YYSTYPE @{
-  double val;
-  symrec *tptr;
-@};
-typedef union YYSTYPE YYSTYPE;
-@end group
-@end example
-
-@noindent
-and then your grammar can use the following
-instead of @code{%union}:
-
-@example
-@group
-%@{
-#include "parser.h"
-%@}
-%type <val> expr
-%token <tptr> ID
-@end group
-@end example
-
 @node Type Decl
 @subsection Nonterminal Symbols
 @cindex declaring value types, nonterminals
@@ -4649,7 +4899,7 @@ used.  This is done with a @code{%type} declaration, like this:
 @noindent
 Here @var{nonterminal} is the name of a nonterminal symbol, and
 @var{type} is the name given in the @code{%union} to the alternative
-that you want (@pxref{Union Decl, ,The Collection of Value Types}).  You
+that you want (@pxref{Union Decl, ,The Union Declaration}).  You
 can give any number of nonterminal symbols in the same @code{%type}
 declaration, if they have the same value type.  Use spaces to separate
 the symbol names.
@@ -4745,10 +4995,8 @@ For example:
 
 @example
 %union @{ char *string; @}
-%token <string> STRING1
-%token <string> STRING2
-%type  <string> string1
-%type  <string> string2
+%token <string> STRING1 STRING2
+%type  <string> string1 string2
 %union @{ char character; @}
 %token <character> CHR
 %type  <character> chr
@@ -4874,10 +5122,8 @@ For example:
 
 @example
 %union @{ char *string; @}
-%token <string> STRING1
-%token <string> STRING2
-%type  <string> string1
-%type  <string> string2
+%token <string> STRING1 STRING2
+%type  <string> string1 string2
 %union @{ char character; @}
 %token <character> CHR
 %type  <character> chr
@@ -4995,7 +5241,7 @@ statically allocated variables for communication with @code{yylex},
 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
@@ -5008,7 +5254,7 @@ calling convention is used for the lexical analyzer function
 @code{yylex}.  @xref{Pure Calling, ,Calling Conventions for Pure
 Parsers}, for the details of this.  The variable @code{yynerrs}
 becomes local in @code{yyparse} in pull mode but it becomes a member
-of yypstate in push mode.  (@pxref{Error Reporting, ,The Error
+of @code{yypstate} in push mode.  (@pxref{Error Reporting, ,The Error
 Reporting Function @code{yyerror}}).  The convention for calling
 @code{yyparse} itself is unchanged.
 
@@ -5099,14 +5345,14 @@ for use by the next invocation of the @code{yypush_parse} function.
 
 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
@@ -5122,9 +5368,9 @@ yypull_parse (ps); /* Will call the lexer */
 yypstate_delete (ps);
 @end example
 
-Adding the @code{%define api.pure full} 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
@@ -5136,7 +5382,7 @@ Here is a summary of the declarations used to define a grammar:
 
 @deffn {Directive} %union
 Declare the collection of data types that semantic values may have
-(@pxref{Union Decl, ,The Collection of Value Types}).
+(@pxref{Union Decl, ,The Union Declaration}).
 @end deffn
 
 @deffn {Directive} %token
@@ -5197,10 +5443,8 @@ default location or at the location specified by @var{qualifier}.
 @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
 
@@ -5266,7 +5510,7 @@ For instance with @samp{%define api.prefix "calc"} and @samp{%defines
 @end deffn
 
 @deffn {Directive} %defines @var{defines-file}
-Same as above, but save in the file @var{defines-file}.
+Same as above, but save in the file @file{@var{defines-file}}.
 @end deffn
 
 @deffn {Directive} %destructor
@@ -5294,6 +5538,22 @@ grammar does not use it, using @samp{%locations} allows for more
 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}
@@ -5313,11 +5573,11 @@ own right.
 @end deffn
 
 @deffn {Directive} %output "@var{file}"
-Specify @var{file} for the parser implementation file.
+Generate the parser implementation in @file{@var{file}}.
 @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
@@ -5438,12 +5698,62 @@ values, depend on the selected target language and/or the parser
 skeleton (@pxref{Decl Summary,,%language}, @pxref{Decl
 Summary,,%skeleton}).
 Unaccepted @var{variable}s produce an error.
-Some of the accepted @var{variable}s are:
+Some of the accepted @var{variable}s are described below.
+
+@c ================================================== api.namespace
+@deffn Directive {%define api.namespace} @{@var{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
+@end deffn
+@c api.namespace
 
-@itemize @bullet
 @c ================================================== api.location.type
-@item @code{api.location.type}
-@findex %define api.location.type
+@deffn {Directive} {%define api.location.type} @var{type}
 
 @itemize @bullet
 @item Language(s): C++, Java
@@ -5455,12 +5765,14 @@ Some of the accepted @var{variable}s are:
 
 @item Default Value: none
 
-@item History: introduced in Bison 2.7
+@item History:
+Introduced in Bison 2.7 for C, C++ and Java.  Introduced under the name
+@code{location_type} for C++ in Bison 2.5 and for Java in Bison 2.4.
 @end itemize
+@end deffn
 
 @c ================================================== api.prefix
-@item @code{api.prefix}
-@findex %define api.prefix
+@deffn {Directive} {%define api.prefix} @var{prefix}
 
 @itemize @bullet
 @item Language(s): All
@@ -5474,10 +5786,10 @@ Some of the accepted @var{variable}s are:
 
 @item History: introduced in Bison 2.6
 @end itemize
+@end deffn
 
 @c ================================================== api.pure
-@item @code{api.pure}
-@findex %define api.pure
+@deffn Directive {%define api.pure}
 
 @itemize @bullet
 @item Language(s): C
@@ -5519,13 +5831,16 @@ Reporting Function @code{yyerror}})
 
 @item Default Value: @code{false}
 
-@item History: the @code{full} value was introduced in Bison 2.7
+@item History:
+the @code{full} value was introduced in Bison 2.7
 @end itemize
+@end deffn
+@c api.pure
 
-@c ================================================== api.push-pull
 
-@item @code{api.push-pull}
-@findex %define api.push-pull
+
+@c ================================================== api.push-pull
+@deffn Directive {%define api.push-pull} @var{kind}
 
 @itemize @bullet
 @item Language(s): C (deterministic parsers only)
@@ -5539,11 +5854,184 @@ More user feedback will help to stabilize it.)
 
 @item Default Value: @code{pull}
 @end itemize
+@end deffn
+@c api.push-pull
+
+
+
+@c ================================================== api.token.constructor
+@deffn Directive {%define api.token.constructor}
+
+@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}
+@item History:
+introduced in Bison 2.8
+@end itemize
+@end deffn
+@c api.token.constructor
+
+
+@c ================================================== api.token.prefix
+@deffn Directive {%define api.token.prefix} @var{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.token.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.
+
+Bison also prefixes the generated member names of the semantic value union.
+@xref{Type Generation,, Generating the Semantic Value Type}, for more
+details.
+
+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
+@item History:
+introduced in Bison 2.8
+@end itemize
+@end deffn
+@c api.token.prefix
+
+
+@c ================================================== api.value.type
+@deffn Directive {%define api.value.type} @var{type}
+@itemize @bullet
+@item Language(s):
+all
 
-@c ================================================== lr.default-reductions
+@item Purpose:
+The type for semantic values.
 
-@item @code{lr.default-reductions}
-@findex %define lr.default-reductions
+@item Accepted Values:
+@table @asis
+@item @code{""}
+This grammar has no semantic value at all.  This is not properly supported
+yet.
+@item @code{%union} (C, C++)
+The type is defined thanks to the @code{%union} directive.  You don't have
+to define @code{api.value.type} in that case, using @code{%union} suffices.
+@xref{Union Decl, ,The Union Declaration}.
+For instance:
+@example
+%define api.value.type "%union"
+%union
+@{
+  int ival;
+  char *sval;
+@}
+%token <ival> INT "integer"
+%token <sval> STR "string"
+@end example
+
+@item @code{union} (C, C++)
+The symbols are defined with type names, from which Bison will generate a
+@code{union}.  For instance:
+@example
+%define api.value.type "union"
+%token <int> INT "integer"
+%token <char *> STR "string"
+@end example
+This feature needs user feedback to stabilize.  Note that most C++ objects
+cannot be stored in a @code{union}.
+
+@item @code{variant} (C++)
+This is similar to @code{union}, but special storage techniques are used to
+allow any kind of C++ object to be used. For instance:
+@example
+%define api.value.type "variant"
+%token <int> INT "integer"
+%token <std::string> STR "string"
+@end example
+This feature needs user feedback to stabilize.
+@xref{C++ Variants}.
+
+@item any other identifier
+Use this name as semantic value.
+@example
+%code requires
+@{
+  struct my_value
+  @{
+    enum
+    @{
+      is_int, is_str
+    @} kind;
+    union
+    @{
+      int ival;
+      char *sval;
+    @} u;
+  @};
+@}
+%define api.value.type "struct my_value"
+%token <u.ival> INT "integer"
+%token <u.sval> STR "string"
+@end example
+@end table
+
+@item Default Value:
+@itemize @minus
+@item
+@code{%union} if @code{%union} is used, otherwise @dots{}
+@item
+@code{int} if type tags are used (i.e., @samp{%token <@var{type}>@dots{}} or
+@samp{%token <@var{type}>@dots{}} is used), otherwise @dots{}
+@item
+@code{""}
+@end itemize
+
+@item History:
+introduced in Bison 2.8.  Was introduced for Java only in 2.3b as
+@code{stype}.
+@end itemize
+@end deffn
+@c api.value.type
+
+
+@c ================================================== location_type
+@deffn Directive {%define location_type}
+Obsoleted by @code{api.location.type} since Bison 2.7.
+@end deffn
+
+
+@c ================================================== lr.default-reduction
+
+@deffn Directive {%define lr.default-reduction} @var{when}
 
 @itemize @bullet
 @item Language(s): all
@@ -5559,12 +6047,15 @@ feedback will help to stabilize it.)
 @item @code{accepting} if @code{lr.type} is @code{canonical-lr}.
 @item @code{most} otherwise.
 @end itemize
+@item History:
+introduced as @code{lr.default-reduction} in 2.5, renamed as
+@code{lr.default-reduction} in 2.8.
 @end itemize
+@end deffn
 
-@c ============================================ lr.keep-unreachable-states
+@c ============================================ lr.keep-unreachable-state
 
-@item @code{lr.keep-unreachable-states}
-@findex %define lr.keep-unreachable-states
+@deffn Directive {%define lr.keep-unreachable-state}
 
 @itemize @bullet
 @item Language(s): all
@@ -5572,12 +6063,17 @@ feedback will help to stabilize it.)
 remain in the parser tables.  @xref{Unreachable States}.
 @item Accepted Values: Boolean
 @item Default Value: @code{false}
+@item History:
+introduced as @code{lr.keep_unreachable_states} in 2.3b, renamed as
+@code{lr.keep-unreachable-states} in 2.5, and as
+@code{lr.keep-unreachable-state} in 2.8.
 @end itemize
+@end deffn
+@c lr.keep-unreachable-state
 
 @c ================================================== lr.type
 
-@item @code{lr.type}
-@findex %define lr.type
+@deffn Directive {%define lr.type} @var{type}
 
 @itemize @bullet
 @item Language(s): all
@@ -5590,64 +6086,62 @@ More user feedback will help to stabilize it.)
 
 @item Default Value: @code{lalr}
 @end itemize
+@end deffn
 
 @c ================================================== namespace
+@deffn Directive %define namespace @{@var{namespace}@}
+Obsoleted by @code{api.namespace}
+@c namespace
+@end deffn
 
-@item @code{namespace}
-@findex %define namespace
+@c ================================================== parse.assert
+@deffn Directive {%define parse.assert}
 
 @itemize
 @item Languages(s): C++
 
-@item Purpose: Specify the namespace for the parser class.
-For example, if you specify:
-
-@smallexample
-%define namespace "foo::bar"
-@end smallexample
-
-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
+@end deffn
+@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
+@deffn Directive {%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
+@end deffn
+@c parse.error
+
 
 @c ================================================== parse.lac
-@item @code{parse.lac}
-@findex %define parse.lac
+@deffn Directive {%define parse.lac}
 
 @itemize
 @item Languages(s): C (deterministic parsers only)
@@ -5657,8 +6151,30 @@ syntax error handling.  @xref{LAC}.
 @item Accepted Values: @code{none}, @code{full}
 @item Default Value: @code{none}
 @end itemize
-@end itemize
+@end deffn
+@c parse.lac
+
+@c ================================================== parse.trace
+@deffn Directive {%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
+@end deffn
+@c parse.trace
 
 @node %code Summary
 @subsection %code Summary
@@ -5703,7 +6219,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
 
@@ -5711,10 +6227,11 @@ qualifiers produce an error.  Some of the accepted qualifiers are:
 @item Language(s): C, C++
 
 @item Purpose: This is the best place to write dependency code required for
-@code{YYSTYPE} and @code{YYLTYPE}.
-In other words, it's the best place to define types referenced in @code{%union}
-directives, and it's the best place to override Bison's default @code{YYSTYPE}
-and @code{YYLTYPE} definitions.
+@code{YYSTYPE} and @code{YYLTYPE}.  In other words, it's the best place to
+define types referenced in @code{%union} directives.  If you use
+@code{#define} to override Bison's default @code{YYSTYPE} and @code{YYLTYPE}
+definitions, then it is also the best place.  However you should rather
+@code{%define} @code{api.value.type} and @code{api.location.type}.
 
 @item Location(s): The parser header file and the parser implementation file
 before the Bison-generated @code{YYSTYPE} and @code{YYLTYPE}
@@ -5767,7 +6284,7 @@ parser implementation file.  For example:
 @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
@@ -5839,7 +6356,7 @@ parsers.  To comply with this tradition, when @code{api.prefix} is used,
 @code{YYDEBUG} (not renamed) is used as a default value:
 
 @example
-/* Enabling traces.  */
+/* Debug traces.  */
 #ifndef CDEBUG
 # if defined YYDEBUG
 #  if YYDEBUG
@@ -5929,10 +6446,10 @@ If you use a reentrant parser, you can optionally pass additional
 parameter information to it in a reentrant way.  To do so, use the
 declaration @code{%parse-param}:
 
-@deffn {Directive} %parse-param @{@var{argument-declaration}@}
+@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.
@@ -5941,8 +6458,7 @@ functions or prototypes.  The last identifier in
 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
@@ -5993,11 +6509,11 @@ int  yyparse (int *randomness);
 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)
+@deftypefun int yypush_parse (yypstate *@var{yyps})
 The value returned by @code{yypush_parse} is the same as for yyparse with
 the following exception: it returns @code{YYPUSH_MORE} if more input is
 required to finish parsing the grammar.
@@ -6011,11 +6527,11 @@ 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}.
 
-@deftypefun int yypull_parse (yypstate *yyps)
+@deftypefun int yypull_parse (yypstate *@var{yyps})
 The value returned by @code{yypull_parse} is the same as for @code{yyparse}.
 @end deftypefun
 
@@ -6027,8 +6543,8 @@ The value returned by @code{yypull_parse} is the same as for @code{yyparse}.
 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)
@@ -6046,11 +6562,11 @@ 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)
+@deftypefun void yypstate_delete (yypstate *@var{yyps})
 This function will reclaim the memory associated with a parser instance.
 After this call, you should no longer attempt to use the parser instance.
 @end deftypefun
@@ -6115,7 +6631,7 @@ yylex (void)
     return 0;
   @dots{}
   if (c == '+' || c == '-')
-    return c;      /* Assume token type for `+' is '+'.  */
+    return c;      /* Assume token type for '+' is '+'.  */
   @dots{}
   return INT;      /* Return the type of the token.  */
   @dots{}
@@ -6187,7 +6703,7 @@ Thus, if the type is @code{int} (the default), you might write this in
 
 When you are using multiple data types, @code{yylval}'s type is a union
 made from the @code{%union} declaration (@pxref{Union Decl, ,The
-Collection of Value Types}).  So when you store a token's value, you
+Union Declaration}).  So when you store a token's value, you
 must use the proper member of the union.  If the @code{%union}
 declaration looks like this:
 
@@ -6260,36 +6776,59 @@ textual locations, then the type @code{YYLTYPE} will not be defined.  In
 this case, omit the second argument; @code{yylex} will be called with
 only one argument.
 
-
-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
 
 @noindent
 For instance:
 
 @example
-%lex-param   @{int *nastiness@}
+%lex-param   @{scanner_mode *mode@}
+%parse-param @{parser_mode *mode@}
+%param       @{environment_type *env@}
 @end example
 
 @noindent
-results in the following signature:
+results in the following signatures:
 
 @example
-int yylex (int *nastiness);
+int yylex   (scanner_mode *mode, environment_type *env);
+int yyparse (parser_mode *mode, environment_type *env);
+@end example
+
+If @samp{%define api.pure full} is added:
+
+@example
+int yylex   (YYSTYPE *lvalp, scanner_mode *mode, environment_type *env);
+int yyparse (parser_mode *mode, environment_type *env);
 @end example
 
 @noindent
-If @code{%define api.pure full} (or just @code{%define api.pure}) is added:
+and finally, if both @samp{%define api.pure full} and @code{%locations} are
+used:
 
 @example
-int yylex (YYSTYPE *lvalp, int *nastiness);
+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
@@ -6299,7 +6838,7 @@ int yylex (YYSTYPE *lvalp, int *nastiness);
 @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
@@ -6311,8 +6850,8 @@ called by @code{yyparse} whenever a syntax error is found, and it
 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
@@ -6827,9 +7366,7 @@ rules.  Here is a complete Bison grammar file that actually manifests
 the conflict:
 
 @example
-@group
 %%
-@end group
 @group
 stmt:
   expr
@@ -6861,7 +7398,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.
 * Non Operators::     Using precedence for general conflicts.
@@ -6918,8 +7456,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
@@ -6929,13 +7468,63 @@ those operators left-associative and the @code{%right} declaration makes
 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
 
@@ -6996,8 +7585,8 @@ instance as follows:
 
 @example
 @group
-%nonassoc "then"
-%nonassoc "else"
+%precedence "then"
+%precedence "else"
 @end group
 @end example
 
@@ -7010,7 +7599,7 @@ use right associativity:
 @end example
 
 Neither solution is perfect however.  Since Bison does not provide, so far,
-support for ``scoped'' precedence, both force you to declare the precedence
+``scoped'' precedence, both force you to declare the precedence
 of these keywords with respect to the other operators your grammar.
 Therefore, instead of being warned about new conflicts you would be unaware
 of (e.g., a shift/reduce conflict due to @samp{if test then 1 else 2 + 3}
@@ -7030,8 +7619,8 @@ outlandish at first, but it is really very common.  For example, a minus
 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.
@@ -7139,7 +7728,7 @@ of zero or more @code{word} groupings.
 @example
 @group
 sequence:
-  /* empty */    @{ printf ("empty sequence\n"); @}
+  %empty         @{ printf ("empty sequence\n"); @}
 | maybeword
 | sequence word  @{ printf ("added word %s\n", $2); @}
 ;
@@ -7147,8 +7736,8 @@ sequence:
 
 @group
 maybeword:
-  /* empty */   @{ printf ("empty maybeword\n"); @}
-| word          @{ printf ("single word %s\n", $1); @}
+  %empty    @{ printf ("empty maybeword\n"); @}
+| word      @{ printf ("single word %s\n", $1); @}
 ;
 @end group
 @end example
@@ -7179,7 +7768,7 @@ proper way to define @code{sequence}:
 @example
 @group
 sequence:
-  /* empty */    @{ printf ("empty sequence\n"); @}
+  %empty         @{ printf ("empty sequence\n"); @}
 | sequence word  @{ printf ("added word %s\n", $2); @}
 ;
 @end group
@@ -7188,9 +7777,9 @@ sequence:
 Here is another common error that yields a reduce/reduce conflict:
 
 @example
-sequence:
 @group
-  /* empty */
+sequence:
+  %empty
 | sequence words
 | sequence redirects
 ;
@@ -7198,14 +7787,14 @@ sequence:
 
 @group
 words:
-  /* empty */
+  %empty
 | words word
 ;
 @end group
 
 @group
 redirects:
-  /* empty */
+  %empty
 | redirects redirect
 ;
 @end group
@@ -7228,7 +7817,7 @@ of sequence:
 
 @example
 sequence:
-  /* empty */
+  %empty
 | sequence word
 | sequence redirect
 ;
@@ -7240,7 +7829,7 @@ from being empty:
 @example
 @group
 sequence:
-  /* empty */
+  %empty
 | sequence words
 | sequence redirects
 ;
@@ -7279,12 +7868,12 @@ relies on precedences: use @code{%prec} to give a lower precedence to the
 rule:
 
 @example
-%nonassoc "word"
-%nonassoc "sequence"
+%precedence "word"
+%precedence "sequence"
 %%
 @group
 sequence:
-  /* empty */
+  %empty
 | sequence word      %prec "sequence"
 | sequence redirect  %prec "sequence"
 ;
@@ -7306,7 +7895,7 @@ rule with the same precedence, but make them right-associative:
 %%
 @group
 sequence:
-  /* empty */
+  %empty
 | sequence word      %prec "word"
 | sequence redirect  %prec "redirect"
 ;
@@ -7329,15 +7918,16 @@ param_spec:
 | name_list ':' type
 ;
 @end group
+
 @group
 return_spec:
   type
 | name ':' type
 ;
 @end group
-@group
+
 type: "id";
-@end group
+
 @group
 name: "id";
 name_list:
@@ -7411,14 +8001,19 @@ contexts to have different sets of active rules, because the one for
 rather than the one for @code{name}.
 
 @example
+@group
 param_spec:
   type
 | name_list ':' type
 ;
+@end group
+
+@group
 return_spec:
   type
 | "id" ':' type
 ;
+@end group
 @end example
 
 For a more detailed exposition of LALR(1) parsers and parser
@@ -7431,9 +8026,9 @@ The default behavior of Bison's LR-based parsers is chosen mostly for
 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
@@ -7523,7 +8118,8 @@ There are at least two scenarios where LALR can be worthwhile:
 
 @cindex GLR with LALR
 When employing GLR parsers (@pxref{GLR Parsers}), if you do not resolve any
-conflicts statically (for example, with @code{%left} or @code{%prec}), then
+conflicts statically (for example, with @code{%left} or @code{%precedence}),
+then
 the parser explores all potential parses of any given input.  In this case,
 the choice of parser table construction algorithm is guaranteed not to alter
 the language accepted by the parser.  LALR parser tables are the smallest
@@ -7580,7 +8176,7 @@ and the benefits of IELR, @pxref{Bibliography,,Denny 2008 March}, and
 @node Default Reductions
 @subsection Default Reductions
 @cindex default reductions
-@findex %define lr.default-reductions
+@findex %define lr.default-reduction
 @findex %nonassoc
 
 After parser table construction, Bison identifies the reduction with the
@@ -7662,9 +8258,9 @@ token for which there is a conflict.  The correct action in this case is to
 split the parse instead.
 
 To adjust which states have default reductions enabled, use the
-@code{%define lr.default-reductions} directive.
+@code{%define lr.default-reduction} directive.
 
-@deffn {Directive} {%define lr.default-reductions} @var{where}
+@deffn {Directive} {%define lr.default-reduction} @var{where}
 Specify the kind of states that are permitted to contain default reductions.
 The accepted values of @var{where} are:
 @itemize
@@ -7787,7 +8383,7 @@ parser community for years, for the publication that introduces LAC,
 
 @node Unreachable States
 @subsection Unreachable States
-@findex %define lr.keep-unreachable-states
+@findex %define lr.keep-unreachable-state
 @cindex unreachable states
 
 If there exists no sequence of transitions from the parser's start state to
@@ -7800,7 +8396,7 @@ resolution because they are useless in the generated parser.  However,
 keeping unreachable states is sometimes useful when trying to understand the
 relationship between the parser and the grammar.
 
-@deffn {Directive} {%define lr.keep-unreachable-states} @var{value}
+@deffn {Directive} {%define lr.keep-unreachable-state} @var{value}
 Request that Bison allow unreachable states to remain in the parser tables.
 @var{value} must be a Boolean.  The default is @code{false}.
 @end deffn
@@ -7957,12 +8553,14 @@ that allows variable-length arrays.  The default is 200.
 
 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
@@ -7994,7 +8592,7 @@ For example:
 
 @example
 stmts:
-  /* empty string */
+  %empty
 | stmts '\n'
 | stmts exp '\n'
 | stmts error '\n'
@@ -8962,12 +9560,19 @@ otherwise it defines @code{YYDEBUG} to 1.
 @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
@@ -9041,7 +9646,7 @@ prologue:
 /* Formatting semantic values.  */
 %printer @{ fprintf (yyoutput, "%s", $$->name); @} VAR;
 %printer @{ fprintf (yyoutput, "%s()", $$->name); @} FNCT;
-%printer @{ fprintf (yyoutput, "%g", $$); @} <val>;
+%printer @{ fprintf (yyoutput, "%g", $$); @} <double>;
 @end example
 
 The @code{%define} directive instructs Bison to generate run-time trace
@@ -9054,8 +9659,8 @@ ill-named) @code{%verbose} directive.
 The set of @code{%printer} directives demonstrates how to format the
 semantic value in the traces.  Note that the specification can be done
 either on the symbol type (e.g., @code{VAR} or @code{FNCT}), or on the type
-tag: since @code{<val>} is the type for both @code{NUM} and @code{exp}, this
-printer will be used for them.
+tag: since @code{<double>} is the type for both @code{NUM} and @code{exp},
+this printer will be used for them.
 
 Here is a sample of the information provided by run-time traces.  The traces
 are sent onto standard error.
@@ -9105,7 +9710,7 @@ Entering state 24
 
 @noindent
 The previous reduction demonstrates the @code{%printer} directive for
-@code{<val>}: both the token @code{NUM} and the resulting nonterminal
+@code{<double>}: both the token @code{NUM} and the resulting nonterminal
 @code{exp} have @samp{1} as value.
 
 @example
@@ -9289,7 +9894,7 @@ Here is a list of options that can be used with Bison, alphabetized by
 short option.  It is followed by a cross key alphabetized by long
 option.
 
-@c Please, keep this ordered as in `bison --help'.
+@c Please, keep this ordered as in 'bison --help'.
 @noindent
 Operations modes:
 @table @option
@@ -9366,6 +9971,76 @@ unexpected number of conflicts is an error, and an expected number of
 conflicts is not reported, so @option{-W} and @option{--warning} then have
 no effect on the conflict report.
 
+@item deprecated
+Deprecated constructs whose support will be removed in future versions of
+Bison.
+
+@item empty-rule
+Empty rules without @code{%empty}.  @xref{Empty Rules}.  Disabled by
+default, but enabled by uses of @code{%empty}, unless
+@option{-Wno-empty-rule} was specified.
+
+@item precedence
+Useless precedence and associativity directives.  Disabled by default.
+
+Consider for instance the following grammar:
+
+@example
+@group
+%nonassoc "="
+%left "+"
+%left "*"
+%precedence "("
+@end group
+%%
+@group
+stmt:
+  exp
+| "var" "=" exp
+;
+@end group
+
+@group
+exp:
+  exp "+" exp
+| exp "*" "num"
+| "(" exp ")"
+| "num"
+;
+@end group
+@end example
+
+Bison reports:
+
+@c cannot leave the location and the [-Wprecedence] for lack of
+@c width in PDF.
+@example
+@group
+warning: useless precedence and associativity for "="
+ %nonassoc "="
+           ^^^
+@end group
+@group
+warning: useless associativity for "*", use %precedence
+ %left "*"
+       ^^^
+@end group
+@group
+warning: useless precedence for "("
+ %precedence "("
+             ^^^
+@end group
+@end example
+
+One would get the exact same parser with the following directives instead:
+
+@example
+@group
+%left "+"
+%precedence "*"
+@end group
+@end example
+
 @item other
 All warnings not categorized above.  These warnings are enabled by default.
 
@@ -9374,17 +10049,40 @@ releases of Bison may move warnings from this category to new, more specific
 categories.
 
 @item all
-All the warnings.
+All the warnings except @code{yacc}.
+
 @item none
 Turn off all the warnings.
+
 @item error
-Treat warnings as errors.
+See @option{-Werror}, below.
 @end table
 
 A category can be turned off by prefixing its name with @samp{no-}.  For
 instance, @option{-Wno-yacc} will hide the warnings about
 POSIX Yacc incompatibilities.
 
+@item -Werror[=@var{category}]
+@itemx -Wno-error[=@var{category}]
+Enable warnings falling in @var{category}, and treat them as errors.  If no
+@var{category} is given, it defaults to making all enabled warnings into errors.
+
+@var{category} is the same as for @option{--warnings}, with the exception that
+it may not be prefixed with @samp{no-} (see above).
+
+Prefixed with @samp{no}, it deactivates the error treatment for this
+@var{category}. However, the warning itself won't be disabled, or enabled, by
+this option.
+
+Note that the precedence of the @samp{=} and @samp{,} operators is such that
+the following commands are @emph{not} equivalent, as the first will not treat
+S/R conflicts as errors.
+
+@example
+$ bison -Werror=yacc,conflicts-sr input.y
+$ bison -Werror=yacc,error=conflicts-sr input.y
+@end example
+
 @item -f [@var{feature}]
 @itemx --feature[=@var{feature}]
 Activate miscellaneous @var{feature}. @var{feature} can be one of:
@@ -9403,7 +10101,7 @@ an example, using the following file @file{in.y}:
 exp: exp '+' exp @{ $exp = $1 + $2; @};
 @end example
 
-When invoked with @option{-fcaret}, Bison will report:
+When invoked with @option{-fcaret} (or nothing), Bison will report:
 
 @example
 @group
@@ -9433,6 +10131,20 @@ in.y:3.32-33: error: $2 of 'exp' has no declared type
 @end group
 @end example
 
+Whereas, when invoked with @option{-fno-caret}, Bison will only report:
+
+@example
+@group
+in.y:3.20-23: error: ambiguous reference: â€˜$exp’
+in.y:3.1-3:       refers to: $exp at $$
+in.y:3.6-8:       refers to: $exp at $1
+in.y:3.14-16:     refers to: $exp at $3
+in.y:3.32-33: error: $2 of â€˜exp’ has no declared type
+@end group
+@end example
+
+This option is activated by default.
+
 @end table
 @end table
 
@@ -9676,17 +10388,18 @@ The C++ deterministic parser is selected using the skeleton directive,
 
 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.  These files are not generated if the @code{%define}
-variable @code{api.location.type} is defined.  @xref{C++ Location Values}.
+location tracking when enabled.  These files are not generated if the
+@code{%define} variable @code{api.location.type} is defined.  @xref{C++
+Location Values}.
 
 @item stack.hh
 An auxiliary class @code{stack} used by the parser.
@@ -9712,11 +10425,22 @@ for a complete and accurate documentation.
 @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++.
+Union Declaration}.  In particular it produces a genuine
+@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
@@ -9733,6 +10457,89 @@ reclaimed automatically: using the @code{%destructor} directive is the
 only means to avoid leaks.  @xref{Destructor Decl, , Freeing Discarded
 Symbols}.
 
+@node C++ Variants
+@subsubsection C++ Variants
+
+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
+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
@@ -9755,8 +10562,8 @@ In this section @code{uint} is an abbreviation for @code{unsigned int}: in
 genuine code only the latter is used.
 
 @menu
-* C++ position::                One point in the source file
-* C++ location::                Two points in the source file
+* C++ position::         One point in the source file
+* C++ location::         Two points in the source file
 * User Defined Location Type::  Required interface for locations
 @end menu
 
@@ -9937,7 +10744,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}
@@ -9948,11 +10755,27 @@ use @code{yy::parser::token::FOO}.  The scanner can use
 (@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.
 
@@ -9975,9 +10798,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
 
 
@@ -9989,25 +10814,144 @@ described by @var{m}.
 
 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 full} 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
+
+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 api.value.type variant} and
+@code{%define api.token.constructor},
+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.token.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.token.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
@@ -10071,11 +11015,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
@@ -10099,8 +11040,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
@@ -10115,9 +11056,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
 
@@ -10199,19 +11144,35 @@ the grammar for.
 %define parser_class_name "calcxx_parser"
 @end example
 
+@noindent
+@findex %define api.token.constructor
+@findex %define api.value.type variant
+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{api.token.constructor}.
+
+@comment file: calc++-parser.yy
+@example
+%define api.token.constructor
+%define api.value.type variant
+%define parse.assert
+@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;
 @}
@@ -10225,15 +11186,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
@@ -10246,28 +11206,14 @@ automatically propagated.
 @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
@@ -10277,7 +11223,8 @@ The code between @samp{%code @{} and @samp{@}} is output in the
 
 @comment file: calc++-parser.yy
 @example
-%code @{
+%code
+@{
 # include "calc++-driver.hh"
 @}
 @end example
@@ -10285,35 +11232,52 @@ The code between @samp{%code @{} and @samp{@}} is output in the
 
 @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.token.prefix}).
 
 @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
+%define api.token.prefix "TOK_"
+%token
+  END  0  "end of file"
+  ASSIGN  ":="
+  MINUS   "-"
+  PLUS    "+"
+  STAR    "*"
+  SLASH   "/"
+  LPAREN  "("
+  RPAREN  ")"
+;
 @end example
 
 @noindent
-To enable memory deallocation during error recovery, use
-@code{%destructor}.
+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.
 
-@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"
+%token <std::string> IDENTIFIER "identifier"
+%token <int> NUMBER "number"
+%type  <int> exp
+@end example
+
+@noindent
+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<<} (@pxref{Printer Decl, , Printing Semantic Values}).
 
-%printer    @{ yyoutput << $$; @} <ival>
+@comment file: calc++-parser.yy
+@example
+%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
@@ -10322,21 +11286,22 @@ The grammar itself is straightforward.
 unit: assignments exp  @{ driver.result = $2; @};
 
 assignments:
-  /* Nothing.  */        @{@}
+  %empty                 @{@}
 | 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
 
@@ -10347,7 +11312,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);
@@ -10363,24 +11328,22 @@ parser's to get the set of defined tokens.
 @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
 
@@ -10388,11 +11351,11 @@ parser's to get the set of defined tokens.
 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
-%option noyywrap nounput batch debug
+%option noyywrap nounput batch debug noinput
 @end example
 
 @noindent
@@ -10408,8 +11371,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.
@@ -10418,57 +11381,51 @@ 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;
-
-@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;
-         @}
-@end group
-
-@group
-@{id@}     @{
-           yylval->sval = new std::string (yytext);
-           return token::IDENTIFIER;
-         @}
+"-"      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 (loc, "integer is out of range");
+  return yy::calcxx_parser::make_NUMBER(n, loc);
+@}
 @end group
-
-.        driver.error (*yylloc, "invalid character");
+@{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
@@ -10511,6 +11468,7 @@ The top level file, @file{calc++.cc}, poses no problem.
 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"))
@@ -10519,6 +11477,9 @@ main (int argc, char *argv[])
       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
@@ -10563,8 +11524,7 @@ You can create documentation for generated parsers using Javadoc.
 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 full} directives does not do anything when used in
-Java.
+and @code{%define api.pure} directives do nothing when used in Java.
 
 Push parsers are currently unsupported in Java and @code{%define
 api.push-pull} have no effect.
@@ -10576,15 +11536,23 @@ No header file can be generated for Java parsers.  Do not use the
 @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.
@@ -10603,11 +11571,11 @@ semantic values' types (class names) should be specified in the
 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 api.value.type}
 directive.  For example, after the following declaration:
 
 @example
-%define stype "ASTNode"
+%define api.value.type "ASTNode"
 @end example
 
 @noindent
@@ -10681,20 +11649,22 @@ properly, the position class should override the @code{equals} and
 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
@@ -10703,30 +11673,33 @@ these inner class/interface, and the members described in the interface
 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 ()
@@ -10734,6 +11707,21 @@ Run the syntactic analysis, and return @code{true} on success,
 @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.
@@ -10752,6 +11740,11 @@ Get or set the tracing level.  Currently its value is either 0, no trace,
 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
@@ -10762,7 +11755,9 @@ or nonzero, full tracing.
 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
@@ -10789,7 +11784,7 @@ Return the next token.  Its type is the return value, its semantic
 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
 
@@ -10806,7 +11801,7 @@ The return type can be changed using @code{%define api.position.type
 @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 api.value.type
 "@var{class-name}".}
 @end deftypemethod
 
@@ -10817,7 +11812,7 @@ The return type can be changed using @code{%define stype
 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}
@@ -10834,7 +11829,7 @@ Like @code{$@var{n}} but specifies a alternative type @var{typealt}.
 @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 api.value.type}) 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}.
@@ -10881,11 +11876,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
 
 
@@ -10915,7 +11911,7 @@ corresponds to these C macros.}.
 @item
 Java lacks unions, so @code{%union} has no effect.  Instead, semantic
 values have a common base type: @code{Object} or as specified by
-@samp{%define stype}.  Angle brackets on @code{%token}, @code{type},
+@samp{%define api.value.type}.  Angle brackets on @code{%token}, @code{type},
 @code{$@var{n}} and @code{$$} specify subtypes rather than fields of
 an union.  The type of @code{$$}, even with angle brackets, is the base
 type since Java casts are not allow on the left-hand side of assignments.
@@ -10929,7 +11925,7 @@ The prologue declarations have a different meaning than in C/C++ code.
 @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.
@@ -10970,7 +11966,7 @@ constructor that @emph{creates} a lexer.  Default is none.
 
 @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
 
@@ -11001,6 +11997,11 @@ Code inserted just after the @code{package} declaration.
 @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}.
@@ -11013,7 +12014,7 @@ Code (after the second @code{%%}) appended to the end of the file,
 @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
 
@@ -11022,6 +12023,11 @@ Whether the parser class is declared @code{abstract}.  Default is false.
 @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}.
@@ -11038,6 +12044,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}.
@@ -11075,7 +12087,7 @@ Whether the parser class is declared @code{public}.  Default is false.
 @xref{Java Bison Interface}.
 @end deffn
 
-@deffn {Directive} {%define stype} "@var{class}"
+@deffn {Directive} {%define api.value.type} "@var{class}"
 The base type of semantic values.  Default is @code{Object}.
 @xref{Java Semantic Values}.
 @end deffn
@@ -11449,7 +12461,7 @@ operating system's name and version and your compiler's name and
 version.  If you have trouble compiling, you should also include a
 transcript of the build session, starting with the invocation of
 `configure'.  Depending on the nature of the bug, you may be asked to
-send additional files as well (such as `config.h' or `config.cache').
+send additional files as well (such as @file{config.h} or @file{config.cache}).
 
 Patches are most welcome, but not required.  That is, do not hesitate to
 send a bug report just because you cannot provide a fix.
@@ -11558,6 +12570,19 @@ the grammar file.  @xref{Grammar Outline, ,Outline of a Bison
 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{} */
 @deffnx {Construct} // @dots{}
 Comments, as in C/C++.
@@ -11651,6 +12676,11 @@ time to resolve reduce/reduce conflicts.  @xref{GLR Parsers, ,Writing
 GLR Parsers}.
 @end deffn
 
+@deffn {Directive} %empty
+Bison declaration to declare make explicit that a rule has an empty
+right-hand side.  @xref{Empty Rules}.
+@end deffn
+
 @deffn {Symbol} $end
 The predefined token marking the end of the token stream.  It cannot be
 used in the grammar.
@@ -11668,8 +12698,8 @@ token is reset to the token that originally caused the violation.
 @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}"
@@ -11692,12 +12722,12 @@ Specify the programming language for the generated parser.
 @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
@@ -11742,7 +12772,7 @@ parser implementation file.  @xref{Decl Summary}.
 @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
 
@@ -11751,10 +12781,15 @@ Bison declaration to set the name of the parser implementation file.
 @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
@@ -11762,8 +12797,13 @@ Bison declaration to assign a precedence to a specific rule.
 @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
@@ -11774,7 +12814,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
 
@@ -11811,7 +12851,7 @@ The predefined token onto which all undefined values returned by
 
 @deffn {Directive} %union
 Bison declaration to specify several possible data types for semantic
-values.  @xref{Union Decl, ,The Collection of Value Types}.
+values.  @xref{Union Decl, ,The Union Declaration}.
 @end deffn
 
 @deffn {Macro} YYABORT
@@ -11879,17 +12919,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
@@ -11908,13 +12947,6 @@ the next token.  @xref{Lexical, ,The Lexical Analyzer Function
 @code{yylex}}.
 @end deffn
 
-@deffn {Macro} YYLEX_PARAM
-An obsolete macro for specifying an extra argument (or list of extra
-arguments) for @code{yyparse} to pass to @code{yylex}.  The use of this
-macro is deprecated, and is supported only for Yacc like parsers.
-@xref{Pure Calling,, Calling Conventions for Pure Parsers}.
-@end deffn
-
 @deffn {Variable} yylloc
 External variable in which @code{yylex} should place the line and column
 numbers associated with a token.  (In a pure parser, it is a local
@@ -11950,7 +12982,7 @@ Management}.
 @deffn {Variable} yynerrs
 Global variable which Bison increments each time it reports a syntax error.
 (In a pure parser, it is a local variable within @code{yyparse}. In a
-pure push parser, it is a member of yypstate.)
+pure push parser, it is a member of @code{yypstate}.)
 @xref{Error Reporting, ,The Error Reporting Function @code{yyerror}}.
 @end deffn
 
@@ -12000,13 +13032,6 @@ parse a single token.  @xref{Push Parser Function, ,The Push Parser Function
 More user feedback will help to stabilize it.)
 @end deffn
 
-@deffn {Macro} YYPARSE_PARAM
-An obsolete macro for specifying the name of a parameter that
-@code{yyparse} should accept.  The use of this macro is deprecated, and
-is supported only for Yacc like parsers.  @xref{Pure Calling,, Calling
-Conventions for Pure Parsers}.
-@end deffn
-
 @deffn {Macro} YYRECOVERING
 The expression @code{YYRECOVERING ()} yields 1 when the parser
 is recovering from a syntax error, and 0 otherwise.
@@ -12031,6 +13056,7 @@ require some expertise in low-level implementation details.
 @end deffn
 
 @deffn {Type} YYSTYPE
+Deprecated in favor of the @code{%define} variable @code{api.value.type}.
 Data type of semantic values; @code{int} by default.
 @xref{Value Type, ,Data Types of Semantic Values}.
 @end deffn
index 1eaa9fdf62c269bc7ba76977a4522fd57188ca70..edaebe830cf385be1c0823892e2347f527e579e5 100644 (file)
@@ -39,7 +39,7 @@ This description of the options that can be given to
 is adapted from the node
 .B Invocation
 in the
-.B bison.texinfo
+.B bison.texi
 manual, which should be taken as authoritative.
 .PP
 .I Bison
@@ -53,3 +53,8 @@ are unique.  When a long option takes an argument, like
 .BR \-\-file-prefix ,
 connect the option name and the argument with
 .BR = .
+
+[see also]
+.BR lex (1),
+.BR flex (1),
+.BR yacc (1).
diff --git a/doc/common.x b/doc/common.x
deleted file mode 100644 (file)
index 60224c3..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-[see also]
-.BR lex (1),
-.BR flex (1),
-.BR yacc (1).
diff --git a/doc/local.mk b/doc/local.mk
new file mode 100644 (file)
index 0000000..afd50dd
--- /dev/null
@@ -0,0 +1,176 @@
+## Copyright (C) 2001-2003, 2005-2013 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/>.
+
+AM_MAKEINFOFLAGS = --no-split
+info_TEXINFOS = doc/bison.texi
+doc_bison_TEXINFOS =                            \
+  $(CROSS_OPTIONS_TEXI)                         \
+  doc/fdl.texi                                  \
+  doc/gpl-3.0.texi
+
+# Cannot express dependencies directly on file names because of Automake.
+# Obfuscate with a variable.
+doc_bison = doc/bison
+$(doc_bison).dvi: $(FIGS_DOT:.dot=.eps)
+$(doc_bison).pdf: $(FIGS_DOT:.dot=.pdf)
+$(doc_bison).html: $(FIGS_DOT:.dot=.png)
+
+TEXI2DVI = texi2dvi --build-dir=doc/bison.t2d -I doc
+CLEANDIRS = doc/bison.t2d
+clean-local:
+       rm -rf $(CLEANDIRS)
+
+MOSTLYCLEANFILES += $(top_srcdir)/doc/*.t
+
+CROSS_OPTIONS_PL = $(top_srcdir)/build-aux/cross-options.pl
+CROSS_OPTIONS_TEXI = $(top_srcdir)/doc/cross-options.texi
+$(CROSS_OPTIONS_TEXI): doc/bison.help $(CROSS_OPTIONS_PL)
+# Create $@~ which is the previous contents.  Don't use 'mv' here so
+# that even if we are interrupted, the file is still available for
+# diff in the next run.  Note that $@ might not exist yet.
+       $(AM_V_GEN){ test ! -f $@ || cat $@; } >$@~
+       $(AM_V_at)test ! -f $@.tmp || rm -f $@.tmp
+       $(AM_V_at)src/bison$(EXEEXT) --help |                            \
+         $(PERL) $(CROSS_OPTIONS_PL) $(top_srcdir)/src/scan-gram.l >$@.tmp
+       $(AM_V_at)diff -u $@~ $@.tmp || true
+       $(AM_V_at)mv $@.tmp $@
+MAINTAINERCLEANFILES = $(CROSS_OPTIONS_TEXI)
+
+## ---------- ##
+## Ref card.  ##
+## ---------- ##
+
+EXTRA_DIST += doc/refcard.tex
+CLEANFILES += doc/refcard.pdf
+
+doc/refcard.pdf: doc/refcard.tex
+       $(AM_V_GEN) cd doc && pdftex $(abs_top_srcdir)/doc/refcard.tex
+
+
+
+## ---------------- ##
+## doc/bison.help.  ##
+## ---------------- ##
+
+# Some of our targets (cross-option.texi, bison.1) use "bison --help".
+# Since we want to ship the generated file to avoid additional
+# requirements over the user environment, we used not depend on
+# src/bison itself, but on src/getargs.c and other files.  Yet, we
+# need "bison --help" to work to make help2man happy, so we used to
+# include "make src/bison" in the commands.  Then we may have a
+# problem with concurrent builds, since one make might be aiming one
+# of its jobs at compiling src/bison, and another job at generating
+# the man page.  If the latter is faster than the former, then we have
+# two makes that concurrently try to compile src/bison.  Doomed to
+# failure.
+#
+# As a simple scheme to get our way out, make a stamp file,
+# bison.help, which contains --version then --help.  This file can
+# depend on bison, which ensures its correctness.  But update it
+# *only* if needed (content changes).  This way, we avoid useless
+# compilations of cross-option.texi and bison.1.  At the cost of
+# repeated builds of bison.help.
+
+EXTRA_DIST += $(top_srcdir)/doc/bison.help
+MAINTAINERCLEANFILES += $(top_srcdir)/doc/bison.help
+$(top_srcdir)/doc/bison.help: src/bison$(EXEEXT)
+       $(AM_V_GEN)src/bison$(EXEEXT) --version >doc/bison.help.tmp
+       $(AM_V_at) src/bison$(EXEEXT) --help   >>doc/bison.help.tmp
+       $(AM_V_at)$(top_srcdir)/build-aux/move-if-change doc/bison.help.tmp $@
+
+
+## ----------- ##
+## Man Pages.  ##
+## ----------- ##
+
+dist_man_MANS = $(top_srcdir)/doc/bison.1
+
+EXTRA_DIST += $(dist_man_MANS:.1=.x)
+MAINTAINERCLEANFILES += $(dist_man_MANS)
+
+# Differences to ignore when comparing the man page (the date).
+remove_time_stamp = \
+  sed 's/^\(\.TH[^"]*"[^"]*"[^"]*\)"[^"]*"/\1/'
+
+# Depend on configure to get version number changes.
+$(top_srcdir)/doc/bison.1: doc/bison.help doc/bison.x $(top_srcdir)/configure
+       $(AM_V_GEN)$(HELP2MAN)                  \
+           --include=$(top_srcdir)/doc/bison.x \
+           --output=$@.t src/bison$(EXEEXT)
+       $(AM_V_at)if $(remove_time_stamp) $@ >$@a.t 2>/dev/null &&       \
+          $(remove_time_stamp) $@.t | cmp $@a.t - >/dev/null 2>&1; then \
+         touch $@;                                                      \
+       else                                                             \
+         mv $@.t $@;                                                    \
+       fi
+       $(AM_V_at)rm -f $@*.t
+
+nodist_man_MANS = doc/yacc.1
+
+## ----------------------------- ##
+## Graphviz examples generation. ##
+## ----------------------------- ##
+
+CLEANDIRS += doc/figs
+FIGS_DOT =                                                      \
+  doc/figs/example.dot                                          \
+  doc/figs/example-reduce.dot doc/figs/example-shift.dot
+EXTRA_DIST +=                                                           \
+  $(FIGS_DOT)                                                           \
+  $(FIGS_DOT:.dot=.eps) $(FIGS_DOT:.dot=.pdf) $(FIGS_DOT:.dot=.png)
+SUFFIXES += .dot .eps .pdf .png
+
+.dot.eps:
+       $(AM_V_GEN) $(MKDIR_P) `echo "./$@" | sed -e 's,/[^/]*$$,,'`
+       $(AM_V_at) $(DOT) -Gmargin=0 -Teps $< >$@.tmp
+       $(AM_V_at) mv $@.tmp $@
+
+.dot.pdf:
+       $(AM_V_GEN) $(MKDIR_P) `echo "./$@" | sed -e 's,/[^/]*$$,,'`
+       $(AM_V_at) $(DOT) -Gmargin=0 -Tpdf $< >$@.tmp
+       $(AM_V_at) mv $@.tmp $@
+
+.dot.png:
+       $(AM_V_GEN) $(MKDIR_P) `echo "./$@" | sed -e 's,/[^/]*$$,,'`
+       $(AM_V_at) $(DOT) -Gmargin=0 -Tpng $< >$@.tmp
+       $(AM_V_at) mv $@.tmp $@
+
+## -------------- ##
+## Doxygenation.  ##
+## -------------- ##
+
+DOXYGEN = doxygen
+
+.PHONY: doc html
+
+doc: html
+
+html-local: doc/Doxyfile
+       $(AM_V_GEN) $(DOXYGEN) doc/Doxyfile
+
+edit = sed -e 's,@PACKAGE_NAME\@,$(PACKAGE_NAME),g' \
+          -e 's,@PACKAGE_VERSION\@,$(PACKAGE_VERSION),g' \
+          -e 's,@PERL\@,$(PERL),g' \
+          -e 's,@top_builddir\@,$(top_builddir),g' \
+          -e 's,@top_srcdir\@,$(top_srcdir),g'
+
+EXTRA_DIST += doc/Doxyfile.in
+CLEANFILES += doc/Doxyfile
+# Sed is used to generate Doxyfile from Doxyfile.in instead of
+# configure, because the former is way faster than the latter.
+doc/Doxyfile: $(top_srcdir)/doc/Doxyfile.in
+       $(AM_V_GEN) $(edit) $(top_srcdir)/doc/Doxyfile.in >doc/Doxyfile
+
+CLEANDIRS += doc/html
index db2e7575a3a1d11315383208c81fdbf7e2bbe4dc..d644d12260b8ac0a7e51d4670012cf21aea57711 100644 (file)
@@ -1,3 +1 @@
-/Makefile
-/Makefile.in
 /bench.pl
diff --git a/etc/Makefile.am b/etc/Makefile.am
deleted file mode 100644 (file)
index 17c6ca8..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-## Copyright (C) 2006, 2009-2013 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/>.
-
-nodist_noinst_SCRIPTS = bench.pl
index 66cb240c3d4bb54ca567d10a6910243ec9e938be..30d0a996e611a3b73acb871c9e45132686b44879 100755 (executable)
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+=head1 NAME
+
+bench.pl - bench marks for Bison parsers.
+
+=head1 SYNOPSIS
+
+  ./bench.pl [OPTIONS]... DIRECTIVES
+
+=head1 DIRECTIVES
+
+Specify the set of benches to run.  The following grammar defines the
+I<directives>:
+
+   directives ::=
+       directives | directives  -- Alternation
+     | directives & directives  -- Concatenation
+     | [ directives> ]          -- Optional
+     | ( directives> )          -- Parentheses
+     | %b PATH                  -- Use bison at PATH for this bench
+     | #d NAME[=VALUE]          -- %code { #define NAME [VALUE] }
+     | %d NAME[=VALUE]          -- %define NAME ["VALUE"]
+     | %s skeleton              -- %skeleton "skeleton"
+     | directive
+
+Parentheses only group to override precedence.  For instance:
+
+  [ %debug ] & [ %error-verbose ] & [ %define variant ]
+
+will generate eight different cases.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-b>, B<--bench>
+
+Predefined benches, that is, combimation between a grammar and a I<directives>
+request.
+
+=over 4
+
+=item I<push>
+
+Test the push parser vs. the pull interface.  Use the C parser.
+
+=item I<variant>
+
+Test the use of variants instead of union in the C++ parser.
+
+=back
+
+=item B<-c>, B<--cflags>=I<flags>
+
+Flags to pass to the C or C++ compiler.  Defaults to -O2.
+
+=item B<-d>, B<--directive>=I<directives>
+
+Add a set of Bison directives to bench against each other.
+
+=item B<-g>, B<--grammar>=I<grammar>
+
+Select the base I<grammar> to use.  Defaults to I<calc>.
+
+=over 4
+
+=item I<calc>
+
+Traditional calculator.
+
+=item I<list>
+
+C++ grammar that uses std::string and std::list.  Can be used with
+or without %define variant.
+
+=item I<triangular>
+
+Artificial grammar with very long rules.
+
+=back
+
+=item B<-h>, B<--help>
+
+Display this message and exit succesfully.  The more verbose, the more
+details.
+
+=item B<-i>, B<--iterations>=I<integer>
+
+Say how many times a single test of the bench must be run.  If
+negative, specify the minimum number of CPU seconds to run.  Defaults
+to -1.
+
+=item B<-q>, B<--quiet>
+
+Decrease the verbosity level (defaults to 1).
+
+=item B<-v>, B<--verbose>
+
+Raise the verbosity level (defaults to 1).
+
+=back
+
+=cut
+
+use strict;
 use IO::File;
-use Benchmark qw (:all);
 
+##################################################################
+
+=head1 VARIABLES
+
+=over 4
+
+=item C<@bench>
+
+The list of benches to run.
+
+=item C<$bison>
+
+The Bison program to use to compile the grammar.
+
+=item C<$cc>
+
+The C compiler.
+
+=item C<$cxx>
+
+The C++ compiler.
+
+=item C<$cflags>
+
+Compiler flags (C or C++).
+
+=item C<@directive>
+
+A list of directive sets to measure against each other.
+
+=item C<$iterations>
+
+The number of times the parser is run for a bench.
+
+=item C<$verbose>
+
+Verbosity level.
+
+=back
+
+=cut
+
+my $bench;
 my $bison = $ENV{'BISON'} || '@abs_top_builddir@/tests/bison';
 my $cc = $ENV{'CC'} || 'gcc';
+my $cxx = $ENV{'CXX'} || 'g++';
+my $cflags = '-O2';
+my @directive = ();
+my $grammar = 'calc';
+my $iterations = -1;
+my $verbose = 1;
 
-##################################################################
+=head1 FUNCTIONS
+
+=over 4
+
+=item C<verbose($level, $message)>
+
+Report the C<$message> is C<$level> E<lt>= C<$verbose>.
 
-sub triangular_grammar ($$$)
+=cut
+
+sub verbose($$)
 {
-  my ($base, $max, $directives) = @_;
+  my ($level, $message) = @_;
+  print STDERR $message
+    if $level <= $verbose;
+}
+
+
+######################################################################
+
+=item C<directives($bench, @directive)>
+
+Format the list of directives for Bison for bench named C<$bench>.
+
+=cut
+
+sub directives($@)
+{
+  my ($bench, @directive) = @_;
+  my $res = "/* Directives for bench '$bench'. */\n";
+  $res .= join ("\n", @directive) . "\n";
+  $res .= "/* End of directives for bench '$bench'. */\n";
+  return $res;
+}
+
+######################################################################
+
+=item C<generate_grammar_triangular ($base, $max, @directive)>
+
+Create a large triangular grammar which looks like :
+
+  input:
+    exp        { if ($1 != 0) abort (); $$ = $1; }
+  | input exp  { if ($2 != $1 + 1) abort (); $$ = $2; }
+  ;
+
+  exp:
+    END                         { $$ = 0; }
+  | "1"  END                    { $$ = 1; }
+  | "1" "2"  END                { $$ = 2; }
+  | "1" "2" "3"  END            { $$ = 3; }
+  | "1" "2" "3" "4"  END        { $$ = 4; }
+  | "1" "2" "3" "4" "5"  END    { $$ = 5; }
+  ;
+
+C<$base> is the base name for the file to create (F<$base.y>).
+C<$max> is the number of such rules (here, 5).  You may pass
+additional Bison C<@directive>.
+
+The created parser is self contained: it includes its scanner, and
+source of input.
+=cut
+
+sub generate_grammar_triangular ($$@)
+{
+  my ($base, $max, @directive) = @_;
+  my $directives = directives ($base, @directive);
 
   my $out = new IO::File ">$base.y"
     or die;
   print $out <<EOF;
 %error-verbose
-%debug
 %{
 #include <stdio.h>
 #include <stdlib.h>
@@ -41,6 +254,7 @@ sub triangular_grammar ($$$)
 static int yylex (void);
 static void yyerror (const char *msg);
 %}
+$directives
 %union
 {
   int val;
@@ -71,8 +285,8 @@ for my $size (1 .. $max)
   {
     use Text::Wrap;
     print $out wrap ("| ", "   ",
-                    (map { "\"$_\"" } (1 .. $size)),
-                    " END \n"),
+                     (map { "\"$_\"" } (1 .. $size)),
+                     " END \n"),
                "    { \$\$ = $size; }\n";
   };
 print $out ";\n";
@@ -104,7 +318,9 @@ yyerror (const char *msg)
 int
 main (void)
 {
+#if YYDEBUG
   yydebug = !!getenv ("YYDEBUG");
+#endif
   return yyparse ();
 }
 EOF
@@ -112,6 +328,15 @@ EOF
 
 ##################################################################
 
+=item C<calc_input ($base, $max)>
+
+Generate the input file F<$base.input> for the calc parser.  The input
+is composed of two expressions.  The first one is using left recursion
+only and consumes no stack.  The second one requires a deep stack.
+These two expressions are repeated C<$max> times in the output file.
+
+=cut
+
 sub calc_input ($$)
 {
   my ($base, $max) = @_;
@@ -126,9 +351,22 @@ sub calc_input ($$)
 
 ##################################################################
 
-sub calc_grammar ($$$)
+=item C<generate_grammar_calc ($base, $max, @directive)>
+
+Generate a Bison file F<$base.y> for a calculator parser in C.  Pass
+the additional Bison C<@directive>.  C<$max> is ignored, but left to
+have the same interface as C<triangular_grammar>.
+
+=cut
+
+sub generate_grammar_calc ($$@)
 {
-  my ($base, $max, $directives) = @_;
+  my ($base, $max, @directive) = @_;
+  my $directives = directives ($base, @directive);
+
+  # Putting this request here is stupid, since the input will be
+  # generated each time we generate a grammar.
+  calc_input ('calc', 200);
 
   my $out = new IO::File ">$base.y"
     or die;
@@ -148,9 +386,9 @@ static semantic_value global_result = 0;
 static int global_count = 0;
 %}
 
-/* Exercise %union. */
 $directives
 %error-verbose
+/* Exercise %union. */
 %union
 {
   semantic_value ival;
@@ -174,7 +412,7 @@ static int yylex (void);
 %token <ival> NUM "number"
 %type  <ival> exp
 
-%nonassoc '=' /* comparison           */
+%nonassoc '=' /* comparison            */
 %left '-' '+'
 %left '*' '/'
 %left NEG     /* negation--unary minus */
@@ -306,6 +544,10 @@ main (int argc, const char **argv)
   int count = 0;
   int status;
 
+#if YYDEBUG
+  yydebug = !!getenv ("YYDEBUG");
+#endif
+
   input = fopen ("calc.input", "r");
   if (!input)
     {
@@ -326,44 +568,567 @@ EOF
 
 ##################################################################
 
-sub compile ($)
+=item C<generate_grammar_list ($base, $max, @directive)>
+
+Generate a Bison file F<$base.y> for a C++ parser that uses C++
+objects (std::string, std::list).  Tailored for using %define variant.
+
+=cut
+
+sub generate_grammar_list ($$@)
 {
-  my ($base) = @_;
-  system ("$bison $base.y -o $base.c") == 0
-    or die;
-  system ("$cc -o $base $base.c") == 0
+  my ($base, $max, @directive) = @_;
+  my $directives = directives ($base, @directive);
+  my $variant = grep { /%define "?variant"?/ } @directive;
+  my $token_ctor = grep { /%define "?api.token.constructor"?/ } @directive;
+  my $out = new IO::File ">$base.y"
     or die;
+  print $out <<EOF;
+%language "C++"
+%defines
+%locations
+$directives
+
+%code requires // *.h
+{
+#include <string>
 }
 
-sub bench_grammar ($)
+%code // *.c
 {
-  my ($gram) = @_;
-  my %test =
+#include <algorithm>
+#include <iostream>
+#include <sstream>
+
+#define STAGE_MAX    ($max * 10) // max = $max
+
+#define USE_TOKEN_CTOR $token_ctor
+#define USE_VARIANTS $variant
+
+  // Prototype of the yylex function providing subsequent tokens.
+  static
+#if USE_TOKEN_CTOR
+  yy::parser::symbol_type yylex();
+#else
+  yy::parser::token_type yylex(yy::parser::semantic_type* yylvalp,
+                               yy::parser::location_type* yyllocp);
+#endif
+
+  // Conversion to string.
+  template <typename T>
+    inline
+    std::string
+    string_cast (const T& t)
+  {
+    std::ostringstream o;
+    o << t;
+    return o.str ();
+  }
+}
+
+%token END_OF_FILE 0
+EOF
+
+  if ($variant)
+    {
+      print $out <<'EOF';
+%token <std::string> TEXT
+%token <int> NUMBER
+%printer { std::cerr << "Number: " << $$; } <int>
+%printer { std::cerr << "Text: " << $$; } <std::string>
+%type <std::string> text result
+
+%%
+result:
+  text                  { /* Throw away the result. */ }
+;
+
+text:
+  /* nothing */         { /* This will generate an empty string */ }
+| text TEXT             { std::swap ($$, $2); }
+| text NUMBER           { $$ = string_cast($2); }
+;
+EOF
+    }
+  else
+    {
+      # Not using Bison variants.
+      print $out <<'EOF';
+%union {int ival; std::string* sval;}
+%token <sval> TEXT
+%token <ival> NUMBER
+%printer { std::cerr << "Number: " << $$; } <ival>
+%printer { std::cerr << "Text: " << *$$; } <sval>
+%type <sval> text result
+
+%%
+result:
+  text                  { delete $1; }
+;
+
+text:
+  /* nothing */         { $$ = new std::string; }
+| text TEXT             { delete $1; $$ = $2; }
+| text NUMBER           { delete $1; $$ = new std::string (string_cast ($2)); }
+;
+EOF
+    }
+
+  print $out <<'EOF';
+%%
+#
+
+static
+#if USE_TOKEN_CTOR
+yy::parser::symbol_type yylex()
+#else
+yy::parser::token_type yylex(yy::parser::semantic_type* yylvalp,
+                             yy::parser::location_type* yyllocp)
+#endif
+{
+  typedef yy::parser::location_type location_type;
+  typedef yy::parser::token token;
+  static int stage = -1;
+  ++stage;
+  if (stage == STAGE_MAX)
+    {
+#if USE_TOKEN_CTOR
+      return yy::parser::make_END_OF_FILE (location_type ());
+#else
+      *yyllocp = location_type ();
+      return token::END_OF_FILE;
+#endif
+    }
+  else if (stage % 2)
+    {
+#if USE_TOKEN_CTOR
+      return yy::parser::make_NUMBER (stage, location_type ());
+#else
+# if defined ONE_STAGE_BUILD
+      yylvalp->build(stage);
+# elif USE_VARIANTS
+      yylvalp->build<int>() = stage;
+# else
+      yylvalp->ival = stage;
+# endif
+      *yyllocp = location_type ();
+      return token::NUMBER;
+#endif
+    }
+  else
+    {
+#if USE_TOKEN_CTOR
+      return yy::parser::make_TEXT ("A string.", location_type ());
+#else
+# if defined ONE_STAGE_BUILD
+      yylvalp->build(std::string("A string."));
+# elif USE_VARIANTS
+      yylvalp->build<std::string>() = std::string("A string.");
+# else
+      yylvalp->sval = new std::string("A string.");
+# endif
+      *yyllocp = location_type ();
+      return token::TEXT;
+#endif
+    }
+  abort();
+}
+
+// Mandatory error function
+void
+yy::parser::error(const yy::parser::location_type& loc, const std::string& msg)
+{
+  std::cerr << loc << ": " << msg << std::endl;
+}
+
+int main(int argc, char *argv[])
+{
+  yy::parser p;
+#if YYDEBUG
+  p.set_debug_level(!!getenv("YYDEBUG"));
+#endif
+  p.parse();
+  return 0;
+}
+EOF
+}
+
+##################################################################
+
+=item C<generate_grammar ($name, $base, @directive)>
+
+Generate F<$base.y> by calling C<&generate_grammar_$name>.
+
+=cut
+
+sub generate_grammar ($$@)
+{
+  my ($name, $base, @directive) = @_;
+  verbose 3, "Generating $base.y\n";
+  my %generator =
     (
-     "pull-impure" => '',
-     "pull-pure" => '%define api.pure',
-     "push-impure" => '%define api.push-pull "both"',
-     "push-pure" => '%define api.push-pull "both" %define api.pure',
+      "calc"       => \&generate_grammar_calc,
+      "list"       => \&generate_grammar_list,
+      "triangular" => \&generate_grammar_triangular,
     );
+  &{$generator{$name}}($base, 200, @directive);
+}
+
+##################################################################
+
+=item C<run ($command)>
+
+Run, possibly verbosely, the shell C<$command>.
+
+=cut
 
+sub run ($)
+{
+  my ($command) = @_;
+  verbose 3, "$command\n";
+  system ("$command") == 0
+    or die "$command failed";
+}
+
+##################################################################
+
+=item C<compile ($base)>
+
+Compile C<$base.y> to an executable C, Using the C or C++ compiler
+depending on the %language specification in C<$base.y>.
+
+=cut
+
+sub compile ($)
+{
+  my ($base) = @_;
+  my $language = `sed -ne '/%language "\\(.*\\)"/{s//\\1/;p;q;}' $base.y`;
+  chomp $language;
+
+  my $compiler = $language eq 'C++' ? $cxx : $cc;
+
+  my $my_bison = `sed -ne '/%bison "\\(.*\\)"/{s//\\1/;p;q;}' $base.y`;
+  run ((length $my_bison ? $my_bison : $bison) . " $base.y -o $base.c");
+  run "$compiler -o $base $cflags $base.c";
+}
+
+######################################################################
+
+=item C<bench ($grammar, @token)>
+
+Generate benches for the C<$grammar> and the directive specification
+given in the list of C<@token>.
+
+=cut
+
+sub bench ($@)
+{
+  my ($grammar, @token) = @_;
+  use Benchmark qw (:all :hireswallclock);
+
+  my @directive = parse (@token);
+
+  # Set up the benches as expected by timethese.
   my %bench;
-  while (my ($name, $directives) = each %test)
+  # A counter of directive sets.
+  my $count = 1;
+  for my $d (@directive)
     {
-      print STDERR "$name\n";
-      my $generator = "$gram" . "_grammar";
-      &$generator ($name, 200, $directives);
+      $bench{$count} = $d;
+      printf " %2d. %s\n", $count, join (' ', split ("\n", $d));
+      $count++;
+    };
+
+  # For each bench, capture the size.
+  my %size;
+
+  while (my ($name, $directives) = each %bench)
+    {
+      generate_grammar ($grammar, $name, $directives);
+      # Compile the executable.
       compile ($name);
       $bench{$name} = "system ('./$name');";
+      chop($size{$name} = `wc -c <$name`);
     }
 
-  print "$gram:\n";
-  my $res = timethese (50, \%bench, 'nop');
+  # Run the benches.
+  #
+  # STYLE can be any of 'all', 'none', 'noc', 'nop' or 'auto'.  'all'
+  # shows each of the 5 times available ('wallclock' time, user time,
+  # system time, user time of children, and system time of
+  # children). 'noc' shows all except the two children times. 'nop'
+  # shows only wallclock and the two children times.  'auto' (the
+  # default) will act as 'all' unless the children times are both
+  # zero, in which case it acts as 'noc'.  'none' prevents output.
+  verbose 3, "Running the benches for $grammar\n";
+  my $res = timethese ($iterations, \%bench, 'nop');
+
+  # Output the speed result.
   cmpthese ($res, 'nop');
+
+  # Display the sizes.
+  print "Sizes (decreasing):\n";
+  my $width = 10;
+  for my $bench (keys %size)
+    {
+      $width = length $bench
+        if $width < length $bench;
+    }
+  # Benches sorted by decreasing size.
+  my @benches_per_size = sort {$size{$b} <=> $size{$a}} keys %size;
+  for my $bench (@benches_per_size)
+    {
+      printf "%${width}s: %5.2fkB\n", $bench, $size{$bench} / 1024;
+    }
+}
+
+######################################################################
+
+=item C<bench_push_parser ()>
+
+Bench the C push parser against the pull parser, pure and impure
+interfaces.
+
+=cut
+
+sub bench_push_parser ()
+{
+  bench ('calc',
+         qw(
+            [ %d api.pure ]
+            &
+            [ %d api.push-pull=both ]
+         ));
 }
 
-print STDERR "Using $bison, $cc.\n";
-calc_input ('calc', 200);
-bench_grammar ('calc');
+######################################################################
+
+=item C<bench_variant_parser ()>
+
+Bench the C++ lalr1.cc parser using variants or %union.
+
+=cut
+
+sub bench_variant_parser ()
+{
+  bench ('list',
+         qw(
+            [
+              %d variant
+              &
+              [ #d ONE_STAGE_BUILD | %d api.token.constructor ]
+            ]
+         )
+    );
+}
+
+############################################################################
+
+sub help ($)
+{
+  my ($verbose) = @_;
+  use Pod::Usage;
+  # See <URL:http://perldoc.perl.org/pod2man.html#NOTES>.
+  pod2usage( { -message => "Bench Bison parsers",
+               -exitval => 0,
+               -verbose => $verbose,
+               -output  => \*STDOUT });
+}
+
+######################################################################
+
+# The end of the directives to parse.
+my $eod = "end of directives";
+# The list of tokens parsed by the following functions.
+my @token;
+
+# eat ($EXPECTED)
+# ---------------
+# Check that the current token is $EXPECTED, and move to the next.
+sub eat ($)
+{
+  my ($expected) = @_;
+  die "expected $expected, unexpected: $token[0] (@token)\n"
+    unless $token[0] eq $expected;
+  shift @token;
+}
+
+# Parse directive specifications:
+#   expr: term (| term)*
+#   term: fact (& fact)*
+#   fact: ( expr ) | [ expr ] | dirs
+#   dirs: %s SKELETON | #d NAME[=VALUE] | %d NAME[=VALUE] | directive
+sub parse (@)
+{
+  @token = (@_, $eod);
+  verbose 3, "Parsing: @token\n";
+  my @res = parse_expr ();
+  eat ($eod);
+  return @res;
+}
+
+sub parse_expr ()
+{
+  my @res = parse_term ();
+  while ($token[0] eq '|')
+    {
+      eat ('|');
+      # Alternation.
+      push @res, parse_term ();
+    }
+  return @res;
+}
+
+sub parse_term ()
+{
+  my @res = parse_fact ();
+  while ($token[0] eq '&')
+    {
+      eat ('&');
+      # Cartesian product.
+      my @lhs = @res;
+      @res = ();
+      for my $rhs (parse_fact ())
+        {
+          for my $lhs (@lhs)
+            {
+              push @res, $lhs . ($lhs && $rhs ? "\n" : "") . $rhs;
+            }
+        }
+    }
+  return @res;
+}
+
+sub parse_fact ()
+{
+  my @res;
+  die "unexpected end of expression"
+    unless defined $token[0];
+
+  if ($token[0] eq '(')
+    {
+      eat ('(');
+      @res = parse_expr ();
+      eat (')');
+    }
+  elsif ($token[0] eq '[')
+    {
+      eat ('[');
+      @res = (parse_expr (), '');
+      eat (']');
+    }
+  else
+    {
+      @res = parse_dirs ();
+    }
+  return @res;
+}
+
+sub parse_dirs ()
+{
+  my @res;
+  die "unexpected end of expression"
+    unless defined $token[0];
+
+  if ($token[0] eq '#d')
+    {
+      eat ('#d');
+      $token[0] =~ s/(.*?)=(.*)/$1 $2/;
+      @res = ("%code {\n#define $token[0]\n}");
+      shift @token;
+    }
+  elsif ($token[0] eq '%d')
+    {
+      shift @token;
+      $token[0] =~ s/(.*?)=(.*)/$1 "$2"/;
+      @res = ("%define $token[0]");
+      shift @token;
+    }
+  elsif ($token[0] eq '%s')
+    {
+      shift @token;
+      @res = ("%skeleton \"$token[0]\"");
+      shift @token;
+    }
+  elsif ($token[0] eq '%b')
+    {
+      shift @token;
+      @res = ("/*\n%bison \"$token[0]\"\\\n*/");
+      shift @token;
+    }
+  else
+    {
+      @res = $token[0];
+      shift @token;
+    }
+
+  return @res;
+}
+
+######################################################################
+
+sub getopt ()
+{
+  use Getopt::Long;
+  my %option = (
+    "b|bench=s"      => \$bench,
+    "c|cflags=s"     => \$cflags,
+    "d|directive=s"  => \@directive,
+    "g|grammar=s"    => \$grammar,
+    "h|help"         => sub { help ($verbose) },
+    "i|iterations=i" => \$iterations,
+    "q|quiet"        => sub { --$verbose },
+    "v|verbose"      => sub { ++$verbose },
+    );
+  Getopt::Long::Configure ("bundling", "pass_through");
+  GetOptions (%option)
+    or exit 1;
+}
+
+######################################################################
+
+getopt;
+
+# Create the directory we work in.
+mkdir "benches" or die "cannot create benches"
+  unless -d "benches";
+my $count = 1;
+++$count
+  while -d "benches/$count";
+my $dir = "benches/$count";
+mkdir $dir
+  or die "cannot create $dir";
+chdir $dir
+  or die "cannot chdir $dir";
+
+# The following message is tailored to please Emacs' compilation-mode.
+verbose 1, "Entering directory `$dir'\n";
+verbose 1, "Using bison=$bison.\n";
+verbose 2, "Using cc=$cc.\n";
+verbose 2, "Using cxx=$cxx.\n";
+verbose 2, "Using cflags=$cflags.\n";
+verbose 2, "Grammar: $grammar\n";
+
+
+# Support -b: predefined benches.
+my %bench =
+  (
+   "push"     => \&bench_push_parser,
+   "variant"  => \&bench_variant_parser,
+  );
+
+if (defined $bench)
+{
+  die "invalid argument for --bench: $bench"
+    unless defined $bench{$bench};
+  &{$bench{$bench}}();
+  exit 0;
+}
+else
+{
+  # Launch the bench marking.
+  bench ($grammar, @ARGV);
+}
 
 ### Setup "GNU" style for perl-mode and cperl-mode.
 ## Local Variables:
diff --git a/etc/local.mk b/etc/local.mk
new file mode 100644 (file)
index 0000000..2dc411e
--- /dev/null
@@ -0,0 +1,16 @@
+## Copyright (C) 2006, 2008-2013 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/>.
+
+nodist_noinst_SCRIPTS = etc/bench.pl
diff --git a/examples/.cvsignore b/examples/.cvsignore
deleted file mode 100644 (file)
index 282522d..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-Makefile
-Makefile.in
diff --git a/examples/.gitignore b/examples/.gitignore
deleted file mode 100644 (file)
index b336cc7..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-/Makefile
-/Makefile.in
diff --git a/examples/Makefile.am b/examples/Makefile.am
deleted file mode 100644 (file)
index 89f244d..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-## Process this file with automake to produce Makefile.in -*-Makefile-*-
-## Copyright (C) 2005, 2009-2013 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/>.
-
-if BISON_CXX_WORKS
-SUBDIRS = calc++
-endif
-
-dist_noinst_SCRIPTS = extexi
index 2050491fe4532fdd2888d03251bc8043b72115a2..50eb5ba1e816d1a39714e311cbb403fbcdd82475 100644 (file)
@@ -1,13 +1,19 @@
-/*.cc
-/*.hh
-/*.ll
 /*.o
-/*.output
-/*.stamp
 /*.tmp
-/*.yy
 /.deps
-/Makefile
-/Makefile.in
 /calc++
+/calc++-driver.cc
+/calc++-driver.hh
+/calc++-parser.cc
+/calc++-parser.hh
+/calc++-parser.output
+/calc++-parser.stamp
+/calc++-parser.yy
+/calc++-scanner.cc
+/calc++-scanner.ll
+/calc++.cc
 /calc++.exe
+/calc.stamp
+/location.hh
+/position.hh
+/stack.hh
diff --git a/examples/calc++/Makefile.am b/examples/calc++/Makefile.am
deleted file mode 100644 (file)
index 41448bd..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-## Process this file with automake to produce Makefile.in -*-Makefile-*-
-## Copyright (C) 2005-2006, 2009-2013 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/>.
-
-## ------------------------------------- ##
-## Running the bison from this tarball.  ##
-## ------------------------------------- ##
-
-BISON = $(top_builddir)/tests/bison
-BISON_IN = $(top_srcdir)/tests/bison.in
-
-$(BISON): $(BISON_IN)
-       $(AM_V_GEN)cd $(top_builddir)/tests && $(MAKE) $(AM_MAKEFLAGS) bison
-
-## ------------ ##
-## Extracting.  ##
-## ------------ ##
-
-doc = $(top_srcdir)/doc/bison.texi
-extexi = $(top_srcdir)/examples/extexi
-# Extract in src.
-$(srcdir)/calc.stamp: $(doc) $(extexi)
-       $(AM_V_GEN)rm -f $@ $@.tmp
-       $(AM_V_at)touch $@.tmp
-       $(AM_V_at)cd $(srcdir) && \
-          $(AWK) -f ../extexi -v VERSION="$(VERSION)" \
-            ../../doc/bison.texi -- calc++-parser.yy \
-            calc++-scanner.ll calc++.cc calc++-driver.hh calc++-driver.cc
-       $(AM_V_at)mv $@.tmp $@
-
-$(calc_extracted): $(srcdir)/calc.stamp
-
-## ------------------- ##
-## Parser generation.  ##
-## ------------------- ##
-
-DEFAULT_INCLUDES = -I. -I$(srcdir)
-BUILT_SOURCES = $(calc_extracted) $(calc_sources_generated)
-CLEANFILES = $(srcdir)/*.output *.tmp
-MAINTAINERCLEANFILES = $(srcdir)/*.stamp $(BUILT_SOURCES)
-
-# Compile the parser and save cycles.
-# This code comes from "Handling Tools that Produce Many Outputs",
-# from the Automake documentation.
-EXTRA_DIST =                                   \
-  $(srcdir)/calc++-parser.stamp                        \
-  $(srcdir)/calc++-parser.yy                   \
-  $(srcdir)/calc.stamp
-# Don't depend on $(BISON) otherwise we would rebuild these files
-# in srcdir, including during distcheck, which is forbidden.
-$(srcdir)/calc++-parser.stamp: $(srcdir)/calc++-parser.yy $(BISON_IN)
-       $(AM_V_GEN)rm -f calc++-parser.tmp
-       $(AM_V_at)touch calc++-parser.tmp
-       $(AM_V_at)$(BISON) -d -ra -S lalr1.cc -o $(srcdir)/calc++-parser.cc \
-         $(srcdir)/calc++-parser.yy
-       $(AM_V_at)mv -f calc++-parser.tmp $@
-
-$(calc_sources_generated): $(srcdir)/calc++-parser.stamp
-       $(AM_V_GEN)if test -f $@; then :; else \
-         rm -f $(srcdir)/calc++-parser.stamp && \
-         $(MAKE) $(AM_MAKEFLAGS) $(srcdir)/calc++-parser.stamp; \
-       fi
-
-
-## --------------------------- ##
-## Building & testing calc++.  ##
-## --------------------------- ##
-
-check_PROGRAMS = calc++
-
-calc_sources_extracted = $(srcdir)/calc++-scanner.ll $(srcdir)/calc++.cc \
-  $(srcdir)/calc++-driver.hh $(srcdir)/calc++-driver.cc
-calc_extracted = $(calc_sources_extracted) $(srcdir)/calc++-parser.yy
-calc_sources_generated = \
-  $(srcdir)/stack.hh $(srcdir)/position.hh $(srcdir)/location.hh \
-  $(srcdir)/calc++-parser.hh $(srcdir)/calc++-parser.cc
-
-calc___SOURCES = $(calc_sources_extracted) $(calc_sources_generated)
-
-TESTS = test
-EXTRA_DIST += $(TESTS)
diff --git a/examples/calc++/calc++.test b/examples/calc++/calc++.test
new file mode 100755 (executable)
index 0000000..18accef
--- /dev/null
@@ -0,0 +1,50 @@
+#! /bin/sh
+
+# Copyright (C) 2005-2013 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/>.
+
+cat >input <<EOF
+toto := 1
+toto
+EOF
+run 0 1 -s
+
+
+cat >input <<EOF
+a := 1
+b := 2
+c := 3
+d := a + b * c
+d
+EOF
+run 0 7
+run 0 7 -p
+
+
+cat >input <<EOF
+a := 1
+b := 2
+c := 3
+d := (a + b) * c
+d
+EOF
+run 0 9
+
+
+cat >input <<EOF
+a := 1
+d := a + b * c
+EOF
+run 1 ''
diff --git a/examples/calc++/local.mk b/examples/calc++/local.mk
new file mode 100644 (file)
index 0000000..b260001
--- /dev/null
@@ -0,0 +1,74 @@
+# Copyright (C) 2005-2006, 2008-2013 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/>.
+
+## ------------------- ##
+## Parser generation.  ##
+## ------------------- ##
+
+# Don't depend on $(BISON) otherwise we would rebuild these files
+# in srcdir, including during distcheck, which is forbidden.
+examples/calc++/calc++-parser.stamp: $(BISON_IN)
+SUFFIXES += .yy .stamp
+.yy.stamp:
+       $(AM_V_YACC)rm -f $@
+       $(AM_V_at)touch $@.tmp
+       $(AM_V_at)$(YACCCOMPILE) -o $*.cc $<
+       $(AM_V_at)mv -f $@.tmp $@
+
+$(calc_sources_generated): examples/calc++/calc++-parser.stamp
+       @test -f $@ || rm -f examples/calc++/calc++-parser.stamp
+       @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) examples/calc++/calc++-parser.stamp
+CLEANFILES +=                                   \
+  $(calc_sources_generated)                     \
+  examples/calc++/calc++-parser.output          \
+  examples/calc++/calc++-parser.stamp           \
+  examples/calc++/calc++-scanner.cc
+
+
+## -------------------- ##
+## Building & testing.  ##
+## -------------------- ##
+
+# Avoid using BUILT_SOURCES which is too global.
+$(examples_calc___calc___OBJECTS): $(calc_sources_generated)
+
+calc_sources_extracted =                        \
+  examples/calc++/calc++-driver.cc              \
+  examples/calc++/calc++-driver.hh              \
+  examples/calc++/calc++-scanner.ll             \
+  examples/calc++/calc++.cc
+calc_extracted =                                \
+  $(calc_sources_extracted)                     \
+  examples/calc++/calc++-parser.yy
+extracted += $(calc_extracted)
+calc_sources_generated =                        \
+  examples/calc++/calc++-parser.cc              \
+  examples/calc++/calc++-parser.hh              \
+  examples/calc++/location.hh                   \
+  examples/calc++/position.hh                   \
+  examples/calc++/stack.hh
+calc_sources =                                  \
+  $(calc_sources_extracted)                     \
+  $(calc_sources_generated)
+
+if BISON_CXX_WORKS
+check_PROGRAMS += examples/calc++/calc++
+nodist_examples_calc___calc___SOURCES =         \
+  $(calc_sources)
+
+examples_calc___calc___CPPFLAGS = -I$(top_builddir)/examples/calc++
+examples_calc___calc___CXXFLAGS = $(AM_CXXFLAGS) $(FLEX_SCANNER_CXXFLAGS)
+dist_TESTS += examples/calc++/calc++.test
+endif
diff --git a/examples/calc++/test b/examples/calc++/test
deleted file mode 100755 (executable)
index 6aa12eb..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-#! /bin/sh
-
-# Copyright (C) 2005-2013 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/>.
-
-test -z "$VERBOSE" && {
-   exec > /dev/null 2>&1
-   set -x
-}
-
-cat >input <<EOF
-a := 1
-b := 2
-c := 3
-d := a + b * c
-d
-EOF
-
-./calc++ input
-./calc++ -p input
-
-cat >input <<EOF
-a := 1
-d := a + b * c
-EOF
-./calc++ input
-
-cat >input <<EOF
-toto := 1
-toto
-EOF
-./calc++ -s input
-
-rm input
diff --git a/examples/calc++/y.tab.h b/examples/calc++/y.tab.h
new file mode 100644 (file)
index 0000000..798b670
--- /dev/null
@@ -0,0 +1,6 @@
+// Work around an Automake 1.11.2 bug: it asks for the creation of
+// y.tab.c and y.tab.h and then renames them as calc++-parser.cc and
+// calc++-parser.h, but in the former it does not convert the
+// #include "y.tab.h".  We don't want this to show in the
+// documentation.
+#include "calc++-parser.hh"
old mode 100644 (file)
new mode 100755 (executable)
index 4a80217..24a005e
@@ -1,4 +1,5 @@
-# Extract all examples from the manual source.            -*- AWK -*-
+#! /usr/bin/perl -w
+# Extract all examples from the manual source.
 
 # This file is part of GNU Bison
 
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-# This script is for use with any Awk that conforms to POSIX.
-# It was derived from a similar script tests/generate.awk in GNU m4.
-#
 # Usage: extexi input-file.texi ... -- [FILES to extract]
-BEGIN {
-  if (!output_dir)
-    output_dir = ".";
-  for (argc = 1; argc < ARGC; ++argc)
-    if (ARGV[argc] == "--")
-      break;
-  for (i = argc + 1; i < ARGC; ++i)
-    file_wanted[ARGV[i]] = 1;
-  ARGC = argc;
-}
-
-/^@node / {
-  if (seq > 0)
-    print "AT_CLEANUP";
 
-  split ($0, tmp, ",");
-  node = substr(tmp[1], 7);
-  seq = 0;
+# Look for @example environments preceded with lines such as:
+#
+#      @comment file calc.y
+# or
+#      @comment file calc.y: 3
+#
+# and output their content in that file (calc.y).  When numbers are
+# provided, use them to decide the output order (block numbered 1 is
+# output before block 2, even if the latter appears before).  The same
+# number may be used several time, in which case the order of
+# appearance is used.
+
+use strict;
+
+# normalize($block)
+# -----------------
+# Remove Texinfo mark up.
+sub normalize($)
+{
+  local ($_) = @_;
+
+  s/^\@(c |comment|dots|end (ignore|group)|ignore|group).*//mg;
+  s/\@value\{VERSION\}/$ENV{VERSION}/g;
+  s/^\@(error|result)\{\}//mg;
+  s/\@([{}@])/$1/g;
+  s/\@comment.*//;
+  $_;
 }
 
-/^@comment file: / {
-  if (!file_wanted[$3])
-    message("ignoring " $3);
-  else
+# Print messages only once.
+my %msg;
+sub message($)
+{
+  my ($msg) = @_;
+  if (! $msg{$msg})
     {
-      message("extracting " $3);
-      file = $3;
+      print STDERR "extexi: $msg\n";
+      $msg{$msg} = 1;
     }
 }
 
-/^@example$/, /^@end example$/ {
-  if (!file)
-    next;
-
-  if ($0 ~ /^@example$/)
+# basename => full file name for files we should extract.
+my %file_wanted;
+
+sub process ($)
+{
+  my ($in) = @_;
+  use IO::File;
+  my $f = new IO::File($in)
+    or die "$in: cannot open: $?";
+  # FILE-NAME => { BLOCK-NUM => CODE }
+  my %file;
+
+  # The latest "@comment file: FILE [BLOCK-NUM]" arguments.
+  my $file;
+  my $block;
+  # The @example block currently read.
+  my $input;
+  local $_;
+  while (<$f>)
     {
-      input = files_output[file] ? "\n" : "";
-
-      # FNR is starting at 0 instead of 1, and
-      # #line report the line number of the *next* line.
-      # => + 2.
-      # Note that recent Bison support it, but not Flex.
-      if (file ~ /\.[chy]*$/)
-       input = "#line " (FNR + 1) " \"" FILENAME "\"\n";
-      next;
+      if (/^\@comment file: ([^:\n]+)(?::\s*(\d+))?$/)
+        {
+          my $f = $1;
+          $block = $2 || 1;
+          if ($file_wanted{$f})
+            {
+              $file = $file_wanted{$f};
+              message(" GEN $file");
+            }
+          else
+            {
+              message("SKIP $f");
+            }
+        }
+      elsif ($file && /^\@(small)?example$/ .. /^\@end (small)?example$/)
+        {
+          if (/^\@(small)?example$/)
+            {
+              # Bison supports synclines, but not Flex.
+              $input .= sprintf ("#line %s \"$in\"\n", $. + 1)
+                if $file =~ /\.[chy]*$/;
+              next;
+            }
+          elsif (/^\@end (small)?example$/)
+            {
+              die "no contents: $file"
+                if $input eq "";
+
+              $file{$file}{$block} .= normalize($input);
+              $file = $input = undef;
+              ++$block;
+            }
+          else
+            {
+              $input .= $_;
+            }
+        }
     }
 
-  if ($0 ~ /^@end example$/)
+  # Output the files.
+  for my $file (keys %file)
     {
-      if (input == "")
-       fatal("no contents: " file);
-
-      input = normalize(input);
       # No spurious end of line: use printf.
-      if (files_output[file])
-       # The parens around the output file seem to be required
-        # by awk on Mac OS X Tiger (darwin 8.4.6).
-        printf ("%s", input) >> (output_dir "/" file);
-      else
-       printf ("%s", input) > (output_dir "/" file);
-      close (output_dir "/" file);
-      files_output[file] = 1;
-
-      file = input = "";
-      next;
+      my $o = new IO::File(">$file")
+        or die "$file: cannot create: $?";
+      print $o $file{$file}{$_}
+        for sort keys %{$file{$file}};
     }
-
-  input = input $0 "\n";
 }
 
-
-# We have to handle CONTENTS line per line, since anchors in AWK are
-# referring to the whole string, not the lines.
-function normalize(contents,    i, lines, n, line, res) {
-  # Remove the Texinfo tags.
-  n = split (contents, lines, "\n");
-  # We don't want the last field which empty: it's behind the last \n.
-  for (i = 1; i < n; ++i)
+my @input;
+my $seen_dash = 0;
+for my $arg (@ARGV)
+{
+  if ($arg eq '--')
     {
-      line = lines[i];
-
-      # Whole line commands.
-      if (line ~ /^@(c |comment|dots|end (ignore|group)|ignore|group)/)
-       # Gperf accepts empty lines as valid input!!!
-       if (file ~ /\.gperf$/)
-         continue;
-       else
-         line = "";
-
-      gsub (/"@value\{VERSION\}"/, "\"" VERSION "\"", line)
-      gsub (/^@result\{\}/, "", line);
-      gsub (/^@error\{\}/,  "", line);
-      gsub ("@[{]", "{", line);
-      gsub ("@}", "}", line);
-      gsub ("@@", "@", line);
-      gsub ("@comment.*", "", line);
-
-      res = res line "\n";
+      $seen_dash = 1;
     }
-  return res;
-}
-
-
-function message(msg) {
-  if (! message_printed[msg])
+  elsif ($seen_dash)
     {
-      print "extexi: " msg > "/dev/stderr";
-      message_printed[msg] = 1;
+      use File::Basename;
+      $file_wanted{basename($arg)} = $arg;
+    }
+  else
+    {
+      push @input, $arg;
     }
 }
-
-function fatal(msg) {
-  message(msg);
-  exit 1
-}
+process $_
+  foreach @input;
+
+
+### Setup "GNU" style for perl-mode and cperl-mode.
+## Local Variables:
+## perl-indent-level: 2
+## perl-continued-statement-offset: 2
+## perl-continued-brace-offset: 0
+## perl-brace-offset: 0
+## perl-brace-imaginary-offset: 0
+## perl-label-offset: -2
+## cperl-indent-level: 2
+## cperl-brace-offset: 0
+## cperl-continued-brace-offset: 0
+## cperl-label-offset: -2
+## cperl-extra-newline-before-brace: t
+## cperl-merge-trailing-else: nil
+## cperl-continued-statement-offset: 2
+## End:
diff --git a/examples/local.mk b/examples/local.mk
new file mode 100644 (file)
index 0000000..05e28e1
--- /dev/null
@@ -0,0 +1,43 @@
+# Copyright (C) 2005, 2008-2013 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_noinst_SCRIPTS = examples/extexi examples/test
+TEST_LOG_COMPILER = $(top_srcdir)/examples/test
+
+AM_CXXFLAGS =                                                  \
+  $(WARN_CXXFLAGS) $(WARN_CXXFLAGS_TEST) $(WERROR_CXXFLAGS)
+
+## ------------ ##
+## Extracting.  ##
+## ------------ ##
+
+doc = $(top_srcdir)/doc/bison.texi
+extexi = $(top_srcdir)/examples/extexi
+extract = VERSION="$(VERSION)" $(PERL) -f $(extexi) $(doc) --
+extracted =
+CLEANFILES += $(extracted) examples/extracted.stamp
+examples/extracted.stamp: $(doc) $(extexi)
+       $(AM_V_GEN)rm -f $@ $@.tmp
+       $(AM_V_at)touch $@.tmp
+       $(AM_V_at)$(extract) $(extracted)
+       $(AM_V_at)mv $@.tmp $@
+
+$(extracted): examples/extracted.stamp
+       @test -f $@ || rm -f examples/extracted.stamp
+       @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) examples/extracted.stamp
+
+include examples/calc++/local.mk
+include examples/mfcalc/local.mk
+include examples/rpcalc/local.mk
diff --git a/examples/mfcalc/.gitignore b/examples/mfcalc/.gitignore
new file mode 100644 (file)
index 0000000..6f05a04
--- /dev/null
@@ -0,0 +1,11 @@
+/*.o
+/*.tmp
+/.deps
+/calc.h
+/mfcalc
+/mfcalc.c
+/mfcalc.exe
+/mfcalc.h
+/mfcalc.output
+/mfcalc.stamp
+/mfcalc.y
diff --git a/examples/mfcalc/local.mk b/examples/mfcalc/local.mk
new file mode 100644 (file)
index 0000000..10d6696
--- /dev/null
@@ -0,0 +1,36 @@
+# Copyright (C) 2005-2006, 2008-2013 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/>.
+
+## -------------------- ##
+## Building & testing.  ##
+## -------------------- ##
+
+BUILT_SOURCES += $(mfcalc_sources)
+CLEANFILES +=  examples/mfcalc/mfcalc.[ch] examples/mfcalc/mfcalc.output
+
+mfcalc_extracted =                             \
+  examples/mfcalc/calc.h                       \
+  examples/mfcalc/mfcalc.y
+mfcalc_sources =                               \
+  $(mfcalc_extracted)
+extracted += $(mfcalc_extracted)
+
+check_PROGRAMS += examples/mfcalc/mfcalc
+examples_mfcalc_mfcalc_LDADD = -lm
+nodist_examples_mfcalc_mfcalc_SOURCES =                \
+  $(mfcalc_sources)
+
+examples_mfcalc_mfcalc_CPPFLAGS = -I$(top_builddir)/examples/mfcalc
+dist_TESTS += examples/mfcalc/mfcalc.test
diff --git a/examples/mfcalc/mfcalc.test b/examples/mfcalc/mfcalc.test
new file mode 100755 (executable)
index 0000000..90ab4f4
--- /dev/null
@@ -0,0 +1,27 @@
+#! /bin/sh
+
+# Copyright (C) 2005-2013 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/>.
+
+cat >input <<EOF
+1+2*3
+EOF
+run 0 7
+
+cat >input <<EOF
+(1+2) * 3
+EOF
+run 0 9
+run 0 9 -p
diff --git a/examples/rpcalc/.gitignore b/examples/rpcalc/.gitignore
new file mode 100644 (file)
index 0000000..fbd9052
--- /dev/null
@@ -0,0 +1,6 @@
+/calc.h
+/rpcalc.c
+/rpcalc.h
+/rpcalc.output
+/rpcalc.stamp
+/rpcalc.y
diff --git a/examples/rpcalc/local.mk b/examples/rpcalc/local.mk
new file mode 100644 (file)
index 0000000..3ff2f98
--- /dev/null
@@ -0,0 +1,35 @@
+# Copyright (C) 2005-2006, 2008-2013 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/>.
+
+## -------------------- ##
+## Building & testing.  ##
+## -------------------- ##
+
+BUILT_SOURCES += $(rpcalc_sources)
+CLEANFILES +=  examples/rpcalc/rpcalc.[ch] examples/rpcalc/rpcalc.output
+
+rpcalc_extracted =                             \
+  examples/rpcalc/rpcalc.y
+rpcalc_sources =                               \
+  $(rpcalc_extracted)
+extracted += $(rpcalc_extracted)
+
+check_PROGRAMS += examples/rpcalc/rpcalc
+examples_rpcalc_rpcalc_LDADD = -lm
+nodist_examples_rpcalc_rpcalc_SOURCES =                \
+  $(rpcalc_sources)
+
+examples_rpcalc_rpcalc_CPPFLAGS = -I$(top_builddir)/examples/rpcalc
+dist_TESTS += examples/rpcalc/rpcalc.test
diff --git a/examples/rpcalc/rpcalc.test b/examples/rpcalc/rpcalc.test
new file mode 100755 (executable)
index 0000000..8ad2a3d
--- /dev/null
@@ -0,0 +1,46 @@
+#! /bin/sh
+
+# Copyright (C) 2005-2013 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/>.
+
+cat >input <<EOF
+1 2 3 * +
+EOF
+run 0 7
+
+cat >input <<EOF
+1.1 2.2 3.3 * +
+EOF
+run 0 8.36
+
+cat >input <<EOF
+1 2 + 3 *
+EOF
+run 0 9
+
+cat >input <<EOF
+1 2 3 4 5 6 7 8 9 * * * * * * * *
+EOF
+run 0 362880
+
+cat >input <<EOF
+3 7 + 3 4 5 * + - n
+EOF
+run 0 13
+
+cat >input <<EOF
+3 4 ^
+EOF
+run 0 81
diff --git a/examples/test b/examples/test
new file mode 100755 (executable)
index 0000000..f77b8f4
--- /dev/null
@@ -0,0 +1,82 @@
+#! /bin/sh
+
+# Copyright (C) 2005-2013 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/>.
+
+me=`basename $1 .test`
+
+# Number of the current test.
+number=1
+
+# Exit status of this script.
+exit=true
+
+# top_buiddir.
+cwd=`pwd`
+
+# The exercised program.
+prog=$cwd/examples/$me/$me
+
+# cleanup
+# -------
+cleanup ()
+{
+  local status=$?
+  if test -z "$DEBUG"; then
+     cd $cwd
+     rm -rf $$.dir
+  fi
+  exit $status
+}
+trap cleanup 0 1 2 13 15
+mkdir $$.dir
+cd $$.dir
+
+# run EXPECTED-EXIT-STATUS EXPECTED-OUTPUT [PARSER-OPTIONS]
+# ---------------------------------------------------------
+run ()
+{
+  # Expected exit status.
+  local sta_exp=$1
+  shift
+  # Expected output.
+  local out_exp=$1
+  shift
+  # Effective exit status.
+  local sta_eff=0
+  $prog "$@" - <input >out_eff || sta_eff=$?
+  # Effective output.
+  local out_eff=`cat out_eff`
+  if test $sta_eff -eq $sta_exp; then
+    if test "$out_eff" = "$out_exp"; then
+      echo "$me: PASS: $number"
+    else
+      echo "$me: FAIL: $number (expected output: $out_exp, effective: $out_eff)"
+      exit=false
+    fi
+  else
+    echo "$me: FAIL: $number (expected status: $sta_exp, effective: $sta_eff)"
+    exit=false
+  fi
+  number=`expr $number + 1`
+}
+
+# We have cd'd one level deeper.
+case $1 in
+  /*) . "$1";;
+  *)  . "../$1";;
+esac
+
+$exit
diff --git a/examples/variant.yy b/examples/variant.yy
new file mode 100644 (file)
index 0000000..9413cbc
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+  Copyright (C) 2008-2013 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/>.
+*/
+
+%debug
+%skeleton "lalr1.cc"
+%defines
+%define api.token.constructor
+%define api.value.type variant
+%define parse.assert
+%locations
+
+%code requires // *.hh
+{
+#include <list>
+#include <string>
+typedef std::list<std::string> strings_type;
+}
+
+%code // *.cc
+{
+#include <algorithm>
+#include <iostream>
+#include <iterator>
+#include <sstream>
+
+  // Prototype of the yylex function providing subsequent tokens.
+  namespace yy
+  {
+    static parser::symbol_type yylex ();
+  }
+
+  // Printing a list of strings.
+  // Koening look up will look into std, since that's an std::list.
+  namespace std
+  {
+    std::ostream&
+    operator<< (std::ostream& o, const strings_type& s)
+    {
+      std::copy (s.begin (), s.end (),
+                 std::ostream_iterator<strings_type::value_type> (o, "\n"));
+      return o;
+    }
+  }
+
+  // Conversion to string.
+  template <typename T>
+    inline
+    std::string
+    string_cast (const T& t)
+  {
+    std::ostringstream o;
+    o << t;
+    return o.str ();
+  }
+}
+
+%token <::std::string> TEXT;
+%token <int> NUMBER;
+%printer { yyoutput << $$; } <*>;
+%token END_OF_FILE 0;
+
+%type <::std::string> item;
+%type <::std::list<std::string>> list;
+
+%%
+
+result:
+  list  { std::cout << $1 << std::endl; }
+;
+
+list:
+  /* nothing */ { /* Generates an empty string list */ }
+| list item     { std::swap ($$, $1); $$.push_back ($2); }
+;
+
+item:
+  TEXT          { std::swap ($$, $1); }
+| NUMBER        { $$ = string_cast ($1); }
+;
+%%
+
+namespace yy
+{
+  // The yylex function providing subsequent tokens:
+  // TEXT         "I have three numbers for you."
+  // NUMBER       1
+  // NUMBER       2
+  // NUMBER       3
+  // TEXT         "And that's all!"
+  // END_OF_FILE
+
+  static
+  parser::symbol_type
+  yylex ()
+  {
+    static int stage = -1;
+    ++stage;
+    parser::location_type loc(0, stage + 1, stage + 1);
+    switch (stage)
+      {
+      case 0:
+        return parser::make_TEXT ("I have three numbers for you.", loc);
+      case 1:
+      case 2:
+      case 3:
+        return parser::make_NUMBER (stage, loc);
+      case 4:
+        return parser::make_TEXT ("And that's all!", loc);
+      default:
+        return parser::make_END_OF_FILE (loc);
+      }
+  }
+
+  // Mandatory error function
+  void
+  parser::error (const parser::location_type& loc, const std::string& msg)
+  {
+    std::cerr << loc << ": " << msg << std::endl;
+  }
+}
+
+int
+main ()
+{
+  yy::parser p;
+  p.set_debug_level (!!getenv ("YYDEBUG"));
+  return p.parse ();
+}
+
+// Local Variables:
+// mode: C++
+// End:
index 9f63cba1c50a9eb7b2f634b2fd7d36b1e59a8360..e021ab05d2d6399c8fe851c121703c335f6bae6e 100644 (file)
@@ -35,6 +35,8 @@
 /close.c
 /closeout.c
 /closeout.h
+/concat-filename.c
+/concat-filename.h
 /config.charset
 /config.h
 /config.in.h
@@ -62,6 +64,7 @@
 /fd-hook.h
 /fd-safer-flag.c
 /fd-safer.c
+/filename.h
 /float+.h
 /float.c
 /float.h
 /isnanf.c
 /isnanl-nolibm.h
 /isnanl.c
-/iswblank.c
 /itold.c
 /ldexpl.c
 /localcharset.c
 /malloc.c
 /math.h
 /math.in.h
-/mbchar.c
-/mbchar.h
 /mbrtowc.c
-/mbschr.c
 /mbsinit.c
-/mbsrchr.c
 /mbswidth.c
 /mbswidth.h
-/mbuiter.h
 /memchr.c
 /memchr.valgrind
 /msvc-inval.c
 /nonblocking.h
 /obstack.c
 /obstack.h
+/obstack_printf.c
 /open.c
 /pathmax.h
 /perror.c
 /stripslash.c
 /strndup.c
 /strnlen.c
-/strnlen1.c
-/strnlen1.h
 /strtol.c
 /strtoul.c
 /strverscmp.c
 /sys_socket.in.h
 /sys_stat.h
 /sys_stat.in.h
+/sys_types.in.h
 /sys_wait.h
 /sys_wait.in.h
 /sysexits.in.h
 /xalloc-die.c
 /xalloc-oversized.h
 /xalloc.h
+/xconcat-filename.c
 /xmalloc.c
+/xmemdup0.c
+/xmemdup0.h
 /xsize.h
 /xstrndup.c
 /xstrndup.h
-/xmemdup0.c
-/xmemdup0.h
-/sys_types.in.h
-/obstack_printf.c
 /binary-io.c
-/mbuiter.c
 /xsize.c
 /bitrotate.c
 /math.c
 /sig-handler.c
 /unistd.c
 /wctype-h.c
-/getdelim.c
-/getline.c
diff --git a/lib/Makefile.am b/lib/Makefile.am
deleted file mode 100644 (file)
index 67bfeb9..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-# Make bison/lib.
-
-# Copyright (C) 2001-2004, 2006, 2008-2013 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/>.
-
-AM_CFLAGS =
-AM_CPPFLAGS =
-BUILT_SOURCES =
-CLEANFILES =
-EXTRA_DIST =
-MOSTLYCLEANDIRS =
-MOSTLYCLEANFILES =
-SUFFIXES =
-noinst_LIBRARIES =
-
-include gnulib.mk
-
-AM_CFLAGS += $(WARN_CFLAGS)
-
-# Implementation of bitsets.
-bitsets_sources = \
-  abitset.c abitset.h bbitset.h bitset.c bitset.h bitset_stats.c       \
-  bitset_stats.h bitsetv.c bitsetv.h ebitset.c ebitset.h lbitset.c     \
-  lbitset.h libiberty.h vbitset.c vbitset.h
-
-# Additional bitset operations.
-additional_bitsets_sources = \
-  bitsetv-print.h bitsetv-print.c
-
-# timevars, stolen from GCC.
-timevars_sources = \
-  timevar.h timevar.c timevar.def
-
-# Non-gnulib sources in Bison's internal library.
-libbison_a_SOURCES += \
-  get-errno.h get-errno.c \
-  $(bitsets_sources) $(additional_bitsets_sources) $(timevars_sources)
-
-# The Yacc compatibility library.
-lib_LIBRARIES = $(YACC_LIBRARY)
-EXTRA_LIBRARIES = liby.a
-liby_a_SOURCES = main.c yyerror.c
index f0a665d3875867ebc665c96896f1b875325be7d9..f876996bcfdb63a2c9e1fc4472879608fd251b7f 100644 (file)
@@ -47,7 +47,7 @@ abitset_resize (bitset src, bitset_bindex size)
  found and with *NEXT indicating where search stopped.  */
 static bitset_bindex
 abitset_small_list (bitset src, bitset_bindex *list,
-                   bitset_bindex num, bitset_bindex *next)
+                    bitset_bindex num, bitset_bindex *next)
 {
   bitset_bindex bitno;
   bitset_bindex count;
@@ -73,27 +73,27 @@ abitset_small_list (bitset src, bitset_bindex *list,
   if (num >= BITSET_WORD_BITS)
     {
       for (count = 0; word; bitno++)
-       {
-         if (word & 1)
-           list[count++] = bitno;
-         word >>= 1;
-       }
+        {
+          if (word & 1)
+            list[count++] = bitno;
+          word >>= 1;
+        }
     }
   else
     {
       for (count = 0; word; bitno++)
-       {
-         if (word & 1)
-           {
-             list[count++] = bitno;
-             if (count >= num)
-               {
-                 bitno++;
-                 break;
-               }
-           }
-         word >>= 1;
-       }
+        {
+          if (word & 1)
+            {
+              list[count++] = bitno;
+              if (count >= num)
+                {
+                  bitno++;
+                  break;
+                }
+            }
+          word >>= 1;
+        }
     }
 
   *next = bitno;
@@ -115,7 +115,7 @@ abitset_set (bitset dst ATTRIBUTE_UNUSED, bitset_bindex bitno ATTRIBUTE_UNUSED)
 /* Reset bit BITNO in bitset DST.  */
 static void
 abitset_reset (bitset dst ATTRIBUTE_UNUSED,
-              bitset_bindex bitno ATTRIBUTE_UNUSED)
+               bitset_bindex bitno ATTRIBUTE_UNUSED)
 {
   /* This should never occur for abitsets since we should always hit
      the cache.  It is likely someone is trying to access outside the
@@ -126,7 +126,7 @@ abitset_reset (bitset dst ATTRIBUTE_UNUSED,
 /* Test bit BITNO in bitset SRC.  */
 static bool
 abitset_test (bitset src ATTRIBUTE_UNUSED,
-             bitset_bindex bitno ATTRIBUTE_UNUSED)
+              bitset_bindex bitno ATTRIBUTE_UNUSED)
 {
   /* This should never occur for abitsets since we should always
      hit the cache.  */
@@ -140,7 +140,7 @@ abitset_test (bitset src ATTRIBUTE_UNUSED,
    stopped.  */
 static bitset_bindex
 abitset_list_reverse (bitset src, bitset_bindex *list,
-                     bitset_bindex num, bitset_bindex *next)
+                      bitset_bindex num, bitset_bindex *next)
 {
   bitset_bindex bitno;
   bitset_bindex rbitno;
@@ -173,18 +173,18 @@ abitset_list_reverse (bitset src, bitset_bindex *list,
 
       word = srcp[windex] << (BITSET_WORD_BITS - 1 - bitcnt);
       for (; word; bitcnt--)
-       {
-         if (word & BITSET_MSB)
-           {
-             list[count++] = bitoff + bitcnt;
-             if (count >= num)
-               {
-                 *next = n_bits - (bitoff + bitcnt);
-                 return count;
-               }
-           }
-         word <<= 1;
-       }
+        {
+          if (word & BITSET_MSB)
+            {
+              list[count++] = bitoff + bitcnt;
+              if (count >= num)
+                {
+                  *next = n_bits - (bitoff + bitcnt);
+                  return count;
+                }
+            }
+          word <<= 1;
+        }
       bitoff -= BITSET_WORD_BITS;
       bitcnt = BITSET_WORD_BITS - 1;
     }
@@ -200,7 +200,7 @@ abitset_list_reverse (bitset src, bitset_bindex *list,
  found and with *NEXT indicating where search stopped.  */
 static bitset_bindex
 abitset_list (bitset src, bitset_bindex *list,
-             bitset_bindex num, bitset_bindex *next)
+              bitset_bindex num, bitset_bindex *next)
 {
   bitset_bindex bitno;
   bitset_bindex count;
@@ -217,80 +217,80 @@ abitset_list (bitset src, bitset_bindex *list,
     {
       /* Many bitsets are zero, so make this common case fast.  */
       for (windex = 0; windex < size && !srcp[windex]; windex++)
-       continue;
+        continue;
       if (windex >= size)
-       return 0;
+        return 0;
 
       /* If num is 1, we could speed things up with a binary search
-        of the current word.  */
+         of the current word.  */
 
       bitoff = windex * BITSET_WORD_BITS;
     }
   else
     {
       if (bitno >= BITSET_SIZE_ (src))
-       return 0;
+        return 0;
 
       windex = bitno / BITSET_WORD_BITS;
       bitno = bitno % BITSET_WORD_BITS;
 
       if (bitno)
-       {
-         /* Handle the case where we start within a word.
-            Most often, this is executed with large bitsets
-            with many set bits where we filled the array
-            on the previous call to this function.  */
-
-         bitoff = windex * BITSET_WORD_BITS;
-         word = srcp[windex] >> bitno;
-         for (bitno = bitoff + bitno; word; bitno++)
-           {
-             if (word & 1)
-               {
-                 list[count++] = bitno;
-                 if (count >= num)
-                   {
-                     *next = bitno + 1;
-                     return count;
-                   }
-               }
-             word >>= 1;
-           }
-         windex++;
-       }
+        {
+          /* Handle the case where we start within a word.
+             Most often, this is executed with large bitsets
+             with many set bits where we filled the array
+             on the previous call to this function.  */
+
+          bitoff = windex * BITSET_WORD_BITS;
+          word = srcp[windex] >> bitno;
+          for (bitno = bitoff + bitno; word; bitno++)
+            {
+              if (word & 1)
+                {
+                  list[count++] = bitno;
+                  if (count >= num)
+                    {
+                      *next = bitno + 1;
+                      return count;
+                    }
+                }
+              word >>= 1;
+            }
+          windex++;
+        }
       bitoff = windex * BITSET_WORD_BITS;
     }
 
   for (; windex < size; windex++, bitoff += BITSET_WORD_BITS)
     {
       if (!(word = srcp[windex]))
-       continue;
+        continue;
 
       if ((count + BITSET_WORD_BITS) < num)
-       {
-         for (bitno = bitoff; word; bitno++)
-           {
-             if (word & 1)
-               list[count++] = bitno;
-             word >>= 1;
-           }
-       }
+        {
+          for (bitno = bitoff; word; bitno++)
+            {
+              if (word & 1)
+                list[count++] = bitno;
+              word >>= 1;
+            }
+        }
       else
-       {
-         for (bitno = bitoff; word; bitno++)
-           {
-             if (word & 1)
-               {
-                 list[count++] = bitno;
-                 if (count >= num)
-                   {
-                     *next = bitno + 1;
-                     return count;
-                   }
-               }
-             word >>= 1;
-           }
-       }
+        {
+          for (bitno = bitoff; word; bitno++)
+            {
+              if (word & 1)
+                {
+                  list[count++] = bitno;
+                  if (count >= num)
+                    {
+                      *next = bitno + 1;
+                      return count;
+                    }
+                }
+              word >>= 1;
+            }
+        }
     }
 
   *next = bitoff;
@@ -387,7 +387,7 @@ abitset_equal_p (bitset dst, bitset src)
 
   for (i = 0; i < size; i++)
       if (*srcp++ != *dstp++)
-         return false;
+          return false;
   return true;
 }
 
@@ -402,7 +402,7 @@ abitset_subset_p (bitset dst, bitset src)
 
   for (i = 0; i < size; i++, dstp++, srcp++)
       if (*dstp != (*srcp | *dstp))
-         return false;
+          return false;
   return true;
 }
 
@@ -417,7 +417,7 @@ abitset_disjoint_p (bitset dst, bitset src)
 
   for (i = 0; i < size; i++)
       if (*srcp++ & *dstp++)
-         return false;
+          return false;
 
   return true;
 }
@@ -452,10 +452,10 @@ abitset_and_cmp (bitset dst, bitset src1, bitset src2)
       bitset_word tmp = *src1p++ & *src2p++;
 
       if (*dstp != tmp)
-       {
-         changed = true;
-         *dstp = tmp;
-       }
+        {
+          changed = true;
+          *dstp = tmp;
+        }
     }
   return changed;
 }
@@ -490,10 +490,10 @@ abitset_andn_cmp (bitset dst, bitset src1, bitset src2)
       bitset_word tmp = *src1p++ & ~(*src2p++);
 
       if (*dstp != tmp)
-       {
-         changed = true;
-         *dstp = tmp;
-       }
+        {
+          changed = true;
+          *dstp = tmp;
+        }
     }
   return changed;
 }
@@ -528,10 +528,10 @@ abitset_or_cmp (bitset dst, bitset src1, bitset src2)
       bitset_word tmp = *src1p++ | *src2p++;
 
       if (*dstp != tmp)
-       {
-         changed = true;
-         *dstp = tmp;
-       }
+        {
+          changed = true;
+          *dstp = tmp;
+        }
     }
   return changed;
 }
@@ -566,10 +566,10 @@ abitset_xor_cmp (bitset dst, bitset src1, bitset src2)
       bitset_word tmp = *src1p++ ^ *src2p++;
 
       if (*dstp != tmp)
-       {
-         changed = true;
-         *dstp = tmp;
-       }
+        {
+          changed = true;
+          *dstp = tmp;
+        }
     }
   return changed;
 }
@@ -606,10 +606,10 @@ abitset_and_or_cmp (bitset dst, bitset src1, bitset src2, bitset src3)
       bitset_word tmp = (*src1p++ & *src2p++) | *src3p++;
 
       if (*dstp != tmp)
-       {
-         changed = true;
-         *dstp = tmp;
-       }
+        {
+          changed = true;
+          *dstp = tmp;
+        }
     }
   return changed;
 }
@@ -646,10 +646,10 @@ abitset_andn_or_cmp (bitset dst, bitset src1, bitset src2, bitset src3)
       bitset_word tmp = (*src1p++ & ~(*src2p++)) | *src3p++;
 
       if (*dstp != tmp)
-       {
-         changed = true;
-         *dstp = tmp;
-       }
+        {
+          changed = true;
+          *dstp = tmp;
+        }
     }
   return changed;
 }
@@ -686,10 +686,10 @@ abitset_or_and_cmp (bitset dst, bitset src1, bitset src2, bitset src3)
       bitset_word tmp = (*src1p++ | *src2p++) & *src3p++;
 
       if (*dstp != tmp)
-       {
-         changed = true;
-         *dstp = tmp;
-       }
+        {
+          changed = true;
+          *dstp = tmp;
+        }
     }
   return changed;
 }
index ce9d56bdd402c779831de41b62dbd0f1a3769d3d..443d2da2e8e9c027945ce93fcedf4aebb2e6c2d5 100644 (file)
@@ -32,9 +32,9 @@
                   Memory for bit array and bitset structure allocated
                   contiguously.
    BITSET_LIST:   Linked list of arrays of bits (variable size, least storage
-                 for large very sparse sets).
+                  for large very sparse sets).
    BITSET_TABLE:  Expandable table of pointers to arrays of bits
-                 (variable size, less storage for large sparse sets).
+                  (variable size, less storage for large sparse sets).
                   Faster than BITSET_LIST for random access.
    BITSET_VARRAY: Variable array of bits (variable size, fast for
                   dense bitsets).
@@ -42,7 +42,7 @@
                   statistics and/or better run-time checking.
 */
 enum bitset_type {BITSET_ARRAY, BITSET_LIST, BITSET_TABLE, BITSET_VARRAY,
-                 BITSET_TYPE_NUM, BITSET_STATS};
+                  BITSET_TYPE_NUM, BITSET_STATS};
 #define BITSET_TYPE_NAMES {"abitset", "lbitset", "ebitset", "vbitset"}
 
 extern const char * const bitset_type_names[];
@@ -78,19 +78,19 @@ typedef size_t bitset_windex;
 #define BITSET_LIST_SIZE 1024
 
 enum bitset_ops {BITSET_OP_ZERO, BITSET_OP_ONES,
-                BITSET_OP_COPY, BITSET_OP_NOT,
-                BITSET_OP_EMPTY_P, BITSET_OP_EQUAL_P,
-                BITSET_OP_SUBSET_P, BITSET_OP_DISJOINT_P,
-                BITSET_OP_AND, BITSET_OP_OR, BITSET_OP_XOR, BITSET_OP_ANDN,
-                BITSET_OP_OR_AND, BITSET_OP_AND_OR, BITSET_OP_ANDN_OR};
+                 BITSET_OP_COPY, BITSET_OP_NOT,
+                 BITSET_OP_EMPTY_P, BITSET_OP_EQUAL_P,
+                 BITSET_OP_SUBSET_P, BITSET_OP_DISJOINT_P,
+                 BITSET_OP_AND, BITSET_OP_OR, BITSET_OP_XOR, BITSET_OP_ANDN,
+                 BITSET_OP_OR_AND, BITSET_OP_AND_OR, BITSET_OP_ANDN_OR};
 
 struct bbitset_struct
 {
   const struct bitset_vtable *vtable;
-  bitset_windex cindex;                /* Cache word index.  */
-  bitset_windex csize;         /* Cache size in words.  */
-  bitset_word *cdata;          /* Cache data pointer.  */
-  bitset_bindex n_bits;                /* Number of bits.  */
+  bitset_windex cindex;         /* Cache word index.  */
+  bitset_windex csize;          /* Cache size in words.  */
+  bitset_word *cdata;           /* Cache data pointer.  */
+  bitset_bindex n_bits;         /* Number of bits.  */
   /* Perhaps we could sacrifice another word to indicate
      that the bitset is known to be zero, that a bit has been set
      in the cache, and that a bit has been cleared in the cache.
@@ -148,9 +148,9 @@ struct bitset_vtable
   bool (*or_and_cmp) (bitset, bitset, bitset, bitset);
 
   bitset_bindex (*list) (bitset, bitset_bindex *, bitset_bindex,
-                        bitset_bindex *);
+                         bitset_bindex *);
   bitset_bindex (*list_reverse) (bitset, bitset_bindex *, bitset_bindex,
-                                bitset_bindex *);
+                                 bitset_bindex *);
   void (*free) (bitset);
   enum bitset_type type;
 };
index 2bb203359e40becee8d54b759a6cf59fb50455ac..f7a9996afb4e5214ec789108e4e469c54343ba6c 100644 (file)
@@ -151,7 +151,7 @@ bitset_alloc (bitset_bindex n_bits, enum bitset_type type)
 /* Create a bitset of N_BITS of type TYPE.  */
 bitset
 bitset_obstack_alloc (struct obstack *bobstack,
-                     bitset_bindex n_bits, enum bitset_type type)
+                      bitset_bindex n_bits, enum bitset_type type)
 {
   size_t bytes;
   bitset bset;
@@ -296,15 +296,15 @@ bitset_print (FILE *file, bitset bset, bool verbose)
 
   if (verbose)
     fprintf (file, "n_bits = %lu, set = {",
-            (unsigned long int) bitset_size (bset));
+             (unsigned long int) bitset_size (bset));
 
   pos = 30;
   BITSET_FOR_EACH (iter, bset, i, 0)
   {
     if (pos > 70)
       {
-       fprintf (file, "\n");
-       pos = 0;
+        fprintf (file, "\n");
+        pos = 0;
       }
 
     fprintf (file, "%lu ", (unsigned long int) i);
@@ -407,7 +407,7 @@ bitset_copy_ (bitset dst, bitset src)
    four operand operations.  */
 static inline bool
 bitset_op4_cmp (bitset dst, bitset src1, bitset src2, bitset src3,
-               enum bitset_ops op)
+                enum bitset_ops op)
 {
   bool changed = false;
   bool stats_enabled_save;
index 64592426cc7fec31d53880842a3204a26d3a346f..ef44ea4cf860c87da09975daa769ec9949d65b73 100644 (file)
 
 /* Attributes used to select a bitset implementation.  */
 enum bitset_attr {BITSET_FIXED = 1,    /* Bitset size fixed.  */
-                 BITSET_VARIABLE = 2, /* Bitset size variable.  */
-                 BITSET_DENSE = 4,    /* Bitset dense.  */
-                 BITSET_SPARSE = 8,   /* Bitset sparse.  */
-                 BITSET_FRUGAL = 16,  /* Prefer most compact.  */
-                 BITSET_GREEDY = 32}; /* Prefer fastest at memory expense.  */
+                  BITSET_VARIABLE = 2, /* Bitset size variable.  */
+                  BITSET_DENSE = 4,    /* Bitset dense.  */
+                  BITSET_SPARSE = 8,   /* Bitset sparse.  */
+                  BITSET_FRUGAL = 16,  /* Prefer most compact.  */
+                  BITSET_GREEDY = 32}; /* Prefer fastest at memory expense.  */
 
 typedef unsigned int bitset_attrs;
 
@@ -49,26 +49,26 @@ union bitset_union
 {
   /* This must be the first member of every other structure that is a
      member of this union.  */
-  struct bbitset_struct b;             /* Base bitset data.  */
+  struct bbitset_struct b;              /* Base bitset data.  */
 
   struct abitset_struct
   {
     struct bbitset_struct b;
-    bitset_word words[1];              /* The array of bits.  */
+    bitset_word words[1];               /* The array of bits.  */
   } a;
 
   struct ebitset_struct
   {
     struct bbitset_struct b;
-    bitset_windex size;                        /* Number of elements.  */
-    struct ebitset_elt_struct **elts;  /* Expanding array of ptrs to elts.  */
+    bitset_windex size;                 /* Number of elements.  */
+    struct ebitset_elt_struct **elts;   /* Expanding array of ptrs to elts.  */
   } e;
 
   struct lbitset_struct
   {
     struct bbitset_struct b;
-    struct lbitset_elt_struct *head;   /* First element in linked list.  */
-    struct lbitset_elt_struct *tail;   /* Last element in linked list.  */
+    struct lbitset_elt_struct *head;    /* First element in linked list.  */
+    struct lbitset_elt_struct *tail;    /* Last element in linked list.  */
   } l;
 
   struct bitset_stats_struct
@@ -80,7 +80,7 @@ union bitset_union
   struct vbitset_struct
   {
     struct bbitset_struct b;
-    bitset_windex size;                        /* Allocated size of array.  */
+    bitset_windex size;                 /* Allocated size of array.  */
   } v;
 
 };
@@ -116,7 +116,7 @@ extern void bitset_free (bitset);
 /* Create a bitset of desired type and size using an obstack.  The
    bitset is zeroed.  */
 extern bitset bitset_obstack_alloc (struct obstack *bobstack,
-                                   bitset_bindex, enum bitset_type);
+                                    bitset_bindex, enum bitset_type);
 
 /* Free bitset allocated on obstack.  */
 extern void bitset_obstack_free (bitset);
@@ -312,14 +312,14 @@ extern void bitset_dump (FILE *, bitset);
       printf ("%lu ", (unsigned long int) i);
    };
 */
-#define BITSET_FOR_EACH(ITER, BSET, INDEX, MIN)                                      \
-  for (ITER.next = (MIN), ITER.num = BITSET_LIST_SIZE;                       \
-       (ITER.num == BITSET_LIST_SIZE)                                        \
-       && (ITER.num = bitset_list (BSET, ITER.list,                          \
-                                  BITSET_LIST_SIZE, &ITER.next));)           \
-    for (ITER.i = 0;                                                         \
-        ITER.i < ITER.num && ((INDEX) = ITER.list[ITER.i], 1);               \
-        ITER.i++)
+#define BITSET_FOR_EACH(ITER, BSET, INDEX, MIN)                               \
+  for (ITER.next = (MIN), ITER.num = BITSET_LIST_SIZE;                        \
+       (ITER.num == BITSET_LIST_SIZE)                                         \
+       && (ITER.num = bitset_list (BSET, ITER.list,                           \
+                                   BITSET_LIST_SIZE, &ITER.next));)           \
+    for (ITER.i = 0;                                                          \
+         ITER.i < ITER.num && ((INDEX) = ITER.list[ITER.i], 1);               \
+         ITER.i++)
 
 
 /* Loop over all elements of BSET, in reverse order starting with
@@ -334,14 +334,14 @@ extern void bitset_dump (FILE *, bitset);
       printf ("%lu ", (unsigned long int) i);
    };
 */
-#define BITSET_FOR_EACH_REVERSE(ITER, BSET, INDEX, MIN)                              \
-  for (ITER.next = (MIN), ITER.num = BITSET_LIST_SIZE;                       \
-       (ITER.num == BITSET_LIST_SIZE)                                        \
-       && (ITER.num = bitset_list_reverse (BSET, ITER.list,                  \
-                                          BITSET_LIST_SIZE, &ITER.next));)   \
-    for (ITER.i = 0;                                                         \
-        ITER.i < ITER.num && ((INDEX) = ITER.list[ITER.i], 1);               \
-        ITER.i++)
+#define BITSET_FOR_EACH_REVERSE(ITER, BSET, INDEX, MIN)                       \
+  for (ITER.next = (MIN), ITER.num = BITSET_LIST_SIZE;                        \
+       (ITER.num == BITSET_LIST_SIZE)                                         \
+       && (ITER.num = bitset_list_reverse (BSET, ITER.list,                   \
+                                           BITSET_LIST_SIZE, &ITER.next));)   \
+    for (ITER.i = 0;                                                          \
+         ITER.i < ITER.num && ((INDEX) = ITER.list[ITER.i], 1);               \
+         ITER.i++)
 
 
 /* Define set operations in terms of logical operations.  */
index f099b4b31423d725c2e69be7e92c296b6768205c..83163026165a1fa45d5197f099027bea2ef9a76b 100644 (file)
 
 
 /* Accessor macros.  */
-#define BITSET_STATS_ALLOCS_INC(TYPE)                  \
+#define BITSET_STATS_ALLOCS_INC(TYPE)                   \
     bitset_stats_info->types[(TYPE)].allocs++
-#define BITSET_STATS_FREES_INC(BSET)                   \
+#define BITSET_STATS_FREES_INC(BSET)                    \
     bitset_stats_info->types[BITSET_TYPE_ (BSET)].frees++
-#define BITSET_STATS_SETS_INC(BSET)                    \
+#define BITSET_STATS_SETS_INC(BSET)                     \
     bitset_stats_info->types[BITSET_TYPE_ (BSET)].sets++
-#define BITSET_STATS_CACHE_SETS_INC(BSET)              \
+#define BITSET_STATS_CACHE_SETS_INC(BSET)               \
     bitset_stats_info->types[BITSET_TYPE_ (BSET)].cache_sets++
-#define BITSET_STATS_RESETS_INC(BSET)                  \
+#define BITSET_STATS_RESETS_INC(BSET)                   \
     bitset_stats_info->types[BITSET_TYPE_ (BSET)].resets++
-#define BITSET_STATS_CACHE_RESETS_INC(BSET)            \
+#define BITSET_STATS_CACHE_RESETS_INC(BSET)             \
     bitset_stats_info->types[BITSET_TYPE_ (BSET)].cache_resets++
-#define BITSET_STATS_TESTS_INC(BSET)                   \
+#define BITSET_STATS_TESTS_INC(BSET)                    \
     bitset_stats_info->types[BITSET_TYPE_ (BSET)].tests++
-#define BITSET_STATS_CACHE_TESTS_INC(BSET)             \
+#define BITSET_STATS_CACHE_TESTS_INC(BSET)              \
     bitset_stats_info->types[BITSET_TYPE_ (BSET)].cache_tests++
-#define BITSET_STATS_LISTS_INC(BSET)                   \
+#define BITSET_STATS_LISTS_INC(BSET)                    \
     bitset_stats_info->types[BITSET_TYPE_ (BSET)].lists++
-#define BITSET_STATS_LIST_COUNTS_INC(BSET, I)          \
+#define BITSET_STATS_LIST_COUNTS_INC(BSET, I)           \
     bitset_stats_info->types[BITSET_TYPE_ (BSET)].list_counts[(I)]++
-#define BITSET_STATS_LIST_SIZES_INC(BSET, I)           \
+#define BITSET_STATS_LIST_SIZES_INC(BSET, I)            \
     bitset_stats_info->types[BITSET_TYPE_ (BSET)].list_sizes[(I)]++
-#define BITSET_STATS_LIST_DENSITY_INC(BSET, I)         \
+#define BITSET_STATS_LIST_DENSITY_INC(BSET, I)          \
     bitset_stats_info->types[BITSET_TYPE_ (BSET)].list_density[(I)]++
 
 
@@ -105,7 +105,7 @@ bool bitset_stats_enabled = false;
 /* Print a percentage histogram with message MSG to FILE.  */
 static void
 bitset_percent_histogram_print (FILE *file, const char *name, const char *msg,
-                               unsigned int n_bins, unsigned int *bins)
+                                unsigned int n_bins, unsigned int *bins)
 {
   unsigned int i;
   unsigned int total;
@@ -120,16 +120,16 @@ bitset_percent_histogram_print (FILE *file, const char *name, const char *msg,
   fprintf (file, "%s %s", name, msg);
   for (i = 0; i < n_bins; i++)
     fprintf (file, "%.0f-%.0f%%\t%8u (%5.1f%%)\n",
-            i * 100.0 / n_bins,
-            (i + 1) * 100.0 / n_bins, bins[i],
-            (100.0 * bins[i]) / total);
+             i * 100.0 / n_bins,
+             (i + 1) * 100.0 / n_bins, bins[i],
+             (100.0 * bins[i]) / total);
 }
 
 
 /* Print a log histogram with message MSG to FILE.  */
 static void
 bitset_log_histogram_print (FILE *file, const char *name, const char *msg,
-                           unsigned int n_bins, unsigned int *bins)
+                            unsigned int n_bins, unsigned int *bins)
 {
   unsigned int i;
   unsigned int total;
@@ -153,50 +153,50 @@ bitset_log_histogram_print (FILE *file, const char *name, const char *msg,
   fprintf (file, "%s %s", name, msg);
   for (i = 0; i < 2; i++)
     fprintf (file, "%*d\t%8u (%5.1f%%)\n",
-            max_width, i, bins[i], 100.0 * bins[i] / total);
+             max_width, i, bins[i], 100.0 * bins[i] / total);
 
   for (; i < n_bins; i++)
     fprintf (file, "%*lu-%lu\t%8u (%5.1f%%)\n",
-            max_width - ((unsigned int) (0.30103 * (i) + 0.9999) + 1),
-            1UL << (i - 1),
-            (1UL << i) - 1,
-            bins[i],
-            (100.0 * bins[i]) / total);
+             max_width - ((unsigned int) (0.30103 * (i) + 0.9999) + 1),
+             1UL << (i - 1),
+             (1UL << i) - 1,
+             bins[i],
+             (100.0 * bins[i]) / total);
 }
 
 
 /* Print bitset statistics to FILE.  */
 static void
 bitset_stats_print_1 (FILE *file, const char *name,
-                     struct bitset_type_info_struct *stats)
+                      struct bitset_type_info_struct *stats)
 {
   if (!stats)
     return;
 
   fprintf (file, "%s:\n", name);
   fprintf (file, _("%u bitset_allocs, %u freed (%.2f%%).\n"),
-          stats->allocs, stats->frees,
-          stats->allocs ? 100.0 * stats->frees / stats->allocs : 0);
+           stats->allocs, stats->frees,
+           stats->allocs ? 100.0 * stats->frees / stats->allocs : 0);
   fprintf (file, _("%u bitset_sets, %u cached (%.2f%%)\n"),
-          stats->sets, stats->cache_sets,
-          stats->sets ? 100.0 * stats->cache_sets / stats->sets : 0);
+           stats->sets, stats->cache_sets,
+           stats->sets ? 100.0 * stats->cache_sets / stats->sets : 0);
   fprintf (file, _("%u bitset_resets, %u cached (%.2f%%)\n"),
-          stats->resets, stats->cache_resets,
-          stats->resets ? 100.0 * stats->cache_resets / stats->resets : 0);
+           stats->resets, stats->cache_resets,
+           stats->resets ? 100.0 * stats->cache_resets / stats->resets : 0);
   fprintf (file, _("%u bitset_tests, %u cached (%.2f%%)\n"),
-          stats->tests, stats->cache_tests,
-          stats->tests ? 100.0 * stats->cache_tests / stats->tests : 0);
+           stats->tests, stats->cache_tests,
+           stats->tests ? 100.0 * stats->cache_tests / stats->tests : 0);
 
   fprintf (file, _("%u bitset_lists\n"), stats->lists);
 
   bitset_log_histogram_print (file, name, _("count log histogram\n"),
-                             BITSET_LOG_COUNT_BINS, stats->list_counts);
+                              BITSET_LOG_COUNT_BINS, stats->list_counts);
 
   bitset_log_histogram_print (file, name, _("size log histogram\n"),
-                             BITSET_LOG_SIZE_BINS, stats->list_sizes);
+                              BITSET_LOG_SIZE_BINS, stats->list_sizes);
 
   bitset_percent_histogram_print (file, name, _("density histogram\n"),
-                                 BITSET_DENSITY_BINS, stats->list_density);
+                                  BITSET_DENSITY_BINS, stats->list_density);
 }
 
 
@@ -216,7 +216,7 @@ bitset_stats_print (FILE *file, bool verbose ATTRIBUTE_UNUSED)
 
   for (i = 0; i < BITSET_TYPE_NUM; i++)
     bitset_stats_print_1 (file, bitset_type_names[i],
-                         &bitset_stats_info->types[i]);
+                          &bitset_stats_info->types[i]);
 }
 
 
@@ -340,7 +340,7 @@ bitset_stats_reset (bitset dst, bitset_bindex bitno)
   if (offset < bset->b.csize)
     {
       bset->b.cdata[offset] &=
-       ~((bitset_word) 1 << (bitno % BITSET_WORD_BITS));
+        ~((bitset_word) 1 << (bitno % BITSET_WORD_BITS));
       BITSET_STATS_CACHE_RESETS_INC (bset);
     }
   else
@@ -570,7 +570,7 @@ bitset_stats_or_and_cmp (bitset dst, bitset src1, bitset src2, bitset src3)
 
 static bitset_bindex
 bitset_stats_list (bitset bset, bitset_bindex *list,
-                  bitset_bindex num, bitset_bindex *next)
+                   bitset_bindex num, bitset_bindex *next)
 {
   bitset_bindex count;
   bitset_bindex tmp;
@@ -607,7 +607,7 @@ bitset_stats_list (bitset bset, bitset_bindex *list,
 
 static bitset_bindex
 bitset_stats_list_reverse (bitset bset, bitset_bindex *list,
-                          bitset_bindex num, bitset_bindex *next)
+                           bitset_bindex num, bitset_bindex *next)
 {
   return BITSET_LIST_REVERSE_ (bset->s.bset, list, num, next);
 }
index 4b44b5657605e748a61a2c5854ebcfa6fa2c8c8c..dd544a9c9eae02a773156983cebaf76b6b38a976 100644 (file)
@@ -56,7 +56,7 @@ bitsetv_matrix_dump (FILE * out, const char *title, bitsetv bset)
     {
       fprintf (out, "%2lu|", (unsigned long int) i);
       for (j = 0; j < hsize; ++j)
-       fputs (bitset_test (bset[i], j) ? "1" : " ", out);
+        fputs (bitset_test (bset[i], j) ? "1" : " ", out);
       fputs ("|\n", out);
     }
 
index 8d925aa38335844a66df8d3e8e68a3134879902f..2bdf1bfa1a6d0b8aff8c0ad6beb05b37a5a54677 100644 (file)
@@ -27,7 +27,7 @@
    type TYPE.  */
 bitset *
 bitsetv_alloc (bitset_bindex n_vecs, bitset_bindex n_bits,
-              enum bitset_type type)
+               enum bitset_type type)
 {
   size_t vector_bytes;
   size_t bytes;
@@ -116,7 +116,7 @@ bitsetv_transitive_closure (bitsetv bsetv)
   for (i = 0; bsetv[i]; i++)
     for (j = 0; bsetv[j]; j++)
       if (bitset_test (bsetv[j], i))
-       bitset_or (bsetv[j], bsetv[j], bsetv[i]);
+        bitset_or (bsetv[j], bsetv[j], bsetv[i]);
 }
 
 
@@ -139,7 +139,7 @@ bitsetv_reflexive_transitive_closure (bitsetv bsetv)
    FILE.  */
 void
 bitsetv_dump (FILE *file, char const *title, char const *subtitle,
-             bitsetv bsetv)
+              bitsetv bsetv)
 {
   bitset_windex i;
 
index 9d9341fb6f8c5907cb4765fa2ea895f3e8b76df6..e5d6c9239b7263ca526fd2733258e08c6bc61105 100644 (file)
@@ -58,7 +58,7 @@ typedef struct ebitset_elt_struct
 {
   union
   {
-    bitset_word words[EBITSET_ELT_WORDS];      /* Bits that are set.  */
+    bitset_word words[EBITSET_ELT_WORDS];       /* Bits that are set.  */
     struct ebitset_elt_struct *next;
   }
   u;
@@ -84,7 +84,7 @@ static ebitset_elt ebitset_zero_elts[1]; /* Elements of all zero bits.  */
 /* Obstack to allocate bitset elements from.  */
 static struct obstack ebitset_obstack;
 static bool ebitset_obstack_init = false;
-static ebitset_elt *ebitset_free_list; /* Free list of bitset elements.  */
+static ebitset_elt *ebitset_free_list;  /* Free list of bitset elements.  */
 
 #define EBITSET_N_ELTS(N) (((N) + EBITSET_ELT_BITS - 1) / EBITSET_ELT_BITS)
 #define EBITSET_ELTS(BSET) ((BSET)->e.elts)
@@ -96,7 +96,7 @@ static ebitset_elt *ebitset_free_list;        /* Free list of bitset elements.  */
 
 /* Disable bitset cache and mark BSET as being zero.  */
 #define EBITSET_ZERO_SET(BSET) ((BSET)->b.cindex = BITSET_WINDEX_MAX, \
-       (BSET)->b.cdata = 0)
+        (BSET)->b.cdata = 0)
 
 #define EBITSET_CACHE_DISABLE(BSET)  ((BSET)->b.cindex = BITSET_WINDEX_MAX)
 
@@ -136,37 +136,37 @@ ebitset_resize (bitset src, bitset_bindex n_bits)
       bitset_windex size;
 
       /* The bitset needs to grow.  If we already have enough memory
-        allocated, then just zero what we need.  */
+         allocated, then just zero what we need.  */
       if (newsize > EBITSET_ASIZE (src))
-       {
-         /* We need to allocate more memory.  When oldsize is
-            non-zero this means that we are changing the size, so
-            grow the bitset 25% larger than requested to reduce
-            number of reallocations.  */
-
-         if (oldsize == 0)
-           size = newsize;
-         else
-           size = newsize + newsize / 4;
-
-         EBITSET_ELTS (src)
-           = realloc (EBITSET_ELTS (src), size * sizeof (ebitset_elt *));
-         EBITSET_ASIZE (src) = size;
-       }
+        {
+          /* We need to allocate more memory.  When oldsize is
+             non-zero this means that we are changing the size, so
+             grow the bitset 25% larger than requested to reduce
+             number of reallocations.  */
+
+          if (oldsize == 0)
+            size = newsize;
+          else
+            size = newsize + newsize / 4;
+
+          EBITSET_ELTS (src)
+            = realloc (EBITSET_ELTS (src), size * sizeof (ebitset_elt *));
+          EBITSET_ASIZE (src) = size;
+        }
 
       memset (EBITSET_ELTS (src) + oldsize, 0,
-             (newsize - oldsize) * sizeof (ebitset_elt *));
+              (newsize - oldsize) * sizeof (ebitset_elt *));
     }
   else
     {
       /* The bitset needs to shrink.  There's no point deallocating
-        the memory unless it is shrinking by a reasonable amount.  */
+         the memory unless it is shrinking by a reasonable amount.  */
       if ((oldsize - newsize) >= oldsize / 2)
-       {
-         EBITSET_ELTS (src)
-           = realloc (EBITSET_ELTS (src), newsize * sizeof (ebitset_elt *));
-         EBITSET_ASIZE (src) = newsize;
-       }
+        {
+          EBITSET_ELTS (src)
+            = realloc (EBITSET_ELTS (src), newsize * sizeof (ebitset_elt *));
+          EBITSET_ASIZE (src) = newsize;
+        }
 
       /* Need to prune any excess bits.  FIXME.  */
     }
@@ -190,16 +190,16 @@ ebitset_elt_alloc (void)
   else
     {
       if (!ebitset_obstack_init)
-       {
-         ebitset_obstack_init = true;
+        {
+          ebitset_obstack_init = true;
 
-         /* Let particular systems override the size of a chunk.  */
+          /* Let particular systems override the size of a chunk.  */
 
 #ifndef OBSTACK_CHUNK_SIZE
 #define OBSTACK_CHUNK_SIZE 0
 #endif
 
-         /* Let them override the alloc and free routines too.  */
+          /* Let them override the alloc and free routines too.  */
 
 #ifndef OBSTACK_CHUNK_ALLOC
 #define OBSTACK_CHUNK_ALLOC xmalloc
@@ -213,16 +213,16 @@ ebitset_elt_alloc (void)
 #define __alignof__(type) 0
 #endif
 
-         obstack_specify_allocation (&ebitset_obstack, OBSTACK_CHUNK_SIZE,
-                                     __alignof__ (ebitset_elt),
-                                     OBSTACK_CHUNK_ALLOC,
-                                     OBSTACK_CHUNK_FREE);
-       }
+          obstack_specify_allocation (&ebitset_obstack, OBSTACK_CHUNK_SIZE,
+                                      __alignof__ (ebitset_elt),
+                                      OBSTACK_CHUNK_ALLOC,
+                                      OBSTACK_CHUNK_FREE);
+        }
 
       /* Perhaps we should add a number of new elements to the free
-        list.  */
+         list.  */
       elt = (ebitset_elt *) obstack_alloc (&ebitset_obstack,
-                                          sizeof (ebitset_elt));
+                                           sizeof (ebitset_elt));
     }
 
   return elt;
@@ -293,7 +293,7 @@ ebitset_elt_zero_p (ebitset_elt *elt)
 
 static ebitset_elt *
 ebitset_elt_find (bitset bset, bitset_bindex bindex,
-                 enum ebitset_find_mode mode)
+                  enum ebitset_find_mode mode)
 {
   ebitset_elt *elt;
   bitset_windex size;
@@ -308,13 +308,13 @@ ebitset_elt_find (bitset bset, bitset_bindex bindex,
   if (eindex < size)
     {
       if ((elt = elts[eindex]))
-       {
-         if (EBITSET_WORDS (elt) == bset->b.cdata)
-           return elt;
+        {
+          if (EBITSET_WORDS (elt) == bset->b.cdata)
+            return elt;
 
-         EBITSET_CACHE_SET (bset, eindex);
-         return elt;
-       }
+          EBITSET_CACHE_SET (bset, eindex);
+          return elt;
+        }
     }
 
   /* The element could not be found.  */
@@ -329,7 +329,7 @@ ebitset_elt_find (bitset bset, bitset_bindex bindex,
 
     case EBITSET_CREATE:
       if (eindex >= size)
-       ebitset_resize (bset, bindex);
+        ebitset_resize (bset, bindex);
 
       /* Create a new element.  */
       elt = ebitset_elt_calloc ();
@@ -361,22 +361,22 @@ ebitset_weed (bitset bset)
       ebitset_elt *elt = elts[j];
 
       if (elt)
-       {
-         if (ebitset_elt_zero_p (elt))
-           {
-             ebitset_elt_remove (bset, j);
-             count++;
-           }
-       }
+        {
+          if (ebitset_elt_zero_p (elt))
+            {
+              ebitset_elt_remove (bset, j);
+              count++;
+            }
+        }
       else
-       count++;
+        count++;
     }
 
   count = j - count;
   if (!count)
     {
       /* All the bits are zero.  We could shrink the elts.
-        For now just mark BSET as known to be zero.  */
+         For now just mark BSET as known to be zero.  */
       EBITSET_ZERO_SET (bset);
     }
   else
@@ -402,7 +402,7 @@ ebitset_zero (bitset bset)
       ebitset_elt *elt = elts[j];
 
       if (elt)
-       ebitset_elt_remove (bset, j);
+        ebitset_elt_remove (bset, j);
     }
 
   /* All the bits are zero.  We could shrink the elts.
@@ -437,13 +437,13 @@ ebitset_equal_p (bitset dst, bitset src)
       ebitset_elt *delt = delts[j];
 
       if (!selt && !delt)
-       continue;
+        continue;
       if ((selt && !delt) || (!selt && delt))
-       return false;
+        return false;
 
       for (i = 0; i < EBITSET_ELT_WORDS; i++)
-       if (EBITSET_WORDS (selt)[i] != EBITSET_WORDS (delt)[i])
-         return false;
+        if (EBITSET_WORDS (selt)[i] != EBITSET_WORDS (delt)[i])
+          return false;
     }
   return true;
 }
@@ -472,14 +472,14 @@ ebitset_copy_ (bitset dst, bitset src)
       ebitset_elt *selt = selts[j];
 
       if (selt)
-       {
-         ebitset_elt *tmp;
-
-         tmp = ebitset_elt_alloc ();
-         delts[j] = tmp;
-         memcpy (EBITSET_WORDS (tmp), EBITSET_WORDS (selt),
-                 sizeof (EBITSET_WORDS (selt)));
-       }
+        {
+          ebitset_elt *tmp;
+
+          tmp = ebitset_elt_alloc ();
+          delts[j] = tmp;
+          memcpy (EBITSET_WORDS (tmp), EBITSET_WORDS (selt),
+                  sizeof (EBITSET_WORDS (selt)));
+        }
     }
   EBITSET_NONZERO_SET (dst);
 }
@@ -545,9 +545,9 @@ ebitset_test (bitset src, bitset_bindex bitno)
   bitset_windex windex = bitno / BITSET_WORD_BITS;
 
   return (ebitset_elt_find (src, bitno, EBITSET_FIND)
-         && ((src->b.cdata[windex - src->b.cindex]
-              >> (bitno % BITSET_WORD_BITS))
-             & 1));
+          && ((src->b.cdata[windex - src->b.cindex]
+               >> (bitno % BITSET_WORD_BITS))
+              & 1));
 }
 
 
@@ -564,7 +564,7 @@ ebitset_free (bitset bset)
  found and with *NEXT indicating where search stopped.  */
 static bitset_bindex
 ebitset_list_reverse (bitset bset, bitset_bindex *list,
-                     bitset_bindex num, bitset_bindex *next)
+                      bitset_bindex num, bitset_bindex *next)
 {
   bitset_bindex n_bits;
   bitset_bindex bitno;
@@ -610,33 +610,33 @@ ebitset_list_reverse (bitset bset, bitset_bindex *list,
 
       elt = elts[eindex];
       if (elt)
-       {
-         srcp = EBITSET_WORDS (elt);
-
-         do
-           {
-             bitset_word word;
-
-             word = srcp[woffset] << (BITSET_WORD_BITS - 1 - bcount);
-
-             for (; word; bcount--)
-               {
-                 if (word & BITSET_MSB)
-                   {
-                     list[count++] = boffset + bcount;
-                     if (count >= num)
-                       {
-                         *next = n_bits - (boffset + bcount);
-                         return count;
-                       }
-                   }
-                 word <<= 1;
-               }
-             boffset -= BITSET_WORD_BITS;
-             bcount = BITSET_WORD_BITS - 1;
-           }
-         while (woffset--);
-       }
+        {
+          srcp = EBITSET_WORDS (elt);
+
+          do
+            {
+              bitset_word word;
+
+              word = srcp[woffset] << (BITSET_WORD_BITS - 1 - bcount);
+
+              for (; word; bcount--)
+                {
+                  if (word & BITSET_MSB)
+                    {
+                      list[count++] = boffset + bcount;
+                      if (count >= num)
+                        {
+                          *next = n_bits - (boffset + bcount);
+                          return count;
+                        }
+                    }
+                  word <<= 1;
+                }
+              boffset -= BITSET_WORD_BITS;
+              bcount = BITSET_WORD_BITS - 1;
+            }
+          while (woffset--);
+        }
 
       woffset = EBITSET_ELT_WORDS - 1;
       boffset = eindex * EBITSET_ELT_BITS - BITSET_WORD_BITS;
@@ -653,7 +653,7 @@ ebitset_list_reverse (bitset bset, bitset_bindex *list,
  found and with *NEXT indicating where search stopped.  */
 static bitset_bindex
 ebitset_list (bitset bset, bitset_bindex *list,
-             bitset_bindex num, bitset_bindex *next)
+              bitset_bindex num, bitset_bindex *next)
 {
   bitset_bindex bitno;
   bitset_windex windex;
@@ -680,33 +680,33 @@ ebitset_list (bitset bset, bitset_bindex *list,
 
       elt = elts[eindex];
       if (elt)
-       {
-         bitset_windex woffset;
-         bitset_word *srcp = EBITSET_WORDS (elt);
-
-         windex = bitno / BITSET_WORD_BITS;
-         woffset = eindex * EBITSET_ELT_WORDS;
-
-         for (; (windex - woffset) < EBITSET_ELT_WORDS; windex++)
-           {
-             word = srcp[windex - woffset] >> (bitno % BITSET_WORD_BITS);
-
-             for (; word; bitno++)
-               {
-                 if (word & 1)
-                   {
-                     list[count++] = bitno;
-                     if (count >= num)
-                       {
-                         *next = bitno + 1;
-                         return count;
-                       }
-                   }
-                 word >>= 1;
-               }
-             bitno = (windex + 1) * BITSET_WORD_BITS;
-           }
-       }
+        {
+          bitset_windex woffset;
+          bitset_word *srcp = EBITSET_WORDS (elt);
+
+          windex = bitno / BITSET_WORD_BITS;
+          woffset = eindex * EBITSET_ELT_WORDS;
+
+          for (; (windex - woffset) < EBITSET_ELT_WORDS; windex++)
+            {
+              word = srcp[windex - woffset] >> (bitno % BITSET_WORD_BITS);
+
+              for (; word; bitno++)
+                {
+                  if (word & 1)
+                    {
+                      list[count++] = bitno;
+                      if (count >= num)
+                        {
+                          *next = bitno + 1;
+                          return count;
+                        }
+                    }
+                  word >>= 1;
+                }
+              bitno = (windex + 1) * BITSET_WORD_BITS;
+            }
+        }
 
       /* Skip to next element.  */
       eindex++;
@@ -722,108 +722,108 @@ ebitset_list (bitset bset, bitset_bindex *list,
 
       elt = elts[eindex];
       if (!elt)
-       continue;
+        continue;
 
       srcp = EBITSET_WORDS (elt);
       windex = eindex * EBITSET_ELT_WORDS;
 
       if ((count + EBITSET_ELT_BITS) < num)
-       {
-         /* The coast is clear, plant boot!  */
+        {
+          /* The coast is clear, plant boot!  */
 
 #if EBITSET_ELT_WORDS == 2
-         word = srcp[0];
-         if (word)
-           {
-             if (!(word & 0xffff))
-               {
-                 word >>= 16;
-                 bitno += 16;
-               }
-             if (!(word & 0xff))
-               {
-                 word >>= 8;
-                 bitno += 8;
-               }
-             for (; word; bitno++)
-               {
-                 if (word & 1)
-                   list[count++] = bitno;
-                 word >>= 1;
-               }
-           }
-         windex++;
-         bitno = windex * BITSET_WORD_BITS;
-
-         word = srcp[1];
-         if (word)
-           {
-             if (!(word & 0xffff))
-               {
-                 word >>= 16;
-                 bitno += 16;
-               }
-             for (; word; bitno++)
-               {
-                 if (word & 1)
-                   list[count++] = bitno;
-                 word >>= 1;
-               }
-           }
-         windex++;
-         bitno = windex * BITSET_WORD_BITS;
+          word = srcp[0];
+          if (word)
+            {
+              if (!(word & 0xffff))
+                {
+                  word >>= 16;
+                  bitno += 16;
+                }
+              if (!(word & 0xff))
+                {
+                  word >>= 8;
+                  bitno += 8;
+                }
+              for (; word; bitno++)
+                {
+                  if (word & 1)
+                    list[count++] = bitno;
+                  word >>= 1;
+                }
+            }
+          windex++;
+          bitno = windex * BITSET_WORD_BITS;
+
+          word = srcp[1];
+          if (word)
+            {
+              if (!(word & 0xffff))
+                {
+                  word >>= 16;
+                  bitno += 16;
+                }
+              for (; word; bitno++)
+                {
+                  if (word & 1)
+                    list[count++] = bitno;
+                  word >>= 1;
+                }
+            }
+          windex++;
+          bitno = windex * BITSET_WORD_BITS;
 #else
-         for (i = 0; i < EBITSET_ELT_WORDS; i++, windex++)
-           {
-             bitno = windex * BITSET_WORD_BITS;
-
-             word = srcp[i];
-             if (word)
-               {
-                 if (!(word & 0xffff))
-                   {
-                     word >>= 16;
-                     bitno += 16;
-                   }
-                 if (!(word & 0xff))
-                   {
-                     word >>= 8;
-                     bitno += 8;
-                   }
-                 for (; word; bitno++)
-                   {
-                     if (word & 1)
-                       list[count++] = bitno;
-                     word >>= 1;
-                   }
-               }
-           }
+          for (i = 0; i < EBITSET_ELT_WORDS; i++, windex++)
+            {
+              bitno = windex * BITSET_WORD_BITS;
+
+              word = srcp[i];
+              if (word)
+                {
+                  if (!(word & 0xffff))
+                    {
+                      word >>= 16;
+                      bitno += 16;
+                    }
+                  if (!(word & 0xff))
+                    {
+                      word >>= 8;
+                      bitno += 8;
+                    }
+                  for (; word; bitno++)
+                    {
+                      if (word & 1)
+                        list[count++] = bitno;
+                      word >>= 1;
+                    }
+                }
+            }
 #endif
-       }
+        }
       else
-       {
-         /* Tread more carefully since we need to check
-            if array overflows.  */
-
-         for (i = 0; i < EBITSET_ELT_WORDS; i++, windex++)
-           {
-             bitno = windex * BITSET_WORD_BITS;
-
-             for (word = srcp[i]; word; bitno++)
-               {
-                 if (word & 1)
-                   {
-                     list[count++] = bitno;
-                     if (count >= num)
-                       {
-                         *next = bitno + 1;
-                         return count;
-                       }
-                   }
-                 word >>= 1;
-               }
-           }
-       }
+        {
+          /* Tread more carefully since we need to check
+             if array overflows.  */
+
+          for (i = 0; i < EBITSET_ELT_WORDS; i++, windex++)
+            {
+              bitno = windex * BITSET_WORD_BITS;
+
+              for (word = srcp[i]; word; bitno++)
+                {
+                  if (word & 1)
+                    {
+                      list[count++] = bitno;
+                      if (count >= num)
+                        {
+                          *next = bitno + 1;
+                          return count;
+                        }
+                    }
+                  word >>= 1;
+                }
+            }
+        }
     }
 
   *next = bitno;
@@ -853,19 +853,19 @@ ebitset_unused_clear (bitset dst)
 
       elt = elts[eindex];
       if (elt)
-       {
-         bitset_windex windex;
-         bitset_windex woffset;
-         bitset_word *srcp = EBITSET_WORDS (elt);
-
-         windex = n_bits / BITSET_WORD_BITS;
-         woffset = eindex * EBITSET_ELT_WORDS;
-
-         srcp[windex - woffset] &= ((bitset_word) 1 << last_bit) - 1;
-         windex++;
-         for (; (windex - woffset) < EBITSET_ELT_WORDS; windex++)
-           srcp[windex - woffset] = 0;
-       }
+        {
+          bitset_windex windex;
+          bitset_windex woffset;
+          bitset_word *srcp = EBITSET_WORDS (elt);
+
+          windex = n_bits / BITSET_WORD_BITS;
+          woffset = eindex * EBITSET_ELT_WORDS;
+
+          srcp[windex - woffset] &= ((bitset_word) 1 << last_bit) - 1;
+          windex++;
+          for (; (windex - woffset) < EBITSET_ELT_WORDS; windex++)
+            srcp[windex - woffset] = 0;
+        }
     }
 }
 
@@ -879,9 +879,9 @@ ebitset_ones (bitset dst)
   for (j = 0; j < EBITSET_SIZE (dst); j++)
     {
       /* Create new elements if they cannot be found.  Perhaps
-        we should just add pointers to a ones element?  */
+         we should just add pointers to a ones element?  */
       elt =
-       ebitset_elt_find (dst, j * EBITSET_ELT_BITS, EBITSET_CREATE);
+        ebitset_elt_find (dst, j * EBITSET_ELT_BITS, EBITSET_CREATE);
       memset (EBITSET_WORDS (elt), -1, sizeof (EBITSET_WORDS (elt)));
     }
   EBITSET_NONZERO_SET (dst);
@@ -904,12 +904,12 @@ ebitset_empty_p (bitset dst)
       ebitset_elt *elt = elts[j];
 
       if (elt)
-       {
-         if (!ebitset_elt_zero_p (elt))
-           return 0;
-         /* Do some weeding as we go.  */
-         ebitset_elt_remove (dst, j);
-       }
+        {
+          if (!ebitset_elt_zero_p (elt))
+            return 0;
+          /* Do some weeding as we go.  */
+          ebitset_elt_remove (dst, j);
+        }
     }
 
   /* All the bits are zero.  We could shrink the elts.
@@ -932,14 +932,14 @@ ebitset_not (bitset dst, bitset src)
   for (j = 0; j < EBITSET_SIZE (src); j++)
     {
       /* Create new elements for dst if they cannot be found
-        or substitute zero elements if src elements not found.  */
+         or substitute zero elements if src elements not found.  */
       selt =
-       ebitset_elt_find (dst, j * EBITSET_ELT_BITS, EBITSET_SUBST);
+        ebitset_elt_find (dst, j * EBITSET_ELT_BITS, EBITSET_SUBST);
       delt =
-       ebitset_elt_find (dst, j * EBITSET_ELT_BITS, EBITSET_CREATE);
+        ebitset_elt_find (dst, j * EBITSET_ELT_BITS, EBITSET_CREATE);
 
       for (i = 0; i < EBITSET_ELT_WORDS; i++)
-       EBITSET_WORDS (delt)[i] = ~EBITSET_WORDS (selt)[i];
+        EBITSET_WORDS (delt)[i] = ~EBITSET_WORDS (selt)[i];
     }
   EBITSET_NONZERO_SET (dst);
   ebitset_unused_clear (dst);
@@ -972,17 +972,17 @@ ebitset_subset_p (bitset dst, bitset src)
       delt = j < dsize ? delts[j] : 0;
 
       if (!selt && !delt)
-       continue;
+        continue;
 
       if (!selt)
-       selt = &ebitset_zero_elts[0];
+        selt = &ebitset_zero_elts[0];
       if (!delt)
-       delt = &ebitset_zero_elts[0];
+        delt = &ebitset_zero_elts[0];
 
       for (i = 0; i < EBITSET_ELT_WORDS; i++)
-       if (EBITSET_WORDS (delt)[i]
-           != (EBITSET_WORDS (selt)[i] | EBITSET_WORDS (delt)[i]))
-         return false;
+        if (EBITSET_WORDS (delt)[i]
+            != (EBITSET_WORDS (selt)[i] | EBITSET_WORDS (delt)[i]))
+          return false;
     }
   return true;
 }
@@ -1014,11 +1014,11 @@ ebitset_disjoint_p (bitset dst, bitset src)
       delt = j < dsize ? delts[j] : 0;
 
       if (!selt || !delt)
-       continue;
+        continue;
 
       for (i = 0; i < EBITSET_ELT_WORDS; i++)
-       if ((EBITSET_WORDS (selt)[i] & EBITSET_WORDS (delt)[i]))
-         return false;
+        if ((EBITSET_WORDS (selt)[i] & EBITSET_WORDS (delt)[i]))
+          return false;
     }
   return true;
 }
@@ -1066,93 +1066,93 @@ ebitset_op3_cmp (bitset dst, bitset src1, bitset src2, enum bitset_ops op)
       delt = j < dsize ? delts[j] : 0;
 
       if (!selt1 && !selt2)
-       {
-         if (delt)
-           {
-             changed = true;
-             ebitset_elt_remove (dst, j);
-           }
-         continue;
-       }
+        {
+          if (delt)
+            {
+              changed = true;
+              ebitset_elt_remove (dst, j);
+            }
+          continue;
+        }
 
       if (!selt1)
-       selt1 = &ebitset_zero_elts[0];
+        selt1 = &ebitset_zero_elts[0];
       if (!selt2)
-       selt2 = &ebitset_zero_elts[0];
+        selt2 = &ebitset_zero_elts[0];
       if (!delt)
-       delt = ebitset_elt_calloc ();
+        delt = ebitset_elt_calloc ();
       else
-       delts[j] = 0;
+        delts[j] = 0;
 
       srcp1 = EBITSET_WORDS (selt1);
       srcp2 = EBITSET_WORDS (selt2);
       dstp = EBITSET_WORDS (delt);
       switch (op)
-       {
-       default:
-         abort ();
-
-       case BITSET_OP_OR:
-         for (i = 0; i < EBITSET_ELT_WORDS; i++, dstp++)
-           {
-             bitset_word tmp = *srcp1++ | *srcp2++;
-
-             if (*dstp != tmp)
-               {
-                 changed = true;
-                 *dstp = tmp;
-               }
-           }
-         break;
-
-       case BITSET_OP_AND:
-         for (i = 0; i < EBITSET_ELT_WORDS; i++, dstp++)
-           {
-             bitset_word tmp = *srcp1++ & *srcp2++;
-
-             if (*dstp != tmp)
-               {
-                 changed = true;
-                 *dstp = tmp;
-               }
-           }
-         break;
-
-       case BITSET_OP_XOR:
-         for (i = 0; i < EBITSET_ELT_WORDS; i++, dstp++)
-           {
-             bitset_word tmp = *srcp1++ ^ *srcp2++;
-
-             if (*dstp != tmp)
-               {
-                 changed = true;
-                 *dstp = tmp;
-               }
-           }
-         break;
-
-       case BITSET_OP_ANDN:
-         for (i = 0; i < EBITSET_ELT_WORDS; i++, dstp++)
-           {
-             bitset_word tmp = *srcp1++ & ~(*srcp2++);
-
-             if (*dstp != tmp)
-               {
-                 changed = true;
-                 *dstp = tmp;
-               }
-           }
-         break;
-       }
+        {
+        default:
+          abort ();
+
+        case BITSET_OP_OR:
+          for (i = 0; i < EBITSET_ELT_WORDS; i++, dstp++)
+            {
+              bitset_word tmp = *srcp1++ | *srcp2++;
+
+              if (*dstp != tmp)
+                {
+                  changed = true;
+                  *dstp = tmp;
+                }
+            }
+          break;
+
+        case BITSET_OP_AND:
+          for (i = 0; i < EBITSET_ELT_WORDS; i++, dstp++)
+            {
+              bitset_word tmp = *srcp1++ & *srcp2++;
+
+              if (*dstp != tmp)
+                {
+                  changed = true;
+                  *dstp = tmp;
+                }
+            }
+          break;
+
+        case BITSET_OP_XOR:
+          for (i = 0; i < EBITSET_ELT_WORDS; i++, dstp++)
+            {
+              bitset_word tmp = *srcp1++ ^ *srcp2++;
+
+              if (*dstp != tmp)
+                {
+                  changed = true;
+                  *dstp = tmp;
+                }
+            }
+          break;
+
+        case BITSET_OP_ANDN:
+          for (i = 0; i < EBITSET_ELT_WORDS; i++, dstp++)
+            {
+              bitset_word tmp = *srcp1++ & ~(*srcp2++);
+
+              if (*dstp != tmp)
+                {
+                  changed = true;
+                  *dstp = tmp;
+                }
+            }
+          break;
+        }
 
       if (!ebitset_elt_zero_p (delt))
-       {
-         ebitset_elt_add (dst, delt, j);
-       }
+        {
+          ebitset_elt_add (dst, delt, j);
+        }
       else
-       {
-         ebitset_elt_free (delt);
-       }
+        {
+          ebitset_elt_free (delt);
+        }
     }
 
   /* If we have elements of DST left over, free them all.  */
@@ -1165,7 +1165,7 @@ ebitset_op3_cmp (bitset dst, bitset src1, bitset src2, enum bitset_ops op)
       delt = delts[j];
 
       if (delt)
-       ebitset_elt_remove (dst, j);
+        ebitset_elt_remove (dst, j);
     }
 
   EBITSET_NONZERO_SET (dst);
index 5af5fcc823450c190f71ecada0980c0172c45d21..7a638c6f9b17fcb6e8cd0268cb4658ec2fd3581e 100644 (file)
@@ -60,10 +60,10 @@ typedef bitset_word lbitset_word;
    These are linked together in a doubly-linked list.  */
 typedef struct lbitset_elt_struct
 {
-  struct lbitset_elt_struct *next;     /* Next element.  */
-  struct lbitset_elt_struct *prev;     /* Previous element.  */
-  bitset_windex index; /* bitno / BITSET_WORD_BITS.  */
-  bitset_word words[LBITSET_ELT_WORDS];        /* Bits that are set.  */
+  struct lbitset_elt_struct *next;      /* Next element.  */
+  struct lbitset_elt_struct *prev;      /* Previous element.  */
+  bitset_windex index;  /* bitno / BITSET_WORD_BITS.  */
+  bitset_word words[LBITSET_ELT_WORDS]; /* Bits that are set.  */
 }
 lbitset_elt;
 
@@ -76,7 +76,7 @@ static lbitset_elt lbitset_zero_elts[3]; /* Elements of all zero bits.  */
 /* Obstack to allocate bitset elements from.  */
 static struct obstack lbitset_obstack;
 static bool lbitset_obstack_init = false;
-static lbitset_elt *lbitset_free_list; /* Free list of bitset elements.  */
+static lbitset_elt *lbitset_free_list;  /* Free list of bitset elements.  */
 
 extern void debug_lbitset (bitset);
 
@@ -102,16 +102,16 @@ lbitset_elt_alloc (void)
   else
     {
       if (!lbitset_obstack_init)
-       {
-         lbitset_obstack_init = true;
+        {
+          lbitset_obstack_init = true;
 
-         /* Let particular systems override the size of a chunk.  */
+          /* Let particular systems override the size of a chunk.  */
 
 #ifndef OBSTACK_CHUNK_SIZE
 #define OBSTACK_CHUNK_SIZE 0
 #endif
 
-         /* Let them override the alloc and free routines too.  */
+          /* Let them override the alloc and free routines too.  */
 
 #ifndef OBSTACK_CHUNK_ALLOC
 #define OBSTACK_CHUNK_ALLOC xmalloc
@@ -125,16 +125,16 @@ lbitset_elt_alloc (void)
 #define __alignof__(type) 0
 #endif
 
-         obstack_specify_allocation (&lbitset_obstack, OBSTACK_CHUNK_SIZE,
-                                     __alignof__ (lbitset_elt),
-                                     OBSTACK_CHUNK_ALLOC,
-                                     OBSTACK_CHUNK_FREE);
-       }
+          obstack_specify_allocation (&lbitset_obstack, OBSTACK_CHUNK_SIZE,
+                                      __alignof__ (lbitset_elt),
+                                      OBSTACK_CHUNK_ALLOC,
+                                      OBSTACK_CHUNK_FREE);
+        }
 
       /* Perhaps we should add a number of new elements to the free
-        list.  */
+         list.  */
       elt = (lbitset_elt *) obstack_alloc (&lbitset_obstack,
-                                          sizeof (lbitset_elt));
+                                           sizeof (lbitset_elt));
     }
 
   return elt;
@@ -185,20 +185,20 @@ lbitset_elt_unlink (bitset bset, lbitset_elt *elt)
   if (LBITSET_CURRENT (bset) == elt)
     {
       if (next)
-       {
-         bset->b.cdata = next->words;
-         bset->b.cindex = next->index;
-       }
+        {
+          bset->b.cdata = next->words;
+          bset->b.cindex = next->index;
+        }
       else if (prev)
-       {
-         bset->b.cdata = prev->words;
-         bset->b.cindex = prev->index;
-       }
+        {
+          bset->b.cdata = prev->words;
+          bset->b.cindex = prev->index;
+        }
       else
-       {
-         bset->b.csize = 0;
-         bset->b.cdata = 0;
-       }
+        {
+          bset->b.csize = 0;
+          bset->b.cdata = 0;
+        }
     }
 
   lbitset_elt_free (elt);
@@ -278,13 +278,13 @@ lbitset_elt_link (bitset bset, lbitset_elt *elt)
   else if (windex < bset->b.cindex)
     {
       for (ptr = current;
-          ptr->prev && ptr->prev->index > windex; ptr = ptr->prev)
-       continue;
+           ptr->prev && ptr->prev->index > windex; ptr = ptr->prev)
+        continue;
 
       if (ptr->prev)
-       ptr->prev->next = elt;
+        ptr->prev->next = elt;
       else
-       LBITSET_HEAD (bset) = elt;
+        LBITSET_HEAD (bset) = elt;
 
       elt->prev = ptr->prev;
       elt->next = ptr;
@@ -295,13 +295,13 @@ lbitset_elt_link (bitset bset, lbitset_elt *elt)
   else
     {
       for (ptr = current;
-          ptr->next && ptr->next->index < windex; ptr = ptr->next)
-       continue;
+           ptr->next && ptr->next->index < windex; ptr = ptr->next)
+        continue;
 
       if (ptr->next)
-       ptr->next->prev = elt;
+        ptr->next->prev = elt;
       else
-       LBITSET_TAIL (bset) = elt;
+        LBITSET_TAIL (bset) = elt;
 
       elt->next = ptr->next;
       elt->prev = ptr;
@@ -317,7 +317,7 @@ lbitset_elt_link (bitset bset, lbitset_elt *elt)
 
 static lbitset_elt *
 lbitset_elt_find (bitset bset, bitset_windex windex,
-                 enum lbitset_find_mode mode)
+                  enum lbitset_find_mode mode)
 {
   lbitset_elt *elt;
   lbitset_elt *current;
@@ -327,7 +327,7 @@ lbitset_elt_find (bitset bset, bitset_windex windex,
       current = LBITSET_CURRENT (bset);
       /* Check if element is the cached element.  */
       if ((windex - bset->b.cindex) < bset->b.csize)
-       return current;
+        return current;
     }
   else
     {
@@ -337,28 +337,28 @@ lbitset_elt_find (bitset bset, bitset_windex windex,
   if (current)
     {
       if (windex < bset->b.cindex)
-       {
-         for (elt = current;
-              elt->prev && elt->index > windex; elt = elt->prev)
-           continue;
-       }
+        {
+          for (elt = current;
+               elt->prev && elt->index > windex; elt = elt->prev)
+            continue;
+        }
       else
-       {
-         for (elt = current;
-              elt->next && (elt->index + LBITSET_ELT_WORDS - 1) < windex;
-              elt = elt->next)
-           continue;
-       }
+        {
+          for (elt = current;
+               elt->next && (elt->index + LBITSET_ELT_WORDS - 1) < windex;
+               elt = elt->next)
+            continue;
+        }
 
       /* ELT is the nearest to the one we want.  If it's not the one
-        we want, the one we want does not exist.  */
+         we want, the one we want does not exist.  */
       if (windex - elt->index < LBITSET_ELT_WORDS)
-       {
-         bset->b.cindex = elt->index;
-         bset->b.csize = LBITSET_ELT_WORDS;
-         bset->b.cdata = elt->words;
-         return elt;
-       }
+        {
+          bset->b.cindex = elt->index;
+          bset->b.csize = LBITSET_ELT_WORDS;
+          bset->b.cdata = elt->words;
+          return elt;
+        }
     }
 
   switch (mode)
@@ -394,7 +394,7 @@ lbitset_weed (bitset bset)
     {
       next = elt->next;
       if (lbitset_elt_zero_p (elt))
-       lbitset_elt_unlink (bset, elt);
+        lbitset_elt_unlink (bset, elt);
     }
 }
 
@@ -431,11 +431,11 @@ lbitset_equal_p (bitset dst, bitset src)
        selt && delt; selt = selt->next, delt = delt->next)
     {
       if (selt->index != delt->index)
-       return false;
+        return false;
 
       for (j = 0; j < LBITSET_ELT_WORDS; j++)
-       if (delt->words[j] != selt->words[j])
-         return false;
+        if (delt->words[j] != selt->words[j])
+          return false;
     }
   return !selt && !delt;
 }
@@ -467,9 +467,9 @@ lbitset_copy (bitset dst, bitset src)
       tmp->prev = prev;
       tmp->next = 0;
       if (prev)
-       prev->next = tmp;
+        prev->next = tmp;
       else
-       LBITSET_HEAD (dst) = tmp;
+        LBITSET_HEAD (dst) = tmp;
       prev = tmp;
 
       memcpy (tmp->words, elt->words, sizeof (elt->words));
@@ -549,9 +549,9 @@ lbitset_test (bitset src, bitset_bindex bitno)
   bitset_windex windex = bitno / BITSET_WORD_BITS;
 
   return (lbitset_elt_find (src, windex, LBITSET_FIND)
-         && ((src->b.cdata[windex - src->b.cindex]
-              >> (bitno % BITSET_WORD_BITS))
-             & 1));
+          && ((src->b.cdata[windex - src->b.cindex]
+               >> (bitno % BITSET_WORD_BITS))
+              & 1));
 }
 
 
@@ -567,7 +567,7 @@ lbitset_free (bitset bset)
  found and with *NEXT indicating where search stopped.  */
 static bitset_bindex
 lbitset_list_reverse (bitset bset, bitset_bindex *list,
-                     bitset_bindex num, bitset_bindex *next)
+                      bitset_bindex num, bitset_bindex *next)
 {
   bitset_bindex rbitno;
   bitset_bindex bitno;
@@ -603,7 +603,7 @@ lbitset_list_reverse (bitset bset, bitset_bindex *list,
   if (windex >= elt->index + LBITSET_ELT_WORDS)
     {
       /* We are trying to start in no-mans land so start
-        at end of current elt.  */
+         at end of current elt.  */
       bcount = BITSET_WORD_BITS - 1;
       windex = elt->index + LBITSET_ELT_WORDS - 1;
     }
@@ -623,33 +623,33 @@ lbitset_list_reverse (bitset bset, bitset_bindex *list,
       bitset_word *srcp = elt->words;
 
       for (; (windex - elt->index) < LBITSET_ELT_WORDS;
-          windex--, boffset -= BITSET_WORD_BITS,
-            bcount = BITSET_WORD_BITS - 1)
-       {
-         word =
-           srcp[windex - elt->index] << (BITSET_WORD_BITS - 1 - bcount);
-
-         for (; word; bcount--)
-           {
-             if (word & BITSET_MSB)
-               {
-                 list[count++] = boffset + bcount;
-                 if (count >= num)
-                   {
-                     *next = n_bits - (boffset + bcount);
-                     return count;
-                   }
-               }
-             word <<= 1;
-           }
-       }
+           windex--, boffset -= BITSET_WORD_BITS,
+             bcount = BITSET_WORD_BITS - 1)
+        {
+          word =
+            srcp[windex - elt->index] << (BITSET_WORD_BITS - 1 - bcount);
+
+          for (; word; bcount--)
+            {
+              if (word & BITSET_MSB)
+                {
+                  list[count++] = boffset + bcount;
+                  if (count >= num)
+                    {
+                      *next = n_bits - (boffset + bcount);
+                      return count;
+                    }
+                }
+              word <<= 1;
+            }
+        }
 
       elt = elt->prev;
       if (elt)
-       {
-         windex = elt->index + LBITSET_ELT_WORDS - 1;
-         boffset = windex * BITSET_WORD_BITS;
-       }
+        {
+          windex = elt->index + LBITSET_ELT_WORDS - 1;
+          boffset = windex * BITSET_WORD_BITS;
+        }
     }
 
   *next = n_bits - (boffset + 1);
@@ -662,7 +662,7 @@ lbitset_list_reverse (bitset bset, bitset_bindex *list,
  found and with *NEXT indicating where search stopped.  */
 static bitset_bindex
 lbitset_list (bitset bset, bitset_bindex *list,
-             bitset_bindex num, bitset_bindex *next)
+              bitset_bindex num, bitset_bindex *next)
 {
   bitset_bindex bitno;
   bitset_windex windex;
@@ -693,51 +693,51 @@ lbitset_list (bitset bset, bitset_bindex *list,
 
       /* Skip to starting element.  */
       for (elt = head;
-          elt && (elt->index + LBITSET_ELT_WORDS - 1) < windex;
-          elt = elt->next)
-       continue;
+           elt && (elt->index + LBITSET_ELT_WORDS - 1) < windex;
+           elt = elt->next)
+        continue;
 
       if (!elt)
-       return 0;
+        return 0;
 
       if (windex < elt->index)
-       {
-         windex = elt->index;
-         bitno = windex * BITSET_WORD_BITS;
-       }
+        {
+          windex = elt->index;
+          bitno = windex * BITSET_WORD_BITS;
+        }
       else
-       {
-         bitset_word *srcp = elt->words;
-
-         /* We are starting within an element.  */
-
-         for (; (windex - elt->index) < LBITSET_ELT_WORDS; windex++)
-           {
-             word = srcp[windex - elt->index] >> (bitno % BITSET_WORD_BITS);
-
-             for (; word; bitno++)
-               {
-                 if (word & 1)
-                   {
-                     list[count++] = bitno;
-                     if (count >= num)
-                       {
-                         *next = bitno + 1;
-                         return count;
-                       }
-                   }
-                 word >>= 1;
-               }
-             bitno = (windex + 1) * BITSET_WORD_BITS;
-           }
-
-         elt = elt->next;
-         if (elt)
-           {
-             windex = elt->index;
-             bitno = windex * BITSET_WORD_BITS;
-           }
-       }
+        {
+          bitset_word *srcp = elt->words;
+
+          /* We are starting within an element.  */
+
+          for (; (windex - elt->index) < LBITSET_ELT_WORDS; windex++)
+            {
+              word = srcp[windex - elt->index] >> (bitno % BITSET_WORD_BITS);
+
+              for (; word; bitno++)
+                {
+                  if (word & 1)
+                    {
+                      list[count++] = bitno;
+                      if (count >= num)
+                        {
+                          *next = bitno + 1;
+                          return count;
+                        }
+                    }
+                  word >>= 1;
+                }
+              bitno = (windex + 1) * BITSET_WORD_BITS;
+            }
+
+          elt = elt->next;
+          if (elt)
+            {
+              windex = elt->index;
+              bitno = windex * BITSET_WORD_BITS;
+            }
+        }
     }
 
 
@@ -750,109 +750,109 @@ lbitset_list (bitset bset, bitset_bindex *list,
       bitset_word *srcp = elt->words;
 
       if ((count + LBITSET_ELT_BITS) < num)
-       {
-         /* The coast is clear, plant boot!  */
+        {
+          /* The coast is clear, plant boot!  */
 
 #if LBITSET_ELT_WORDS == 2
-         word = srcp[0];
-         if (word)
-           {
-             if (!(word & 0xffff))
-               {
-                 word >>= 16;
-                 bitno += 16;
-               }
-             if (!(word & 0xff))
-               {
-                 word >>= 8;
-                 bitno += 8;
-               }
-             for (; word; bitno++)
-               {
-                 if (word & 1)
-                   list[count++] = bitno;
-                 word >>= 1;
-               }
-           }
-         windex++;
-         bitno = windex * BITSET_WORD_BITS;
-
-         word = srcp[1];
-         if (word)
-           {
-             if (!(word & 0xffff))
-               {
-                 word >>= 16;
-                 bitno += 16;
-               }
-             for (; word; bitno++)
-               {
-                 if (word & 1)
-                   list[count++] = bitno;
-                 word >>= 1;
-               }
-           }
-         windex++;
-         bitno = windex * BITSET_WORD_BITS;
+          word = srcp[0];
+          if (word)
+            {
+              if (!(word & 0xffff))
+                {
+                  word >>= 16;
+                  bitno += 16;
+                }
+              if (!(word & 0xff))
+                {
+                  word >>= 8;
+                  bitno += 8;
+                }
+              for (; word; bitno++)
+                {
+                  if (word & 1)
+                    list[count++] = bitno;
+                  word >>= 1;
+                }
+            }
+          windex++;
+          bitno = windex * BITSET_WORD_BITS;
+
+          word = srcp[1];
+          if (word)
+            {
+              if (!(word & 0xffff))
+                {
+                  word >>= 16;
+                  bitno += 16;
+                }
+              for (; word; bitno++)
+                {
+                  if (word & 1)
+                    list[count++] = bitno;
+                  word >>= 1;
+                }
+            }
+          windex++;
+          bitno = windex * BITSET_WORD_BITS;
 #else
-         for (i = 0; i < LBITSET_ELT_WORDS; i++)
-           {
-             word = srcp[i];
-             if (word)
-               {
-                 if (!(word & 0xffff))
-                   {
-                     word >>= 16;
-                     bitno += 16;
-                   }
-                 if (!(word & 0xff))
-                   {
-                     word >>= 8;
-                     bitno += 8;
-                   }
-                 for (; word; bitno++)
-                   {
-                     if (word & 1)
-                       list[count++] = bitno;
-                     word >>= 1;
-                   }
-               }
-             windex++;
-             bitno = windex * BITSET_WORD_BITS;
-           }
+          for (i = 0; i < LBITSET_ELT_WORDS; i++)
+            {
+              word = srcp[i];
+              if (word)
+                {
+                  if (!(word & 0xffff))
+                    {
+                      word >>= 16;
+                      bitno += 16;
+                    }
+                  if (!(word & 0xff))
+                    {
+                      word >>= 8;
+                      bitno += 8;
+                    }
+                  for (; word; bitno++)
+                    {
+                      if (word & 1)
+                        list[count++] = bitno;
+                      word >>= 1;
+                    }
+                }
+              windex++;
+              bitno = windex * BITSET_WORD_BITS;
+            }
 #endif
-       }
+        }
       else
-       {
-         /* Tread more carefully since we need to check
-            if array overflows.  */
-
-         for (i = 0; i < LBITSET_ELT_WORDS; i++)
-           {
-             for (word = srcp[i]; word; bitno++)
-               {
-                 if (word & 1)
-                   {
-                     list[count++] = bitno;
-                     if (count >= num)
-                       {
-                         *next = bitno + 1;
-                         return count;
-                       }
-                   }
-                 word >>= 1;
-               }
-             windex++;
-             bitno = windex * BITSET_WORD_BITS;
-           }
-       }
+        {
+          /* Tread more carefully since we need to check
+             if array overflows.  */
+
+          for (i = 0; i < LBITSET_ELT_WORDS; i++)
+            {
+              for (word = srcp[i]; word; bitno++)
+                {
+                  if (word & 1)
+                    {
+                      list[count++] = bitno;
+                      if (count >= num)
+                        {
+                          *next = bitno + 1;
+                          return count;
+                        }
+                    }
+                  word >>= 1;
+                }
+              windex++;
+              bitno = windex * BITSET_WORD_BITS;
+            }
+        }
 
       elt = elt->next;
       if (elt)
-       {
-         windex = elt->index;
-         bitno = windex * BITSET_WORD_BITS;
-       }
+        {
+          windex = elt->index;
+          bitno = windex * BITSET_WORD_BITS;
+        }
     }
 
   *next = bitno;
@@ -870,7 +870,7 @@ lbitset_empty_p (bitset dst)
     {
       next = elt->next;
       if (!lbitset_elt_zero_p (elt))
-       return 0;
+        return 0;
       /* Weed as we go.  */
       lbitset_elt_unlink (dst, elt);
     }
@@ -903,7 +903,7 @@ lbitset_unused_clear (bitset dst)
       windex++;
 
       for (; (windex - elt->index) < LBITSET_ELT_WORDS; windex++)
-       srcp[windex - elt->index] = 0;
+        srcp[windex - elt->index] = 0;
     }
 }
 
@@ -947,12 +947,12 @@ lbitset_not (bitset dst, bitset src)
   for (i = 0; i < windex; i += LBITSET_ELT_WORDS)
     {
       /* Create new elements for dst if they cannot be found
-        or substitute zero elements if src elements not found.  */
+         or substitute zero elements if src elements not found.  */
       selt = lbitset_elt_find (src, i, LBITSET_SUBST);
       delt = lbitset_elt_find (dst, i, LBITSET_CREATE);
 
       for (j = 0; j < LBITSET_ELT_WORDS; j++)
-       delt->words[j] = ~selt->words[j];
+        delt->words[j] = ~selt->words[j];
     }
   lbitset_unused_clear (dst);
   lbitset_weed (dst);
@@ -972,26 +972,26 @@ lbitset_subset_p (bitset dst, bitset src)
        selt || delt; selt = selt->next, delt = delt->next)
     {
       if (!selt)
-       selt = &lbitset_zero_elts[0];
+        selt = &lbitset_zero_elts[0];
       else if (!delt)
-       delt = &lbitset_zero_elts[0];
+        delt = &lbitset_zero_elts[0];
       else if (selt->index != delt->index)
-       {
-         if (selt->index < delt->index)
-           {
-             lbitset_zero_elts[2].next = delt;
-             delt = &lbitset_zero_elts[2];
-           }
-         else
-           {
-             lbitset_zero_elts[1].next = selt;
-             selt = &lbitset_zero_elts[1];
-           }
-       }
+        {
+          if (selt->index < delt->index)
+            {
+              lbitset_zero_elts[2].next = delt;
+              delt = &lbitset_zero_elts[2];
+            }
+          else
+            {
+              lbitset_zero_elts[1].next = selt;
+              selt = &lbitset_zero_elts[1];
+            }
+        }
 
       for (j = 0; j < LBITSET_ELT_WORDS; j++)
-       if (delt->words[j] != (selt->words[j] | delt->words[j]))
-         return false;
+        if (delt->words[j] != (selt->words[j] | delt->words[j]))
+          return false;
     }
   return true;
 }
@@ -1009,25 +1009,25 @@ lbitset_disjoint_p (bitset dst, bitset src)
        selt && delt; selt = selt->next, delt = delt->next)
     {
       if (selt->index != delt->index)
-       {
-         if (selt->index < delt->index)
-           {
-             lbitset_zero_elts[2].next = delt;
-             delt = &lbitset_zero_elts[2];
-           }
-         else
-           {
-             lbitset_zero_elts[1].next = selt;
-             selt = &lbitset_zero_elts[1];
-           }
-         /* Since the elements are different, there is no
-            intersection of these elements.  */
-         continue;
-       }
+        {
+          if (selt->index < delt->index)
+            {
+              lbitset_zero_elts[2].next = delt;
+              delt = &lbitset_zero_elts[2];
+            }
+          else
+            {
+              lbitset_zero_elts[1].next = selt;
+              selt = &lbitset_zero_elts[1];
+            }
+          /* Since the elements are different, there is no
+             intersection of these elements.  */
+          continue;
+        }
 
       for (j = 0; j < LBITSET_ELT_WORDS; j++)
-       if (selt->words[j] & delt->words[j])
-         return false;
+        if (selt->words[j] & delt->words[j])
+          return false;
     }
   return true;
 }
@@ -1060,124 +1060,124 @@ lbitset_op3_cmp (bitset dst, bitset src1, bitset src2, enum bitset_ops op)
   while (selt1 || selt2)
     {
       /* Figure out whether we need to substitute zero elements for
-        missing links.  */
+         missing links.  */
       if (windex1 == windex2)
-       {
-         windex = windex1;
-         stmp1 = selt1;
-         stmp2 = selt2;
-         selt1 = selt1->next;
-         windex1 = (selt1) ? selt1->index : BITSET_WINDEX_MAX;
-         selt2 = selt2->next;
-         windex2 = (selt2) ? selt2->index : BITSET_WINDEX_MAX;
-       }
+        {
+          windex = windex1;
+          stmp1 = selt1;
+          stmp2 = selt2;
+          selt1 = selt1->next;
+          windex1 = (selt1) ? selt1->index : BITSET_WINDEX_MAX;
+          selt2 = selt2->next;
+          windex2 = (selt2) ? selt2->index : BITSET_WINDEX_MAX;
+        }
       else if (windex1 < windex2)
-       {
-         windex = windex1;
-         stmp1 = selt1;
-         stmp2 = &lbitset_zero_elts[0];
-         selt1 = selt1->next;
-         windex1 = (selt1) ? selt1->index : BITSET_WINDEX_MAX;
-       }
+        {
+          windex = windex1;
+          stmp1 = selt1;
+          stmp2 = &lbitset_zero_elts[0];
+          selt1 = selt1->next;
+          windex1 = (selt1) ? selt1->index : BITSET_WINDEX_MAX;
+        }
       else
-       {
-         windex = windex2;
-         stmp1 = &lbitset_zero_elts[0];
-         stmp2 = selt2;
-         selt2 = selt2->next;
-         windex2 = (selt2) ? selt2->index : BITSET_WINDEX_MAX;
-       }
+        {
+          windex = windex2;
+          stmp1 = &lbitset_zero_elts[0];
+          stmp2 = selt2;
+          selt2 = selt2->next;
+          windex2 = (selt2) ? selt2->index : BITSET_WINDEX_MAX;
+        }
 
       /* Find the appropriate element from DST.  Begin by discarding
-        elements that we've skipped.  */
+         elements that we've skipped.  */
       while (delt && delt->index < windex)
-       {
-         changed = true;
-         dtmp = delt;
-         delt = delt->next;
-         lbitset_elt_free (dtmp);
-       }
+        {
+          changed = true;
+          dtmp = delt;
+          delt = delt->next;
+          lbitset_elt_free (dtmp);
+        }
       if (delt && delt->index == windex)
-       {
-         dtmp = delt;
-         delt = delt->next;
-       }
+        {
+          dtmp = delt;
+          delt = delt->next;
+        }
       else
-       dtmp = lbitset_elt_calloc ();
+        dtmp = lbitset_elt_calloc ();
 
       /* Do the operation, and if any bits are set, link it into the
-        linked list.  */
+         linked list.  */
       srcp1 = stmp1->words;
       srcp2 = stmp2->words;
       dstp = dtmp->words;
       switch (op)
-       {
-       default:
-         abort ();
-
-       case BITSET_OP_OR:
-         for (i = 0; i < LBITSET_ELT_WORDS; i++, dstp++)
-           {
-             bitset_word tmp = *srcp1++ | *srcp2++;
-
-             if (*dstp != tmp)
-               {
-                 changed = true;
-                 *dstp = tmp;
-               }
-           }
-         break;
-
-       case BITSET_OP_AND:
-         for (i = 0; i < LBITSET_ELT_WORDS; i++, dstp++)
-           {
-             bitset_word tmp = *srcp1++ & *srcp2++;
-
-             if (*dstp != tmp)
-               {
-                 changed = true;
-                 *dstp = tmp;
-               }
-           }
-         break;
-
-       case BITSET_OP_XOR:
-         for (i = 0; i < LBITSET_ELT_WORDS; i++, dstp++)
-           {
-             bitset_word tmp = *srcp1++ ^ *srcp2++;
-
-             if (*dstp != tmp)
-               {
-                 changed = true;
-                 *dstp = tmp;
-               }
-           }
-         break;
-
-       case BITSET_OP_ANDN:
-         for (i = 0; i < LBITSET_ELT_WORDS; i++, dstp++)
-           {
-             bitset_word tmp = *srcp1++ & ~(*srcp2++);
-
-             if (*dstp != tmp)
-               {
-                 changed = true;
-                 *dstp = tmp;
-               }
-           }
-         break;
-       }
+        {
+        default:
+          abort ();
+
+        case BITSET_OP_OR:
+          for (i = 0; i < LBITSET_ELT_WORDS; i++, dstp++)
+            {
+              bitset_word tmp = *srcp1++ | *srcp2++;
+
+              if (*dstp != tmp)
+                {
+                  changed = true;
+                  *dstp = tmp;
+                }
+            }
+          break;
+
+        case BITSET_OP_AND:
+          for (i = 0; i < LBITSET_ELT_WORDS; i++, dstp++)
+            {
+              bitset_word tmp = *srcp1++ & *srcp2++;
+
+              if (*dstp != tmp)
+                {
+                  changed = true;
+                  *dstp = tmp;
+                }
+            }
+          break;
+
+        case BITSET_OP_XOR:
+          for (i = 0; i < LBITSET_ELT_WORDS; i++, dstp++)
+            {
+              bitset_word tmp = *srcp1++ ^ *srcp2++;
+
+              if (*dstp != tmp)
+                {
+                  changed = true;
+                  *dstp = tmp;
+                }
+            }
+          break;
+
+        case BITSET_OP_ANDN:
+          for (i = 0; i < LBITSET_ELT_WORDS; i++, dstp++)
+            {
+              bitset_word tmp = *srcp1++ & ~(*srcp2++);
+
+              if (*dstp != tmp)
+                {
+                  changed = true;
+                  *dstp = tmp;
+                }
+            }
+          break;
+        }
 
       if (!lbitset_elt_zero_p (dtmp))
-       {
-         dtmp->index = windex;
-         /* Perhaps this could be optimised...  */
-         lbitset_elt_link (dst, dtmp);
-       }
+        {
+          dtmp->index = windex;
+          /* Perhaps this could be optimised...  */
+          lbitset_elt_link (dst, dtmp);
+        }
       else
-       {
-         lbitset_elt_free (dtmp);
-       }
+        {
+          lbitset_elt_free (dtmp);
+        }
     }
 
   /* If we have elements of DST left over, free them all.  */
@@ -1385,17 +1385,17 @@ debug_lbitset (bitset bset)
     {
       fprintf (stderr, "Elt %lu\n", (unsigned long int) elt->index);
       for (i = 0; i < LBITSET_ELT_WORDS; i++)
-       {
-         unsigned int j;
-         bitset_word word;
-
-         word = elt->words[i];
-
-         fprintf (stderr, "  Word %u:", i);
-         for (j = 0; j < LBITSET_WORD_BITS; j++)
-           if ((word & ((bitset_word) 1 << j)))
-             fprintf (stderr, " %u", j);
-         fprintf (stderr, "\n");
-       }
+        {
+          unsigned int j;
+          bitset_word word;
+
+          word = elt->words[i];
+
+          fprintf (stderr, "  Word %u:", i);
+          for (j = 0; j < LBITSET_WORD_BITS; j++)
+            if ((word & ((bitset_word) 1 << j)))
+              fprintf (stderr, " %u", j);
+          fprintf (stderr, "\n");
+        }
     }
 }
index 2ae5cf1671e0fa9d693a9b5fa430492e9d080169..ec1467c59b687e9be54c2ebc8af24707a26ee545 100644 (file)
@@ -17,7 +17,7 @@
 
 
 /* Bison depends on libiberty's implementation of bitsets, which
-   requires a `libiberty.h' file.  This file provides the minimum
+   requires a 'libiberty.h' file.  This file provides the minimum
    services.  */
 
 #ifndef BISON_LIBIBERTY_H_
diff --git a/lib/local.mk b/lib/local.mk
new file mode 100644 (file)
index 0000000..d5d2d0b
--- /dev/null
@@ -0,0 +1,56 @@
+# Copyright (C) 2001-2013 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/>.
+
+include lib/gnulib.mk
+
+# Implementation of bitsets.
+lib_libbison_a_SOURCES +=                       \
+  lib/abitset.c                                 \
+  lib/abitset.h                                 \
+  lib/bbitset.h                                 \
+  lib/bitset.c                                  \
+  lib/bitset.h                                  \
+  lib/bitset_stats.c                            \
+  lib/bitset_stats.h                            \
+  lib/bitsetv.c                                 \
+  lib/bitsetv.h                                 \
+  lib/ebitset.c                                 \
+  lib/ebitset.h                                 \
+  lib/lbitset.c                                 \
+  lib/lbitset.h                                 \
+  lib/libiberty.h                               \
+  lib/vbitset.c                                 \
+  lib/vbitset.h
+
+# Additional bitset operations.
+lib_libbison_a_SOURCES +=                       \
+  lib/bitsetv-print.h                           \
+  lib/bitsetv-print.c
+
+# timevars, stolen from GCC.
+lib_libbison_a_SOURCES +=                       \
+  lib/timevar.h                                 \
+  lib/timevar.c                                 \
+  lib/timevar.def
+
+# Non-gnulib sources in Bison's internal library.
+lib_libbison_a_SOURCES +=                       \
+  lib/get-errno.h                               \
+  lib/get-errno.c
+
+# The Yacc compatibility library.
+lib_LIBRARIES = $(YACC_LIBRARY)
+EXTRA_LIBRARIES = lib/liby.a
+lib_liby_a_SOURCES = lib/main.c lib/yyerror.c
index 36578517f3a9bfb8b04d3f07a53849971ff51552..651ca9db18348c45b9d7095389829f256e2d48f8 100644 (file)
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
-
-#if HAVE_LOCALE_H
-# include <locale.h>
-#endif
-#if ! HAVE_SETLOCALE
-# define setlocale(Category, Locale)
-#endif
+#include <locale.h>
 
 int yyparse (void);
 
index c257c3225284cb3b584101e6a9eb8e6d7de747e0..2889920c14fd7b82ab574ab8ebdd0d6fcb0cc088 100644 (file)
@@ -189,8 +189,8 @@ static struct timevar_time_def start_time;
 
 static void get_time (struct timevar_time_def *);
 static void timevar_accumulate (struct timevar_time_def *,
-                               struct timevar_time_def *,
-                               struct timevar_time_def *);
+                                struct timevar_time_def *,
+                                struct timevar_time_def *);
 
 /* Fill the current times into TIME.  The definition of this function
    also defines any or all of the HAVE_USER_TIME, HAVE_SYS_TIME, and
@@ -479,20 +479,20 @@ timevar_print (fp)
       const float tiny = 5e-3;
 
       /* Don't print the total execution time here; that goes at the
-        end.  */
+         end.  */
       if ((timevar_id_t) id == TV_TOTAL)
-       continue;
+        continue;
 
       /* Don't print timing variables that were never used.  */
       if (!tv->used)
-       continue;
+        continue;
 
       /* Don't print timing variables if we're going to get a row of
-        zeroes.  */
+         zeroes.  */
       if (tv->elapsed.user < tiny
-         && tv->elapsed.sys < tiny
-         && tv->elapsed.wall < tiny)
-       continue;
+          && tv->elapsed.sys < tiny
+          && tv->elapsed.wall < tiny)
+        continue;
 
       /* The timing variable name.  */
       fprintf (fp, " %-22s:", tv->name);
@@ -500,22 +500,22 @@ timevar_print (fp)
 #ifdef HAVE_USER_TIME
       /* Print user-mode time for this process.  */
       fprintf (fp, "%7.2f (%2.0f%%) usr",
-              tv->elapsed.user,
-              (total->user == 0 ? 0 : tv->elapsed.user / total->user) * 100);
+               tv->elapsed.user,
+               (total->user == 0 ? 0 : tv->elapsed.user / total->user) * 100);
 #endif /* HAVE_USER_TIME */
 
 #ifdef HAVE_SYS_TIME
       /* Print system-mode time for this process.  */
       fprintf (fp, "%7.2f (%2.0f%%) sys",
-              tv->elapsed.sys,
-              (total->sys == 0 ? 0 : tv->elapsed.sys / total->sys) * 100);
+               tv->elapsed.sys,
+               (total->sys == 0 ? 0 : tv->elapsed.sys / total->sys) * 100);
 #endif /* HAVE_SYS_TIME */
 
 #ifdef HAVE_WALL_TIME
       /* Print wall clock time elapsed.  */
       fprintf (fp, "%7.2f (%2.0f%%) wall",
-              tv->elapsed.wall,
-              (total->wall == 0 ? 0 : tv->elapsed.wall / total->wall) * 100);
+               tv->elapsed.wall,
+               (total->wall == 0 ? 0 : tv->elapsed.wall / total->wall) * 100);
 #endif /* HAVE_WALL_TIME */
 
       putc ('\n', fp);
@@ -534,7 +534,7 @@ timevar_print (fp)
 #endif
 
 #endif /* defined (HAVE_USER_TIME) || defined (HAVE_SYS_TIME)
-         || defined (HAVE_WALL_TIME) */
+          || defined (HAVE_WALL_TIME) */
 }
 
 /* Returns time (user + system) used so far by the compiler process,
@@ -558,8 +558,8 @@ print_time (str, total)
 {
   long all_time = get_run_time ();
   fprintf (stderr,
-          _("time in %s: %ld.%06ld (%ld%%)\n"),
-          str, total / 1000000, total % 1000000,
-          all_time == 0 ? 0
-          : (long) (((100.0 * (double) total) / (double) all_time) + .5));
+           _("time in %s: %ld.%06ld (%ld%%)\n"),
+           str, total / 1000000, total % 1000000,
+           all_time == 0 ? 0
+           : (long) (((100.0 * (double) total) / (double) all_time) + .5));
 }
index c4180908d8fb73f188bd2f956d7152d4bee14e70..d397bd7ff0772eca837128b045f20a8f093b17d0 100644 (file)
@@ -36,7 +36,7 @@
        Timing variables may be pushed onto the stack; elapsed time is
        attributed to the topmost timing variable on the stack.  When
        another variable is pushed on, the previous topmost variable is
-       `paused' until the pushed variable is popped back off.
+       'paused' until the pushed variable is popped back off.
 
      - As a standalone timer, using timevar_start and timevar_stop.
        All time elapsed between the two calls is attributed to the
index 7d4d920f7e1b41232c739665f38b56011d2aa6a4..e7200cdaa5dc80b212cf44b61873a9940fcdc1da 100644 (file)
@@ -38,9 +38,9 @@ static void vbitset_set (bitset, bitset_bindex);
 static void vbitset_reset (bitset, bitset_bindex);
 static bool vbitset_test (bitset, bitset_bindex);
 static bitset_bindex vbitset_list (bitset, bitset_bindex *,
-                                  bitset_bindex, bitset_bindex *);
+                                   bitset_bindex, bitset_bindex *);
 static bitset_bindex vbitset_list_reverse (bitset, bitset_bindex *,
-                                          bitset_bindex, bitset_bindex *);
+                                           bitset_bindex, bitset_bindex *);
 
 #define VBITSET_N_WORDS(N) (((N) + BITSET_WORD_BITS - 1) / BITSET_WORD_BITS)
 #define VBITSET_WORDS(X) ((X)->b.cdata)
@@ -69,38 +69,38 @@ vbitset_resize (bitset src, bitset_bindex n_bits)
       bitset_windex size;
 
       /* The bitset needs to grow.  If we already have enough memory
-        allocated, then just zero what we need.  */
+         allocated, then just zero what we need.  */
       if (newsize > VBITSET_ASIZE (src))
-       {
-         /* We need to allocate more memory.  When oldsize is
-            non-zero this means that we are changing the size, so
-            grow the bitset 25% larger than requested to reduce
-            number of reallocations.  */
-
-         if (oldsize == 0)
-           size = newsize;
-         else
-           size = newsize + newsize / 4;
-
-         VBITSET_WORDS (src)
-           = realloc (VBITSET_WORDS (src), size * sizeof (bitset_word));
-         VBITSET_ASIZE (src) = size;
-       }
+        {
+          /* We need to allocate more memory.  When oldsize is
+             non-zero this means that we are changing the size, so
+             grow the bitset 25% larger than requested to reduce
+             number of reallocations.  */
+
+          if (oldsize == 0)
+            size = newsize;
+          else
+            size = newsize + newsize / 4;
+
+          VBITSET_WORDS (src)
+            = realloc (VBITSET_WORDS (src), size * sizeof (bitset_word));
+          VBITSET_ASIZE (src) = size;
+        }
 
       memset (VBITSET_WORDS (src) + oldsize, 0,
-             (newsize - oldsize) * sizeof (bitset_word));
+              (newsize - oldsize) * sizeof (bitset_word));
       VBITSET_SIZE (src) = newsize;
     }
   else
     {
       /* The bitset needs to shrink.  There's no point deallocating
-        the memory unless it is shrinking by a reasonable amount.  */
+         the memory unless it is shrinking by a reasonable amount.  */
       if ((oldsize - newsize) >= oldsize / 2)
-       {
-         VBITSET_WORDS (src)
-           = realloc (VBITSET_WORDS (src), newsize * sizeof (bitset_word));
-         VBITSET_ASIZE (src) = newsize;
-       }
+        {
+          VBITSET_WORDS (src)
+            = realloc (VBITSET_WORDS (src), newsize * sizeof (bitset_word));
+          VBITSET_ASIZE (src) = newsize;
+        }
 
       /* Need to prune any excess bits.  FIXME.  */
 
@@ -196,18 +196,18 @@ vbitset_list_reverse (src, list, num, next)
 
       word = srcp[windex] << (BITSET_WORD_BITS - 1 - bitcnt);
       for (; word; bitcnt--)
-       {
-         if (word & BITSET_MSB)
-           {
-             list[count++] = bitoff + bitcnt;
-             if (count >= num)
-               {
-                 *next = n_bits - (bitoff + bitcnt);
-                 return count;
-               }
-           }
-         word <<= 1;
-       }
+        {
+          if (word & BITSET_MSB)
+            {
+              list[count++] = bitoff + bitcnt;
+              if (count >= num)
+                {
+                  *next = n_bits - (bitoff + bitcnt);
+                  return count;
+                }
+            }
+          word <<= 1;
+        }
       bitoff -= BITSET_WORD_BITS;
       bitcnt = BITSET_WORD_BITS - 1;
     }
@@ -243,80 +243,80 @@ vbitset_list (src, list, num, next)
     {
       /* Many bitsets are zero, so make this common case fast.  */
       for (windex = 0; windex < size && !srcp[windex]; windex++)
-       continue;
+        continue;
       if (windex >= size)
-       return 0;
+        return 0;
 
       /* If num is 1, we could speed things up with a binary search
-        of the current word.  */
+         of the current word.  */
 
       bitoff = windex * BITSET_WORD_BITS;
     }
   else
     {
       if (bitno >= BITSET_SIZE_ (src))
-       return 0;
+        return 0;
 
       windex = bitno / BITSET_WORD_BITS;
       bitno = bitno % BITSET_WORD_BITS;
 
       if (bitno)
-       {
-         /* Handle the case where we start within a word.
-            Most often, this is executed with large bitsets
-            with many set bits where we filled the array
-            on the previous call to this function.  */
-
-         bitoff = windex * BITSET_WORD_BITS;
-         word = srcp[windex] >> bitno;
-         for (bitno = bitoff + bitno; word; bitno++)
-           {
-             if (word & 1)
-               {
-                 list[count++] = bitno;
-                 if (count >= num)
-                   {
-                     *next = bitno + 1;
-                     return count;
-                   }
-               }
-             word >>= 1;
-           }
-         windex++;
-       }
+        {
+          /* Handle the case where we start within a word.
+             Most often, this is executed with large bitsets
+             with many set bits where we filled the array
+             on the previous call to this function.  */
+
+          bitoff = windex * BITSET_WORD_BITS;
+          word = srcp[windex] >> bitno;
+          for (bitno = bitoff + bitno; word; bitno++)
+            {
+              if (word & 1)
+                {
+                  list[count++] = bitno;
+                  if (count >= num)
+                    {
+                      *next = bitno + 1;
+                      return count;
+                    }
+                }
+              word >>= 1;
+            }
+          windex++;
+        }
       bitoff = windex * BITSET_WORD_BITS;
     }
 
   for (; windex < size; windex++, bitoff += BITSET_WORD_BITS)
     {
       if (!(word = srcp[windex]))
-       continue;
+        continue;
 
       if ((count + BITSET_WORD_BITS) < num)
-       {
-         for (bitno = bitoff; word; bitno++)
-           {
-             if (word & 1)
-               list[count++] = bitno;
-             word >>= 1;
-           }
-       }
+        {
+          for (bitno = bitoff; word; bitno++)
+            {
+              if (word & 1)
+                list[count++] = bitno;
+              word >>= 1;
+            }
+        }
       else
-       {
-         for (bitno = bitoff; word; bitno++)
-           {
-             if (word & 1)
-               {
-                 list[count++] = bitno;
-                 if (count >= num)
-                   {
-                     *next = bitno + 1;
-                     return count;
-                   }
-               }
-             word >>= 1;
-           }
-       }
+        {
+          for (bitno = bitoff; word; bitno++)
+            {
+              if (word & 1)
+                {
+                  list[count++] = bitno;
+                  if (count >= num)
+                    {
+                      *next = bitno + 1;
+                      return count;
+                    }
+                }
+              word >>= 1;
+            }
+        }
     }
 
   *next = bitoff;
@@ -398,7 +398,7 @@ vbitset_copy1 (bitset dst, bitset src)
   memcpy (dstp, srcp, sizeof (bitset_word) * ssize);
 
   memset (dstp + sizeof (bitset_word) * ssize, 0,
-         sizeof (bitset_word) * (dsize - ssize));
+          sizeof (bitset_word) * (dsize - ssize));
 }
 
 
@@ -423,7 +423,7 @@ vbitset_not (bitset dst, bitset src)
 
   vbitset_unused_clear (dst);
   memset (dstp + sizeof (bitset_word) * ssize, 0,
-         sizeof (bitset_word) * (dsize - ssize));
+          sizeof (bitset_word) * (dsize - ssize));
 }
 
 
@@ -438,19 +438,19 @@ vbitset_equal_p (bitset dst, bitset src)
 
   for (i = 0; i < min (ssize, dsize); i++)
       if (*srcp++ != *dstp++)
-         return 0;
+          return 0;
 
   if (ssize > dsize)
     {
       for (; i < ssize; i++)
-       if (*srcp++)
-         return 0;
+        if (*srcp++)
+          return 0;
     }
   else
     {
       for (; i < dsize; i++)
-       if (*dstp++)
-         return 0;
+        if (*dstp++)
+          return 0;
     }
 
   return 1;
@@ -468,13 +468,13 @@ vbitset_subset_p (bitset dst, bitset src)
 
   for (i = 0; i < min (ssize, dsize); i++, dstp++, srcp++)
       if (*dstp != (*srcp | *dstp))
-         return 0;
+          return 0;
 
   if (ssize > dsize)
     {
       for (; i < ssize; i++)
-       if (*srcp++)
-         return 0;
+        if (*srcp++)
+          return 0;
     }
 
   return 1;
@@ -492,7 +492,7 @@ vbitset_disjoint_p (bitset dst, bitset src)
 
   for (i = 0; i < min (ssize, dsize); i++)
       if (*srcp++ & *dstp++)
-         return 0;
+          return 0;
 
   return 1;
 }
@@ -551,10 +551,10 @@ vbitset_and_cmp (bitset dst, bitset src1, bitset src2)
       bitset_word tmp = *src1p++ & *src2p++;
 
       if (*dstp != tmp)
-       {
-         changed = 1;
-         *dstp = tmp;
-       }
+        {
+          changed = 1;
+          *dstp = tmp;
+        }
     }
 
   if (ssize2 > ssize1)
@@ -566,10 +566,10 @@ vbitset_and_cmp (bitset dst, bitset src1, bitset src2)
   for (; i < ssize1; i++, dstp++)
     {
       if (*dstp != 0)
-       {
-         changed = 1;
-         *dstp = 0;
-       }
+        {
+          changed = 1;
+          *dstp = 0;
+        }
     }
 
   memset (dstp, 0, sizeof (bitset_word) * (dsize - ssize1));
@@ -604,14 +604,14 @@ vbitset_andn (bitset dst, bitset src1, bitset src2)
   if (ssize2 > ssize1)
     {
       for (; i < ssize2; i++)
-       *dstp++ = 0;
+        *dstp++ = 0;
 
       memset (dstp, 0, sizeof (bitset_word) * (dsize - ssize2));
     }
   else
     {
       for (; i < ssize1; i++)
-       *dstp++ = *src1p++;
+        *dstp++ = *src1p++;
 
       memset (dstp, 0, sizeof (bitset_word) * (dsize - ssize1));
     }
@@ -644,37 +644,37 @@ vbitset_andn_cmp (bitset dst, bitset src1, bitset src2)
       bitset_word tmp = *src1p++ & ~(*src2p++);
 
       if (*dstp != tmp)
-       {
-         changed = 1;
-         *dstp = tmp;
-       }
+        {
+          changed = 1;
+          *dstp = tmp;
+        }
     }
 
   if (ssize2 > ssize1)
     {
       for (; i < ssize2; i++, dstp++)
-       {
-         if (*dstp != 0)
-           {
-             changed = 1;
-             *dstp = 0;
-           }
-       }
+        {
+          if (*dstp != 0)
+            {
+              changed = 1;
+              *dstp = 0;
+            }
+        }
 
       memset (dstp, 0, sizeof (bitset_word) * (dsize - ssize2));
     }
   else
     {
       for (; i < ssize1; i++, dstp++)
-       {
-         bitset_word tmp = *src1p++;
+        {
+          bitset_word tmp = *src1p++;
 
-         if (*dstp != tmp)
-           {
-             changed = 1;
-             *dstp = tmp;
-           }
-       }
+          if (*dstp != tmp)
+            {
+              changed = 1;
+              *dstp = tmp;
+            }
+        }
 
       memset (dstp, 0, sizeof (bitset_word) * (dsize - ssize1));
     }
@@ -745,10 +745,10 @@ vbitset_or_cmp (bitset dst, bitset src1, bitset src2)
       bitset_word tmp = *src1p++ | *src2p++;
 
       if (*dstp != tmp)
-       {
-         changed = 1;
-         *dstp = tmp;
-       }
+        {
+          changed = 1;
+          *dstp = tmp;
+        }
     }
 
   if (ssize2 > ssize1)
@@ -762,10 +762,10 @@ vbitset_or_cmp (bitset dst, bitset src1, bitset src2)
       bitset_word tmp = *src1p++;
 
       if (*dstp != tmp)
-       {
-         changed = 1;
-         *dstp = tmp;
-       }
+        {
+          changed = 1;
+          *dstp = tmp;
+        }
     }
 
   memset (dstp, 0, sizeof (bitset_word) * (dsize - ssize1));
@@ -836,10 +836,10 @@ vbitset_xor_cmp (bitset dst, bitset src1, bitset src2)
       bitset_word tmp = *src1p++ ^ *src2p++;
 
       if (*dstp != tmp)
-       {
-         changed = 1;
-         *dstp = tmp;
-       }
+        {
+          changed = 1;
+          *dstp = tmp;
+        }
     }
 
   if (ssize2 > ssize1)
@@ -853,10 +853,10 @@ vbitset_xor_cmp (bitset dst, bitset src1, bitset src2)
       bitset_word tmp = *src1p++;
 
       if (*dstp != tmp)
-       {
-         changed = 1;
-         *dstp = tmp;
-       }
+        {
+          changed = 1;
+          *dstp = tmp;
+        }
     }
 
   memset (dstp, 0, sizeof (bitset_word) * (dsize - ssize1));
@@ -926,10 +926,10 @@ vbitset_and_or_cmp (bitset dst, bitset src1, bitset src2, bitset src3)
       bitset_word tmp = (*src1p++ & *src2p++) | *src3p++;
 
       if (*dstp != tmp)
-       {
-         changed = 1;
-         *dstp = tmp;
-       }
+        {
+          changed = 1;
+          *dstp = tmp;
+        }
     }
   return changed;
 }
@@ -993,10 +993,10 @@ vbitset_andn_or_cmp (bitset dst, bitset src1, bitset src2, bitset src3)
       bitset_word tmp = (*src1p++ & ~(*src2p++)) | *src3p++;
 
       if (*dstp != tmp)
-       {
-         changed = 1;
-         *dstp = tmp;
-       }
+        {
+          changed = 1;
+          *dstp = tmp;
+        }
     }
   return changed;
 }
@@ -1060,10 +1060,10 @@ vbitset_or_and_cmp (bitset dst, bitset src1, bitset src2, bitset src3)
       bitset_word tmp = (*src1p++ | *src2p++) & *src3p++;
 
       if (*dstp != tmp)
-       {
-         changed = 1;
-         *dstp = tmp;
-       }
+        {
+          changed = 1;
+          *dstp = tmp;
+        }
     }
   return changed;
 }
index 8b665097b182d45cfcb0889fff21c0e66e6badb7..5b7d363066fabf5b3a3f3f44f965cbe7a32fc454 100644 (file)
@@ -50,6 +50,7 @@
 /include_next.m4
 /intdiv0.m4
 /intl.m4
+/intl.m4~
 /intldir.m4
 /intlmacosx.m4
 /intmax.m4
@@ -62,7 +63,6 @@
 /isnand.m4
 /isnanf.m4
 /isnanl.m4
-/iswblank.m4
 /javacomp.m4
 /javaexec.m4
 /largefile.m4
@@ -81,8 +81,6 @@
 /longlong.m4
 /malloc.m4
 /math_h.m4
-/mbchar.m4
-/mbiter.m4
 /mbrtowc.m4
 /mbsinit.m4
 /mbstate_t.m4
 /perror.m4
 /pipe2.m4
 /po.m4
+/po.m4~
 /posix_spawn.m4
 /printf-frexp.m4
 /printf-frexpl.m4
 /xstrndup.m4
 /obstack-printf.m4
 /extern-inline.m4
-/getdelim.m4
-/getline.m4
+/non-recursive-gnulib-prefix-hack.m4
index b09d8555630f25aac5a9ed216f5c7df65f742d3a..73f8e83f20341bdd587d7eee66c4da7af95334b1 100644 (file)
@@ -21,7 +21,7 @@ AC_DEFUN([BISON_TEST_FOR_WORKING_C_COMPILER], [
   AC_COMPILE_IFELSE(
     [AC_LANG_PROGRAM(
        [[#include <limits.h>
-        int test_array[CHAR_BIT];]])],
+         int test_array[CHAR_BIT];]])],
     [],
     [AC_MSG_FAILURE([cannot compile a simple C program])])
    AC_SUBST([BISON_C_WORKS], [:])
index 8d3505bce6dda40aa550f0a699d99d73821c4929..3fb5d9e0868c7f79a679cc32b99216fc83983294 100644 (file)
--- a/m4/cxx.m4
+++ b/m4/cxx.m4
@@ -26,25 +26,25 @@ AC_DEFUN([BISON_TEST_FOR_WORKING_CXX_COMPILER],
     bison_cv_cxx_works=no
     AC_COMPILE_IFELSE(
       [AC_LANG_PROGRAM(
-        [#include <cstdlib>
-         #include <iostream>
-         #include <map>
-         #include <string>
-         using namespace std;],
+         [#include <cstdlib>
+          #include <iostream>
+          #include <map>
+          #include <string>
+          using namespace std;],
          [std::cerr << "";
           cout << "";
-         typedef std::pair<unsigned int, int> uipair;
-         std::map<unsigned int, int> m;
-         std::map<unsigned int, int>::iterator i;
-         m.insert (uipair (4, -4));
-         for (i = m.begin (); i != m.end (); ++i)
-           if (i->first != 4)
-             return 1;])],
+          typedef std::pair<unsigned int, int> uipair;
+          std::map<unsigned int, int> m;
+          std::map<unsigned int, int>::iterator i;
+          m.insert (uipair (4, -4));
+          for (i = m.begin (); i != m.end (); ++i)
+            if (i->first != 4)
+              return 1;])],
       [AS_IF([AC_TRY_COMMAND([$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_objext $LIBS >&AS_MESSAGE_LOG_FD])],
-        [AS_IF([test "$cross_compiling" = yes],
-           [bison_cv_cxx_works=cross],
-           [AS_IF([AC_TRY_COMMAND(./conftest$ac_exeext)],
-              [bison_cv_cxx_works=yes])])])
+         [AS_IF([test "$cross_compiling" = yes],
+            [bison_cv_cxx_works=cross],
+            [AS_IF([AC_TRY_COMMAND(./conftest$ac_exeext)],
+               [bison_cv_cxx_works=yes])])])
        rm -f conftest$ac_exeext])
     AC_LANG_POP([C++])])
 
index 4907dbcbe114befdcea9e46b979a3ac84bf5c599..6f8530aecbbb2e059aaba95aa160dedca5cd6f28 100644 (file)
@@ -78,7 +78,7 @@ if test -z "${LEXLIB+set}"; then
     for ac_lib in '' -lfl -ll; do
       LIBS="$ac_lib $ac_save_LIBS"
       AC_LINK_IFELSE([AC_LANG_DEFINES_PROVIDED[`cat $LEX_OUTPUT_ROOT.c`]],
-       [ac_cv_lib_lex=$ac_lib])
+        [ac_cv_lib_lex=$ac_lib])
       test "$ac_cv_lib_lex" != 'none needed' && break
     done
     LIBS=$ac_save_LIBS
@@ -104,8 +104,8 @@ LIBS=$ac_save_LIBS
 dnl
 if test $ac_cv_prog_lex_yytext_pointer = yes; then
   AC_DEFINE([YYTEXT_POINTER], [1],
-           [Define to 1 if `lex' declares `yytext' as a `char *' by default,
-            not a `char[]'.])
+            [Define to 1 if `lex' declares `yytext' as a `char *' by default,
+             not a `char[]'.])
 fi
 rm -f conftest.l $LEX_OUTPUT_ROOT.c
 ])# _AC_PROG_LEX_YYTEXT_DECL
index 79594c04304c4a8b5f5545c7fdd7b3302fccbd77..940ce9efe690d672f6cb2b0432d62df006ae5f45 100644 (file)
@@ -6,6 +6,7 @@
 /Makefile
 /Makefile.in
 /Makefile.in.in
+/Makefile.in.in~
 /Makevars
 /Makevars.template
 /POTFILES
index 44ff89631ff95a91c769e6eb4bd7f8d72a90ef14..8675428f03af08d946bf95ad25b0e53daf2f6d9c 100644 (file)
@@ -6,6 +6,7 @@
 /Makefile
 /Makefile.in
 /Makefile.in.in
+/Makefile.in.in~
 /Makevars
 /Makevars.template
 /POTFILES
index 16780b8cb24e62c5c802724de591340cb371962c..87447466a2ab925fac9f1bc8c0f3dab2c222b1be 100644 (file)
@@ -4,8 +4,6 @@
 /*.output
 /.deps
 /.dirstamp
-/Makefile
-/Makefile.in
 /bison
 /bison.exe
 /scan-code.c
index afa3d2136b8c5a1881a030146212641318252a6d..5abaa2e79be9d8688b674c17d31db35d26a67594 100644 (file)
 #ifndef ANNOTATION_LIST_H_
 # define ANNOTATION_LIST_H_
 
-#include <bitsetv.h>
-#include "Sbitset.h"
-#include "InadequacyList.h"
-#include "state.h"
+# include <bitsetv.h>
+# include "Sbitset.h"
+# include "InadequacyList.h"
+# include "state.h"
 
 typedef unsigned int AnnotationIndex;
 
index d205dd50e7670484f44b39ce49e18d91fffbc0f4..d293b9b6c6b951491068c748926095382c653d6d 100644 (file)
 #ifndef INADEQUACY_LIST_H_
 # define INADEQUACY_LIST_H_
 
-#include <bitset.h>
-#include "gram.h"
-#include "state.h"
-#include "symtab.h"
+# include <bitset.h>
+# include "gram.h"
+# include "state.h"
+# include "symtab.h"
 
 /**
  * A unique ID assigned to every \c InadequacyList node.
@@ -90,7 +90,7 @@ typedef struct InadequacyList {
  *     <tt>manifesting_state->reductions->num + 1</tt>.
  *   - If the set of all \c InadequacyList nodes with which the new
  *     \c InadequacyList node might be compared is currently empty, then
- *     it is best if <tt>*node_count</t> is zero so that the node count
+ *     it is best if <tt>*node_count</tt> is zero so that the node count
  *     does not eventually overflow.  However, if that set is not
  *     currently empty, then <tt>*node_count</tt> has not been modified
  *     by any function except \c InadequacyList__new_conflict since the
index 62cdb2b32de8a453afce530834a3e12d9ed9ec4f..f6a9537e4cfa47ade6659d88229e949b4fca5a24 100644 (file)
--- a/src/LR0.c
+++ b/src/LR0.c
@@ -1,7 +1,7 @@
 /* Generate the LR(0) parser states for Bison.
 
-   Copyright (C) 1984, 1986, 1989, 2000-2002, 2004-2007, 2009-2013 Free
-   Software Foundation, Inc.
+   Copyright (C) 1984, 1986, 1989, 2000-2002, 2004-2013 Free Software
+   Foundation, Inc.
 
    This file is part of Bison, the GNU Compiler Compiler.
 
@@ -32,7 +32,6 @@
 #include "complain.h"
 #include "getargs.h"
 #include "gram.h"
-#include "gram.h"
 #include "lalr.h"
 #include "reader.h"
 #include "reduce.h"
@@ -62,7 +61,7 @@ state_list_append (symbol_number sym, size_t core_size, item_number *core)
 
   if (trace_flag & trace_automaton)
     fprintf (stderr, "state_list_append (state = %d, symbol = %d (%s))\n",
-            nstates, sym, symbols[sym]->tag);
+             nstates, sym, symbols[sym]->tag);
 
   node->next = NULL;
   node->state = s;
@@ -100,13 +99,13 @@ allocate_itemsets (void)
      symbols.  */
   size_t count = 0;
   size_t *symbol_count = xcalloc (nsyms + nuseless_nonterminals,
-                                 sizeof *symbol_count);
+                                  sizeof *symbol_count);
 
   for (r = 0; r < nrules; ++r)
     for (rhsp = rules[r].rhs; *rhsp >= 0; ++rhsp)
       {
-       count++;
-       symbol_count[*rhsp]++;
+        count++;
+        symbol_count[*rhsp]++;
       }
 
   /* See comments before new_itemsets.  All the vectors of items
@@ -187,15 +186,15 @@ new_itemsets (state *s)
   for (i = 0; i < nitemset; ++i)
     if (item_number_is_symbol_number (ritem[itemset[i]]))
       {
-       symbol_number sym = item_number_as_symbol_number (ritem[itemset[i]]);
-       if (!kernel_size[sym])
-         {
-           shift_symbol[nshifts] = sym;
-           nshifts++;
-         }
-
-       kernel_base[sym][kernel_size[sym]] = itemset[i] + 1;
-       kernel_size[sym]++;
+        symbol_number sym = item_number_as_symbol_number (ritem[itemset[i]]);
+        if (!kernel_size[sym])
+          {
+            shift_symbol[nshifts] = sym;
+            nshifts++;
+          }
+
+        kernel_base[sym][kernel_size[sym]] = itemset[i] + 1;
+        kernel_size[sym]++;
       }
 }
 
@@ -214,7 +213,7 @@ get_state (symbol_number sym, size_t core_size, item_number *core)
 
   if (trace_flag & trace_automaton)
     fprintf (stderr, "Entering get_state, symbol = %d (%s)\n",
-            sym, symbols[sym]->tag);
+             sym, symbols[sym]->tag);
 
   s = state_hash_lookup (core_size, core);
   if (!s)
@@ -228,7 +227,7 @@ get_state (symbol_number sym, size_t core_size, item_number *core)
 
 /*---------------------------------------------------------------.
 | Use the information computed by new_itemsets to find the state |
-| numbers reached by each shift transition from S.              |
+| numbers reached by each shift transition from S.               |
 |                                                                |
 | SHIFTSET is set up as a vector of those states.                |
 `---------------------------------------------------------------*/
@@ -248,7 +247,7 @@ append_states (state *s)
       symbol_number sym = shift_symbol[i];
       int j;
       for (j = i; 0 < j && sym < shift_symbol[j - 1]; j--)
-       shift_symbol[j] = shift_symbol[j - 1];
+        shift_symbol[j] = shift_symbol[j - 1];
       shift_symbol[j] = sym;
     }
 
@@ -277,16 +276,16 @@ save_reductions (state *s)
     {
       item_number item = ritem[itemset[i]];
       if (item_number_is_rule_number (item))
-       {
-         rule_number r = item_number_as_rule_number (item);
-         redset[count++] = &rules[r];
-         if (r == 0)
-           {
-             /* This is "reduce 0", i.e., accept. */
-             aver (!final_state);
-             final_state = s;
-           }
-       }
+        {
+          rule_number r = item_number_as_rule_number (item);
+          redset[count++] = &rules[r];
+          if (r == 0)
+            {
+              /* This is "reduce 0", i.e., accept. */
+              aver (!final_state);
+              final_state = s;
+            }
+        }
     }
 
   /* Make a reductions structure and copy the data into it.  */
@@ -308,14 +307,14 @@ set_states (void)
       state_list *this = first_state;
 
       /* Pessimization, but simplification of the code: make sure all
-        the states have valid transitions and reductions members,
-        even if reduced to 0.  It is too soon for errs, which are
-        computed later, but set_conflicts.  */
+         the states have valid transitions and reductions members,
+         even if reduced to 0.  It is too soon for errs, which are
+         computed later, but set_conflicts.  */
       state *s = this->state;
       if (!s->transitions)
-       state_transitions_set (s, 0, 0);
+        state_transitions_set (s, 0, 0);
       if (!s->reductions)
-       state_reductions_set (s, 0, 0);
+        state_reductions_set (s, 0, 0);
 
       states[s->number] = s;
 
@@ -349,9 +348,9 @@ generate_states (void)
     {
       state *s = list->state;
       if (trace_flag & trace_automaton)
-       fprintf (stderr, "Processing state %d (reached by %s)\n",
-                s->number,
-                symbols[s->accessing_symbol]->tag);
+        fprintf (stderr, "Processing state %d (reached by %s)\n",
+                 s->number,
+                 symbols[s->accessing_symbol]->tag);
       /* Set up itemset for the transitions out of this state.  itemset gets a
          vector of all the items that could be accepted next.  */
       closure (s->items, s->nitems);
@@ -363,7 +362,7 @@ generate_states (void)
       append_states (s);
 
       /* Create the shifts structures for the shifts to those states,
-        now that the state numbers transitioning to are known.  */
+         now that the state numbers transitioning to are known.  */
       state_transitions_set (s, nshifts, shiftset);
     }
 
diff --git a/src/Makefile.am b/src/Makefile.am
deleted file mode 100644 (file)
index 9e61ff0..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-# Make bison/src.
-
-# Copyright (C) 2001-2013 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/>.
-
-AM_CFLAGS = $(WARN_CFLAGS) $(WERROR_CFLAGS)
-AM_CPPFLAGS = -I$(top_srcdir)/lib
-BISON = ../tests/bison
-# Use our own Bison to build the parser.  Of course, you ought to
-# keep a sane version of Bison nearby...
-YACC = $(BISON) -y
-AM_YFLAGS = -d -v --warnings=all,error --report=all
-
-LDADD = ../lib/libbison.a $(LIBINTL)
-
-bin_PROGRAMS = bison
-bin_SCRIPTS = $(YACC_SCRIPT)
-EXTRA_SCRIPTS = yacc
-
-bison_SOURCES =                                 \
-  AnnotationList.c AnnotationList.h             \
-  InadequacyList.c InadequacyList.h             \
-  LR0.c LR0.h                                   \
-  Sbitset.c Sbitset.h                           \
-  assoc.c assoc.h                               \
-  closure.c closure.h                           \
-  complain.c complain.h                         \
-  conflicts.c conflicts.h                       \
-  derives.c derives.h                           \
-  files.c files.h                               \
-  flex-scanner.h                                \
-  getargs.c getargs.h                           \
-  gram.c gram.h                                 \
-  lalr.h lalr.c                                 \
-  ielr.h ielr.c                                 \
-  location.c location.h                         \
-  main.c                                        \
-  muscle-tab.c muscle-tab.h                     \
-  named-ref.c named-ref.h                       \
-  nullable.c nullable.h                         \
-  output.c output.h                             \
-  parse-gram.y                                  \
-  print.c print.h                               \
-  print_graph.c print_graph.h                   \
-  print-xml.c print-xml.h                       \
-  reader.c reader.h                             \
-  reduce.c reduce.h                             \
-  relation.c relation.h                         \
-  scan-code.h scan-code-c.c                     \
-  scan-gram.h scan-gram-c.c                     \
-  scan-skel.h scan-skel-c.c                     \
-  state.c state.h                               \
-  symlist.c symlist.h                           \
-  symtab.c symtab.h                             \
-  system.h                                      \
-  tables.h tables.c                             \
-  uniqstr.c uniqstr.h                           \
-  graphviz.c graphviz.h
-
-EXTRA_bison_SOURCES = scan-code.l scan-skel.l scan-gram.l
-
-BUILT_SOURCES =                                 \
-  parse-gram.c parse-gram.h                     \
-  scan-code.c                                   \
-  scan-skel.c                                   \
-  scan-gram.c
-
-MOSTLYCLEANFILES = yacc
-
-yacc:
-       $(AM_V_GEN)echo '#! /bin/sh' >$@
-       $(AM_V_at)echo "exec '$(bindir)/bison' -y "'"$$@"' >>$@
-       $(AM_V_at)chmod a+x $@
-
-
-# The following rule is not designed to be portable,
-# and relies on tools that not everyone has.
-
-# Most functions in src/*.c should have static scope.
-# Any that don't must be marked with `extern', but `main'
-# and `usage' are exceptions.  They're always extern, but
-# don't need to be marked.
-#
-# The second nm|grep checks for file-scope variables with `extern' scope.
-sc_tight_scope: $(all_programs)
-       @t=exceptions-$$$$;                                             \
-       trap 's=$$?; rm -f $$t; exit $$s' 0 1 2 13 15;                  \
-       ( printf '^main$$\n^usage$$\n';                                 \
-         grep -h -A1 '^extern .*[^;]$$' $(SOURCES)                     \
-           | grep -vE '^(extern |--)' |sed 's/^/^/;s/ .*/$$/' ) > $$t; \
-       if nm -e *.$(OBJEXT)                                            \
-           | sed -n 's/.* T //p'                                       \
-           | grep -Ev -f $$t; then                                     \
-         echo 'the above functions should have static scope' 1>&2;     \
-         exit 1;                                                       \
-       fi;                                                             \
-       ( printf '^program_name$$\n';                                   \
-         sed -n 's/^extern .*[* ]\([a-zA-Z_][a-zA-Z_0-9]*\);$$/^\1$$/p' \
-           $$(ls $(SOURCES) | grep '\.h$$') /dev/null) > $$t;          \
-       if nm -e *.$(OBJEXT)                                            \
-           | sed -n 's/.* [BD] //p'                                    \
-           | grep -Ev -f $$t; then                                     \
-         echo 'the above variables should have static scope' 1>&2;     \
-         exit 1;                                                       \
-       fi
index 0e4dab3a82fb457f2638f1cc93c296f7433ef447..a930196ebd57ec5818f513f44e5f8936aed3b7b3 100644 (file)
 
 typedef unsigned char *Sbitset;
 typedef size_t Sbitset__Index;
-#define SBITSET__INDEX__CONVERSION_SPEC "zu"
+# define SBITSET__INDEX__CONVERSION_SPEC "zu"
 
-#define Sbitset__nbytes(NBITS) \
+# define Sbitset__nbytes(NBITS) \
   (((NBITS) + CHAR_BIT - 1) / CHAR_BIT)
-#define Sbitset__byteAddress(SELF, INDEX) \
+# define Sbitset__byteAddress(SELF, INDEX) \
   (((SELF) + (INDEX) / CHAR_BIT))
-#define Sbitset__bit_mask(INDEX) \
+# define Sbitset__bit_mask(INDEX) \
   (1 << (CHAR_BIT - 1 - (INDEX) % CHAR_BIT))
-#define Sbitset__last_byte_mask(NBITS) \
+# define Sbitset__last_byte_mask(NBITS) \
   (UCHAR_MAX << (CHAR_BIT - 1 - ((NBITS) - 1) % CHAR_BIT))
 
 /* nbits must not be 0.  */
@@ -39,54 +39,54 @@ Sbitset Sbitset__new_on_obstack (Sbitset__Index nbits,
                                  struct obstack *obstackp);
 void Sbitset__delete (Sbitset self);
 
-#define Sbitset__test(SELF, INDEX)                                            \
+# define Sbitset__test(SELF, INDEX)                                     \
   ((*Sbitset__byteAddress ((SELF), (INDEX)) & Sbitset__bit_mask (INDEX)) != 0)
 
 bool Sbitset__isEmpty (Sbitset self, Sbitset__Index nbits);
 
 void Sbitset__fprint(Sbitset self, Sbitset__Index nbits, FILE *file);
 
-#define Sbitset__set(SELF, INDEX)                                             \
-do {                                                                          \
-  *Sbitset__byteAddress ((SELF), (INDEX)) =                                   \
-    *Sbitset__byteAddress ((SELF), (INDEX)) | Sbitset__bit_mask (INDEX);      \
-} while(0)
+# define Sbitset__set(SELF, INDEX)                                      \
+  do {                                                                  \
+    *Sbitset__byteAddress ((SELF), (INDEX)) =                           \
+      *Sbitset__byteAddress ((SELF), (INDEX)) | Sbitset__bit_mask (INDEX); \
+  } while(0)
 
-#define Sbitset__reset(SELF, INDEX)                                           \
-do {                                                                          \
-  *Sbitset__byteAddress ((SELF), (INDEX)) =                                   \
-    *Sbitset__byteAddress ((SELF), (INDEX)) & ~Sbitset__bit_mask (INDEX);     \
-} while(0)
+# define Sbitset__reset(SELF, INDEX)                                    \
+  do {                                                                  \
+    *Sbitset__byteAddress ((SELF), (INDEX)) =                           \
+      *Sbitset__byteAddress ((SELF), (INDEX)) & ~Sbitset__bit_mask (INDEX); \
+  } while(0)
 
 /* NBITS is the size of the bitset.  More than NBITS bits might be reset.  */
-#define Sbitset__zero(SELF, NBITS)                                            \
-do {                                                                          \
-  memset (SELF, 0, Sbitset__nbytes (NBITS));                                  \
-} while(0)
+# define Sbitset__zero(SELF, NBITS)             \
+  do {                                          \
+    memset (SELF, 0, Sbitset__nbytes (NBITS));  \
+  } while(0)
 
 /* NBITS is the size of the bitset.  More than NBITS bits might be set.  */
-#define Sbitset__ones(SELF, NBITS)                                            \
-do {                                                                          \
-  memset (SELF, UCHAR_MAX, Sbitset__nbytes (NBITS));                          \
-} while(0)
+# define Sbitset__ones(SELF, NBITS)                     \
+  do {                                                  \
+    memset (SELF, UCHAR_MAX, Sbitset__nbytes (NBITS));  \
+  } while(0)
 
 /* NBITS is the size of every bitset.  More than NBITS bits might be set.  */
-#define Sbitset__or(SELF, OTHER1, OTHER2, NBITS)                              \
-do {                                                                          \
-  Sbitset ptr_self = (SELF);                                                  \
-  Sbitset ptr_other1 = (OTHER1);                                              \
-  Sbitset ptr_other2 = (OTHER2);                                              \
-  Sbitset end_self = ptr_self + Sbitset__nbytes (NBITS);                      \
-  for (; ptr_self < end_self; ++ptr_self, ++ptr_other1, ++ptr_other2)         \
-    *ptr_self = *ptr_other1 | *ptr_other2;                                    \
-} while(0)
-
-#define SBITSET__FOR_EACH(SELF, NBITS, ITER, INDEX)                           \
-  for ((ITER) = (SELF); (ITER) < (SELF) + Sbitset__nbytes (NBITS); ++(ITER))  \
-    if (*(ITER) != 0)                                                         \
-      for ((INDEX) = ((ITER)-(SELF))*CHAR_BIT;                                \
-           (INDEX) < (NBITS) && (SELF)+(INDEX)/CHAR_BIT < (ITER)+1;           \
-           ++(INDEX))                                                         \
+# define Sbitset__or(SELF, OTHER1, OTHER2, NBITS)                       \
+  do {                                                                  \
+    Sbitset ptr_self = (SELF);                                          \
+    Sbitset ptr_other1 = (OTHER1);                                      \
+    Sbitset ptr_other2 = (OTHER2);                                      \
+    Sbitset end_self = ptr_self + Sbitset__nbytes (NBITS);              \
+    for (; ptr_self < end_self; ++ptr_self, ++ptr_other1, ++ptr_other2) \
+      *ptr_self = *ptr_other1 | *ptr_other2;                            \
+  } while(0)
+
+# define SBITSET__FOR_EACH(SELF, NBITS, ITER, INDEX)                    \
+  for ((ITER) = (SELF); (ITER) < (SELF) + Sbitset__nbytes (NBITS); ++(ITER)) \
+    if (*(ITER) != 0)                                                   \
+      for ((INDEX) = ((ITER)-(SELF))*CHAR_BIT;                          \
+           (INDEX) < (NBITS) && (SELF)+(INDEX)/CHAR_BIT < (ITER)+1;     \
+           ++(INDEX))                                                   \
         if (((*ITER) & Sbitset__bit_mask (INDEX)) != 0)
 
 #endif /* !SBITSET_H_ */
index 43227f02be718cf8fc30d256386e057686ea8af1..d2eec31574e2994bc1d955f19c7b0885c22874d5 100644 (file)
@@ -1,6 +1,6 @@
 /* Associativity information.
 
-   Copyright (C) 2002, 2005-2006, 2009-2013 Free Software Foundation,
+   Copyright (C) 2002, 2005-2006, 2008-2013 Free Software Foundation,
    Inc.
 
    This file is part of Bison, the GNU Compiler Compiler.
@@ -43,5 +43,8 @@ assoc_to_string (assoc a)
 
     case non_assoc:
       return "%nonassoc";
+
+    case precedence_assoc:
+      return "%precedence";
     }
 }
index 4d9e759d30c772981fe9496d72fe76f870a74018..b9475b5d127b50c56a743953d6ec056ef897aa37 100644 (file)
@@ -1,6 +1,6 @@
 /* Associativity information.
 
-   Copyright (C) 2002, 2006, 2009-2013 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2006, 2008-2013 Free Software Foundation, Inc.
 
    This file is part of Bison, the GNU Compiler Compiler.
 
 /* Associativity values for tokens and rules.  */
 typedef enum
 {
-  undef_assoc,
-  right_assoc,
-  left_assoc,
-  non_assoc
+  undef_assoc,     /** Not defined. */
+  right_assoc,     /** %right */
+  left_assoc,      /** %left */
+  non_assoc,       /** %nonassoc */
+  precedence_assoc /** %precedence */
 } assoc;
 
 char const *assoc_to_string (assoc a);
index c2223caa50219159f2355ecc75c0025546e16e4c..45e8311022e9cbcd94ecc894b789309bd6eaa9f2 100644 (file)
@@ -44,7 +44,7 @@ static bitsetv firsts = NULL;
 
 /* Retrieve the FDERIVES/FIRSTS sets of the nonterminals numbered Var.  */
 #define FDERIVES(Var)   fderives[(Var) - ntokens]
-#define   FIRSTS(Var)   firsts[(Var) - ntokens]
+#define FIRSTS(Var)   firsts[(Var) - ntokens]
 \f
 
 /*-----------------.
@@ -52,7 +52,7 @@ static bitsetv firsts = NULL;
 `-----------------*/
 
 static void
-print_closure (char const *title, item_number *array, size_t size)
+print_closure (char const *title, item_number const *array, size_t size)
 {
   size_t i;
   fprintf (stderr, "Closure: %s\n", title);
@@ -61,7 +61,7 @@ print_closure (char const *title, item_number *array, size_t size)
       item_number *rp;
       fprintf (stderr, "  %2d: .", array[i]);
       for (rp = &ritem[array[i]]; *rp >= 0; ++rp)
-       fprintf (stderr, " %s", symbols[*rp]->tag);
+        fprintf (stderr, " %s", symbols[*rp]->tag);
       fprintf (stderr, "  (rule %d)\n", -*rp - 1);
     }
   fputs ("\n\n", stderr);
@@ -77,12 +77,9 @@ print_firsts (void)
   for (i = ntokens; i < nsyms; i++)
     {
       bitset_iterator iter;
-      fprintf (stderr, "\t%s firsts\n", symbols[i]->tag);
+      fprintf (stderr, "  %s firsts\n", symbols[i]->tag);
       BITSET_FOR_EACH (iter, FIRSTS (i), j, 0)
-       {
-         fprintf (stderr, "\t\t%s\n",
-                  symbols[j + ntokens]->tag);
-       }
+        fprintf (stderr, "    %s\n", symbols[j + ntokens]->tag);
     }
   fprintf (stderr, "\n\n");
 }
@@ -98,12 +95,13 @@ print_fderives (void)
   for (i = ntokens; i < nsyms; i++)
     {
       bitset_iterator iter;
-      fprintf (stderr, "\t%s derives\n", symbols[i]->tag);
+      fprintf (stderr, "  %s derives\n", symbols[i]->tag);
       BITSET_FOR_EACH (iter, FDERIVES (i), r, 0)
-       {
-         fprintf (stderr, "\t\t%3d ", r);
-         rule_rhs_print (&rules[r], stderr);
-       }
+        {
+          fprintf (stderr, "    %3d ", r);
+          rule_rhs_print (&rules[r], stderr);
+          fprintf (stderr, "\n");
+        }
     }
   fprintf (stderr, "\n\n");
 }
@@ -129,9 +127,9 @@ set_firsts (void)
   for (i = ntokens; i < nsyms; i++)
     for (j = 0; derives[i - ntokens][j]; ++j)
       {
-       item_number sym = derives[i - ntokens][j]->rhs[0];
-       if (ISVAR (sym))
-         bitset_set (FIRSTS (i), sym - ntokens);
+        item_number sym = derives[i - ntokens][j]->rhs[0];
+        if (ISVAR (sym))
+          bitset_set (FIRSTS (i), sym - ntokens);
       }
 
   if (trace_flag & trace_sets)
@@ -167,8 +165,8 @@ set_fderives (void)
   for (i = ntokens; i < nsyms; ++i)
     for (j = ntokens; j < nsyms; ++j)
       if (bitset_test (FIRSTS (i), j - ntokens))
-       for (k = 0; derives[j - ntokens][k]; ++k)
-         bitset_set (FDERIVES (i), derives[j - ntokens][k]->number);
+        for (k = 0; derives[j - ntokens][k]; ++k)
+          bitset_set (FDERIVES (i), derives[j - ntokens][k]->number);
 
   if (trace_flag & trace_sets)
     print_fderives ();
@@ -191,7 +189,7 @@ new_closure (unsigned int n)
 
 
 void
-closure (item_number *core, size_t n)
+closure (item_number const *core, size_t n)
 {
   /* Index over CORE. */
   size_t c;
@@ -218,11 +216,11 @@ closure (item_number *core, size_t n)
     {
       item_number itemno = rules[ruleno].rhs - ritem;
       while (c < n && core[c] < itemno)
-       {
-         itemset[nitemset] = core[c];
-         nitemset++;
-         c++;
-       }
+        {
+          itemset[nitemset] = core[c];
+          nitemset++;
+          c++;
+        }
       itemset[nitemset] = itemno;
       nitemset++;
     };
index 89f5600f22074952dca97f1ec61e923c0bd48e88..ad4a3ba96b7ba3c361e26128acbd3f9193d8feed 100644 (file)
@@ -44,7 +44,7 @@ void new_closure (unsigned int n);
    significant).  CLOSURE places there the indices of all items which
    represent units of input that could arrive next.  */
 
-void closure (item_number *items, size_t n);
+void closure (item_number const *items, size_t n);
 
 
 /* Frees ITEMSET, RULESET and internal data.  */
index 7683f8c400c31799a90159b531bae97b91af8409..fdc4b5426b490b0c74bfd785b0fa6c8c327daf8d 100644 (file)
 #include <config.h>
 #include "system.h"
 
+#include <argmatch.h>
 #include <stdarg.h>
 #include <progname.h>
 
 #include "complain.h"
 #include "files.h"
 #include "getargs.h"
+#include "quote.h"
+
+err_status complaint_status = status_none;
+
+bool warnings_are_errors = false;
+
+/** Diagnostics severity.  */
+typedef enum
+  {
+    severity_disabled = 0,
+    severity_unset = 1,
+    severity_warning = 2,
+    severity_error = 3,
+    severity_fatal = 4
+  } severity;
+
+
+/** For each warning type, its severity.  */
+static severity warnings_flag[warnings_size];
 
-bool complaint_issued;
 static unsigned *indent_ptr = 0;
 
-\f
+/*------------------------.
+| --warnings's handling.  |
+`------------------------*/
+
+static const char * const warnings_args[] =
+{
+  "none",
+  "midrule-values",
+  "yacc",
+  "conflicts-sr",
+  "conflicts-rr",
+  "deprecated",
+  "empty-rule",
+  "precedence",
+  "other",
+  "all",
+  "error",
+  "everything",
+  0
+};
+
+static const int warnings_types[] =
+{
+  Wnone,
+  Wmidrule_values,
+  Wyacc,
+  Wconflicts_sr,
+  Wconflicts_rr,
+  Wdeprecated,
+  Wempty_rule,
+  Wprecedence,
+  Wother,
+  Wall,
+  Werror,
+  Weverything
+};
+
+ARGMATCH_VERIFY (warnings_args, warnings_types);
+
+void
+warning_argmatch (char const *arg, size_t no, size_t err)
+{
+  int value = XARGMATCH ("--warning", arg + no + err,
+                         warnings_args, warnings_types);
+
+  /* -Wnone == -Wno-everything, and -Wno-none == -Weverything.  */
+  if (!value)
+    {
+      value = Weverything;
+      no = !no;
+    }
+
+  if (no)
+    {
+      size_t b;
+      for (b = 0; b < warnings_size; ++b)
+        if (value & 1 << b)
+          {
+            if (err)
+              {
+                /* -Wno-error=foo: if foo enabled as an error,
+                   make it a warning.  */
+                if (warnings_flag[b] == severity_error)
+                  warnings_flag[b] = severity_warning;
+              }
+            else
+              /* -Wno-foo.  */
+              warnings_flag[b] = severity_disabled;
+          }
+    }
+  else
+    {
+      size_t b;
+      for (b = 0; b < warnings_size; ++b)
+        if (value & 1 << b)
+          /* -Wfoo and -Werror=foo. */
+          warnings_flag[b] = err ? severity_error : severity_warning;
+    }
+}
+
+/** Decode a comma-separated list of arguments from -W.
+ *
+ *  \param args     comma separated list of effective subarguments to decode.
+ *                  If 0, then activate all the flags.
+ */
+
+void
+warnings_argmatch (char *args)
+{
+  if (args)
+    for (args = strtok (args, ","); args; args = strtok (NULL, ","))
+      if (STREQ (args, "error"))
+        warnings_are_errors = true;
+      else if (STREQ (args, "no-error"))
+        {
+          warnings_are_errors = false;
+          warning_argmatch ("no-error=everything", 3, 6);
+        }
+      else
+        {
+          size_t no = STRPREFIX_LIT ("no-", args) ? 3 : 0;
+          size_t err = STRPREFIX_LIT ("error=", args + no) ? 6 : 0;
+
+          warning_argmatch (args, no, err);
+        }
+  else
+    warning_argmatch ("all", 0, 0);
+}
+
+
+/*-----------.
+| complain.  |
+`-----------*/
+
+void
+complain_init (void)
+{
+  warnings warnings_default =
+    Wconflicts_sr | Wconflicts_rr | Wdeprecated | Wother;
+
+  size_t b;
+  for (b = 0; b < warnings_size; ++b)
+    warnings_flag[b] = (1 << b & warnings_default
+                        ? severity_warning
+                        : severity_unset);
+}
+
+static severity
+warning_severity (warnings flags)
+{
+  if (flags & fatal)
+    return severity_fatal;
+  else if (flags & complaint)
+    return severity_error;
+  else
+    {
+      severity res = severity_disabled;
+      size_t b;
+      for (b = 0; b < warnings_size; ++b)
+        if (flags & 1 << b)
+          res = res < warnings_flag[b] ? warnings_flag[b] : res;
+      if (res == severity_warning && warnings_are_errors)
+        res = severity_error;
+      return res;
+    }
+}
+
+bool
+warning_is_unset (warnings flags)
+{
+  size_t b;
+  for (b = 0; b < warnings_size; ++b)
+    if (flags & 1 << b && warnings_flag[b] != severity_unset)
+      return false;
+  return true;
+}
+
+/** Display a "[-Wyacc]" like message on \a f.  */
+
+static void
+warnings_print_categories (warnings warn_flags, FILE *f)
+{
+  /* Display only the first match, the second is "-Wall".  */
+  size_t i;
+  for (i = 0; warnings_args[i]; ++i)
+    if (warn_flags & warnings_types[i])
+      {
+        severity s = warning_severity (warnings_types[i]);
+        fprintf (f, " [-W%s%s]",
+                 s == severity_error ? "error=" : "",
+                 warnings_args[i]);
+        return;
+      }
+}
 
 /** Report an error message.
  *
  * \param loc     the location, defaulting to the current file,
  *                or the program name.
+ * \param flags   the category for this message.
  * \param prefix  put before the message (e.g., "warning").
  * \param message the error message, a printf format string.  Iff it
  *                ends with ": ", then no trailing newline is printed,
@@ -47,20 +240,21 @@ static unsigned *indent_ptr = 0;
  */
 static
 void
-error_message (location *loc,
-              const char *prefix,
-              const char *message, va_list args)
+error_message (const location *loc, warnings flags, const char *prefix,
+               const char *message, va_list args)
 {
   unsigned pos = 0;
 
   if (loc)
-    pos += location_print (stderr, *loc);
+    pos += location_print (*loc, stderr);
   else
-    pos += fprintf(stderr, "%s", current_file ? current_file : program_name);
-  pos += fprintf(stderr, ": ");
+    pos += fprintf (stderr, "%s", current_file ? current_file : program_name);
+  pos += fprintf (stderr, ": ");
 
   if (indent_ptr)
     {
+      if (*indent_ptr)
+        prefix = NULL;
       if (!*indent_ptr)
         *indent_ptr = pos;
       else if (*indent_ptr > pos)
@@ -72,146 +266,114 @@ error_message (location *loc,
     fprintf (stderr, "%s: ", prefix);
 
   vfprintf (stderr, message, args);
+  if (! (flags & silent))
+    warnings_print_categories (flags, stderr);
   {
     size_t l = strlen (message);
     if (l < 2 || message[l - 2] != ':' || message[l - 1] != ' ')
       {
         putc ('\n', stderr);
         fflush (stderr);
-        if (loc && feature_flag & feature_caret)
-          location_caret (stderr, *loc);
+        if (loc && feature_flag & feature_caret && !(flags & no_caret))
+          location_caret (*loc, stderr);
       }
   }
   fflush (stderr);
 }
 
-/** Wrap error_message() with varargs handling. */
-#define ERROR_MESSAGE(Loc, Prefix, Message)    \
-{                                              \
-  va_list args;                                        \
-  va_start (args, Message);                    \
-  error_message (Loc, Prefix, Message, args);  \
-  va_end (args);                               \
-}
-
+/** Raise a complaint. That can be a fatal error, an error or just a
+    warning.  */
 
-/*--------------------------------.
-| Report a warning, and proceed.  |
-`--------------------------------*/
-
-void
-set_warning_issued (void)
+static void
+complains (const location *loc, warnings flags, const char *message,
+           va_list args)
 {
-  static bool warning_issued = false;
-  if (!warning_issued && (warnings_flag & warnings_error))
+  severity s = warning_severity (flags);
+  if ((flags & complaint) && complaint_status < status_complaint)
+    complaint_status = status_complaint;
+
+  if (severity_warning <= s)
     {
-      fprintf (stderr, "%s: warnings being treated as errors\n", program_name);
-      complaint_issued = true;
+      const char* prefix =
+        s == severity_fatal ? _("fatal error")
+        : s == severity_error ? _("error")
+        : _("warning");
+      if (severity_error <= s && ! complaint_status)
+        complaint_status = status_warning_as_error;
+      error_message (loc, flags, prefix, message, args);
     }
-  warning_issued = true;
-}
-
-void
-warn_at (location loc, const char *message, ...)
-{
-  if (!(warnings_flag & warnings_other))
-    return;
-  set_warning_issued ();
-  ERROR_MESSAGE (&loc, _("warning"), message);
-}
-
-void
-warn_at_indent (location loc, unsigned *indent,
-                const char *message, ...)
-{
-  if (!(warnings_flag & warnings_other))
-    return;
-  set_warning_issued ();
-  indent_ptr = indent;
-  ERROR_MESSAGE (&loc, *indent ? NULL : _("warning"), message);
-}
 
-void
-warn (const char *message, ...)
-{
-  if (!(warnings_flag & warnings_other))
-    return;
-  set_warning_issued ();
-  ERROR_MESSAGE (NULL, _("warning"), message);
+  if (flags & fatal)
+    exit (EXIT_FAILURE);
 }
 
-
-/*-----------------------------------------------------------.
-| An error has occurred, but we can proceed, and die later.  |
-`-----------------------------------------------------------*/
-
 void
-complain_at (location loc, const char *message, ...)
+complain (location const *loc, warnings flags, const char *message, ...)
 {
-  ERROR_MESSAGE (&loc, _("error"), message);
-  complaint_issued = true;
+  va_list args;
+  va_start (args, message);
+  complains (loc, flags, message, args);
+  va_end (args);
 }
 
 void
-complain_at_indent (location loc, unsigned *indent,
-                    const char *message, ...)
+complain_indent (location const *loc, warnings flags, unsigned *indent,
+                 const char *message, ...)
 {
+  va_list args;
   indent_ptr = indent;
-  ERROR_MESSAGE (&loc, *indent ? NULL : _("error"), message);
-  complaint_issued = true;
-}
-
-void
-complain (const char *message, ...)
-{
-  ERROR_MESSAGE (NULL, _("error"), message);
-  complaint_issued = true;
-}
-
-
-/*--------------------------------------------------------------.
-| An incompatibility with POSIX Yacc: mapped either to warn* or |
-| complain* depending on yacc_flag.                             |
-`--------------------------------------------------------------*/
-
-void
-yacc_at (location loc, const char *message, ...)
-{
-  if (yacc_flag)
-    {
-      ERROR_MESSAGE (&loc, NULL, message);
-      complaint_issued = true;
-    }
-  else if (warnings_flag & warnings_yacc)
-    {
-      set_warning_issued ();
-      ERROR_MESSAGE (&loc, _("warning"), message);
-    }
+  va_start (args, message);
+  complains (loc, flags, message, args);
+  va_end (args);
 }
 
 void
-midrule_value_at (location loc, const char *message, ...)
+complain_args (location const *loc, warnings w, unsigned *indent,
+               int argc, char *argv[])
 {
-  if (!(warnings_flag & warnings_midrule_values))
-    return;
-  set_warning_issued ();
-  ERROR_MESSAGE (&loc, _("warning"), message);
+  switch (argc)
+  {
+  case 1:
+    complain_indent (loc, w, indent, "%s", _(argv[0]));
+    break;
+  case 2:
+    complain_indent (loc, w, indent, _(argv[0]), argv[1]);
+    break;
+  case 3:
+    complain_indent (loc, w, indent, _(argv[0]), argv[1], argv[2]);
+    break;
+  case 4:
+    complain_indent (loc, w, indent, _(argv[0]), argv[1], argv[2], argv[3]);
+    break;
+  case 5:
+    complain_indent (loc, w, indent, _(argv[0]), argv[1], argv[2], argv[3],
+                     argv[4]);
+    break;
+  default:
+    complain (loc, fatal, "too many arguments for complains");
+    break;
+  }
 }
 
-/*-------------------------------------------------.
-| A severe error has occurred, we cannot proceed.  |
-`-------------------------------------------------*/
-
 void
-fatal_at (location loc, const char *message, ...)
+deprecated_directive (location const *loc, char const *old, char const *upd)
 {
-  ERROR_MESSAGE (&loc, _("fatal error"), message);
-  exit (EXIT_FAILURE);
+  if (feature_flag & feature_caret)
+    complain (loc, Wdeprecated,
+              _("deprecated directive, use %s"),
+              quote_n (1, upd));
+  else
+    complain (loc, Wdeprecated,
+              _("deprecated directive: %s, use %s"),
+              quote (old), quote_n (1, upd));
 }
 
 void
-fatal (const char *message, ...)
+duplicate_directive (char const *directive,
+                     location first, location second)
 {
-  ERROR_MESSAGE (NULL, _("fatal error"), message);
-  exit (EXIT_FAILURE);
+  unsigned i = 0;
+  complain (&second, complaint, _("only one %s allowed per rule"), directive);
+  i += SUB_INDENT;
+  complain_indent (&first, complaint, &i, _("previous declaration"));
 }
index fe78e6f7b1be7f45f963a8d29203c7e129fd9848..0d81503df7eb2244d848660a50a86982d930e0c1 100644 (file)
 
 # include "location.h"
 
-# ifdef        __cplusplus
-extern "C" {
-# endif
-
 /* Sub-messages indent. */
-#define SUB_INDENT (4)
-
-/** Record that a warning is about to be issued, and treat it as an
-    error if <tt>warnings_flag & warnings_error</tt>.  This is exported
-    only for the sake of Yacc-compatible conflict reports in conflicts.c.
-    All other warnings should be implemented in complain.c and should use
-    the normal warning format.  */
-void set_warning_issued (void);
-
-/** Informative messages, but we proceed.  Report iff
-    <tt>warnings_flag & warnings_other</tt>.  */
-
-void warn (char const *format, ...)
-  __attribute__ ((__format__ (__printf__, 1, 2)));
-
-void warn_at (location loc, char const *format, ...)
-  __attribute__ ((__format__ (__printf__, 2, 3)));
-
-/* Generate a message aligned by an indent.
-   When *indent == 0, assign message's indent to *indent,
-   When *indent > 0, align the message by *indent value. */
-void warn_at_indent (location loc, unsigned *indent,
-                     char const *format, ...)
+# define SUB_INDENT (4)
+
+/*-------------.
+| --warnings.  |
+`-------------*/
+
+/** The bits assigned to each warning type.  */
+typedef enum
+  {
+    warning_midrule_values, /**< Unset or unused midrule values.  */
+    warning_yacc,           /**< POSIXME.  */
+    warning_conflicts_sr,   /**< S/R conflicts.  */
+    warning_conflicts_rr,   /**< R/R conflicts.  */
+    warning_empty_rule,     /**< Implicitly empty rules.  */
+    warning_deprecated,     /**< Obsolete constructs.  */
+    warning_precedence,     /**< Useless precedence and associativity.  */
+    warning_other,          /**< All other warnings.  */
+
+    warnings_size           /**< The number of warnings.  Must be last.  */
+  } warning_bit;
+
+/** Whether -Werror was set. */
+extern bool warnings_are_errors;
+
+/** Decode a single argument from -W.
+ *
+ *  \param arg      the subarguments to decode.
+ *                  If null, then activate all the flags.
+ *  \param no       length of the potential "no-" prefix.
+ *                  Can be 0 or 3. If 3, negate the action of the subargument.
+ *  \param err      length of a potential "error=".
+ *                  Can be 0 or 6. If 6, treat the subargument as a CATEGORY.
+ *
+ *  If VALUE != 0 then KEY sets flags and no-KEY clears them.
+ *  If VALUE == 0 then KEY clears all flags from \c all and no-KEY sets all
+ *  flags from \c all.  Thus no-none = all and no-all = none.
+ */
+void warning_argmatch (char const *arg, size_t no, size_t err);
+
+/** Decode a comma-separated list of arguments from -W.
+ *
+ *  \param args     comma separated list of effective subarguments to decode.
+ *                  If 0, then activate all the flags.
+ */
+void warnings_argmatch (char *args);
+
+
+/*-----------.
+| complain.  |
+`-----------*/
+
+/** Initialize this module.  */
+void complain_init (void);
+
+typedef enum
+  {
+    /**< Issue no warnings.  */
+    Wnone             = 0,
+
+    Wmidrule_values   = 1 << warning_midrule_values,
+    Wyacc             = 1 << warning_yacc,
+    Wconflicts_sr     = 1 << warning_conflicts_sr,
+    Wconflicts_rr     = 1 << warning_conflicts_rr,
+    Wdeprecated       = 1 << warning_deprecated,
+    Wempty_rule       = 1 << warning_empty_rule,
+    Wprecedence       = 1 << warning_precedence,
+    Wother            = 1 << warning_other,
+
+    Werror            = 1 << 10, /** This bit is no longer used. */
+
+    complaint         = 1 << 11, /**< All complaints.  */
+    fatal             = 1 << 12, /**< All fatal errors.  */
+    silent            = 1 << 13, /**< Do not display the warning type.  */
+    no_caret          = 1 << 14, /**< Do not display caret location.  */
+
+    /**< All above warnings.  */
+    Weverything       = ~complaint & ~fatal & ~silent,
+    Wall              = Weverything & ~Wyacc
+  } warnings;
+
+/** Whether the warnings of \a flags are all unset.
+    (Never enabled, never disabled). */
+bool warning_is_unset (warnings flags);
+
+/** Make a complaint, with maybe a location.  */
+void complain (location const *loc, warnings flags, char const *message, ...)
   __attribute__ ((__format__ (__printf__, 3, 4)));
 
-/** An error, but we continue and die later.  */
+/** Likewise, but with an \a argc/argv interface.  */
+void complain_args (location const *loc, warnings w, unsigned *indent,
+                    int argc, char *arg[]);
 
-void complain (char const *format, ...)
-  __attribute__ ((__format__ (__printf__, 1, 2)));
+/** Make a complaint with location and some indentation.  */
+void complain_indent (location const *loc, warnings flags, unsigned *indent,
+                      char const *message, ...)
+  __attribute__ ((__format__ (__printf__, 4, 5)));
 
-void complain_at (location loc, char const *format, ...)
-  __attribute__ ((__format__ (__printf__, 2, 3)));
 
-/* Generate a message aligned by an indent.
-   When *indent == 0, assign message's indent to *indent,
-   When *indent > 0, align the message by *indent value. */
-void complain_at_indent (location loc, unsigned *indent,
-                         char const *format, ...)
-  __attribute__ ((__format__ (__printf__, 3, 4)));
+/** Report an obsolete syntax, suggest the updated one.  */
+void deprecated_directive (location const *loc,
+                           char const *obsolete, char const *updated);
 
-/** An incompatibility with POSIX Yacc: mapped either to warn* or
-    complain* depending on yacc_flag. */
+/** Report a repeated directive for a rule.  */
+void duplicate_directive (char const *directive,
+                          location first, location second);
 
-void yacc_at (location loc, char const *format, ...)
-  __attribute__ ((__format__ (__printf__, 2, 3)));
-
-/** A midrule-value warning.  Report iff
-    <tt>warnings_flag & warnings_midrule_values</tt>.  */
-
-void midrule_value_at (location loc, char const *format, ...)
-  __attribute__ ((__format__ (__printf__, 2, 3)));
-
-/** A fatal error, causing immediate exit.  */
-
-void fatal (char const *format, ...)
-  __attribute__ ((__noreturn__, __format__ (__printf__, 1, 2)));
-
-void fatal_at (location loc, char const *format, ...)
-  __attribute__ ((__noreturn__, __format__ (__printf__, 2, 3)));
+/** Warnings treated as errors shouldn't stop the execution as regular errors
+    should (because due to their nature, it is safe to go on). Thus, there are
+    three possible execution statuses.  */
+typedef enum
+  {
+    status_none,
+    status_warning_as_error,
+    status_complaint
+  } err_status;
 
 /** Whether an error was reported.  */
-extern bool complaint_issued;
-
-# ifdef        __cplusplus
-}
-# endif
+extern err_status complaint_status;
 
 #endif /* !COMPLAIN_H_ */
index 4e05ab32ab37e48dd8191643b393eb9c70f23690..184047362064d6da09eef800c6eff2967abaf034 100644 (file)
@@ -1,7 +1,7 @@
 /* Find and resolve or report lookahead conflicts for bison,
 
-   Copyright (C) 1984, 1989, 1992, 2000-2007, 2009-2013 Free Software
-   Foundation, Inc.
+   Copyright (C) 1984, 1989, 1992, 2000-2013 Free Software Foundation,
+   Inc.
 
    This file is part of Bison, the GNU Compiler Compiler.
 
@@ -64,75 +64,75 @@ enum conflict_resolution
 
 static inline void
 log_resolution (rule *r, symbol_number token,
-               enum conflict_resolution resolution)
+                enum conflict_resolution resolution)
 {
   if (report_flag & report_solved_conflicts)
     {
       /* The description of the resolution. */
       switch (resolution)
-       {
-       case shift_resolution:
-       case right_resolution:
-         obstack_printf (&solved_conflicts_obstack,
-                         _("    Conflict between rule %d and token %s"
-                           " resolved as shift"),
-                         r->number,
-                         symbols[token]->tag);
-         break;
-
-       case reduce_resolution:
-       case left_resolution:
-         obstack_printf (&solved_conflicts_obstack,
-                         _("    Conflict between rule %d and token %s"
-                           " resolved as reduce"),
-                         r->number,
-                         symbols[token]->tag);
-         break;
-
-       case nonassoc_resolution:
-         obstack_printf (&solved_conflicts_obstack,
-                         _("    Conflict between rule %d and token %s"
-                           " resolved as an error"),
-                         r->number,
-                         symbols[token]->tag);
-         break;
-       }
+        {
+        case shift_resolution:
+        case right_resolution:
+          obstack_printf (&solved_conflicts_obstack,
+                          _("    Conflict between rule %d and token %s"
+                            " resolved as shift"),
+                          r->number,
+                          symbols[token]->tag);
+          break;
+
+        case reduce_resolution:
+        case left_resolution:
+          obstack_printf (&solved_conflicts_obstack,
+                          _("    Conflict between rule %d and token %s"
+                            " resolved as reduce"),
+                          r->number,
+                          symbols[token]->tag);
+          break;
+
+        case nonassoc_resolution:
+          obstack_printf (&solved_conflicts_obstack,
+                          _("    Conflict between rule %d and token %s"
+                            " resolved as an error"),
+                          r->number,
+                          symbols[token]->tag);
+          break;
+        }
 
       /* The reason. */
       switch (resolution)
-       {
-       case shift_resolution:
-         obstack_printf (&solved_conflicts_obstack,
-                         " (%s < %s)",
-                         r->prec->tag,
-                         symbols[token]->tag);
-         break;
-
-       case reduce_resolution:
-         obstack_printf (&solved_conflicts_obstack,
-                         " (%s < %s)",
-                         symbols[token]->tag,
-                         r->prec->tag);
-         break;
-
-       case left_resolution:
-         obstack_printf (&solved_conflicts_obstack,
-                         " (%%left %s)",
-                         symbols[token]->tag);
-         break;
-
-       case right_resolution:
-         obstack_printf (&solved_conflicts_obstack,
-                         " (%%right %s)",
-                         symbols[token]->tag);
-         break;
-
-       case nonassoc_resolution:
-         obstack_printf (&solved_conflicts_obstack,
-                         " (%%nonassoc %s)",
-                         symbols[token]->tag);
-         break;
-       }
+        {
+        case shift_resolution:
+          obstack_printf (&solved_conflicts_obstack,
+                          " (%s < %s)",
+                          r->prec->tag,
+                          symbols[token]->tag);
+          break;
+
+        case reduce_resolution:
+          obstack_printf (&solved_conflicts_obstack,
+                          " (%s < %s)",
+                          symbols[token]->tag,
+                          r->prec->tag);
+          break;
+
+        case left_resolution:
+          obstack_printf (&solved_conflicts_obstack,
+                          " (%%left %s)",
+                          symbols[token]->tag);
+          break;
+
+        case right_resolution:
+          obstack_printf (&solved_conflicts_obstack,
+                          " (%%right %s)",
+                          symbols[token]->tag);
+          break;
+
+        case nonassoc_resolution:
+          obstack_printf (&solved_conflicts_obstack,
+                          " (%%nonassoc %s)",
+                          symbols[token]->tag);
+          break;
+        }
 
       obstack_sgrow (&solved_conflicts_obstack, ".\n");
     }
@@ -226,7 +226,7 @@ flush_shift (state *s, int token)
   bitset_reset (lookahead_set, token);
   for (i = 0; i < trans->num; i++)
     if (!TRANSITION_IS_DISABLED (trans, i)
-       && TRANSITION_SYMBOL (trans, i) == token)
+        && TRANSITION_SYMBOL (trans, i) == token)
       TRANSITION_DISABLE (trans, i);
 }
 
@@ -268,51 +268,61 @@ resolve_sr_conflict (state *s, int ruleno, symbol **errors, int *nerrs)
 
   for (i = 0; i < ntokens; i++)
     if (bitset_test (lookahead_tokens, i)
-       && bitset_test (lookahead_set, i)
-       && symbols[i]->prec)
+        && bitset_test (lookahead_set, i)
+        && symbols[i]->prec)
       {
-       /* Shift-reduce conflict occurs for token number i
-          and it has a precedence.
-          The precedence of shifting is that of token i.  */
-       if (symbols[i]->prec < redprec)
-         {
-           log_resolution (redrule, i, reduce_resolution);
-           flush_shift (s, i);
-         }
-       else if (symbols[i]->prec > redprec)
-         {
-           log_resolution (redrule, i, shift_resolution);
-           flush_reduce (lookahead_tokens, i);
-         }
-       else
-         /* Matching precedence levels.
-            For left association, keep only the reduction.
-            For right association, keep only the shift.
-            For nonassociation, keep neither.  */
-
-         switch (symbols[i]->assoc)
-           {
-           default:
-             abort ();
-
-           case right_assoc:
-             log_resolution (redrule, i, right_resolution);
-             flush_reduce (lookahead_tokens, i);
-             break;
-
-           case left_assoc:
-             log_resolution (redrule, i, left_resolution);
-             flush_shift (s, i);
-             break;
-
-           case non_assoc:
-             log_resolution (redrule, i, nonassoc_resolution);
-             flush_shift (s, i);
-             flush_reduce (lookahead_tokens, i);
-             /* Record an explicit error for this token.  */
-             errors[(*nerrs)++] = symbols[i];
-             break;
-           }
+        /* Shift-reduce conflict occurs for token number i
+           and it has a precedence.
+           The precedence of shifting is that of token i.  */
+        if (symbols[i]->prec < redprec)
+          {
+            register_precedence (redrule->prec->number, i);
+            log_resolution (redrule, i, reduce_resolution);
+            flush_shift (s, i);
+          }
+        else if (symbols[i]->prec > redprec)
+          {
+            register_precedence (i, redrule->prec->number);
+            log_resolution (redrule, i, shift_resolution);
+            flush_reduce (lookahead_tokens, i);
+          }
+        else
+          /* Matching precedence levels.
+             For non-defined associativity, keep both: unexpected
+             associativity conflict.
+             For left associativity, keep only the reduction.
+             For right associativity, keep only the shift.
+             For nonassociativity, keep neither.  */
+
+          switch (symbols[i]->assoc)
+            {
+            case undef_assoc:
+              abort ();
+
+            case precedence_assoc:
+              break;
+
+            case right_assoc:
+              register_assoc (i, redrule->prec->number);
+              log_resolution (redrule, i, right_resolution);
+              flush_reduce (lookahead_tokens, i);
+              break;
+
+            case left_assoc:
+              register_assoc (i, redrule->prec->number);
+              log_resolution (redrule, i, left_resolution);
+              flush_shift (s, i);
+              break;
+
+            case non_assoc:
+              register_assoc (i, redrule->prec->number);
+              log_resolution (redrule, i, nonassoc_resolution);
+              flush_shift (s, i);
+              flush_reduce (lookahead_tokens, i);
+              /* Record an explicit error for this token.  */
+              errors[(*nerrs)++] = symbols[i];
+              break;
+            }
       }
 }
 
@@ -345,7 +355,7 @@ set_conflicts (state *s, symbol **errors)
      precedence.  */
   for (i = 0; i < reds->num; ++i)
     if (reds->rules[i]->prec && reds->rules[i]->prec->prec
-       && !bitset_disjoint_p (reds->lookahead_tokens[i], lookahead_set))
+        && !bitset_disjoint_p (reds->lookahead_tokens[i], lookahead_set))
       resolve_sr_conflict (s, i, errors, &nerrs);
 
   if (nerrs)
@@ -355,22 +365,16 @@ set_conflicts (state *s, symbol **errors)
       state_errs_set (s, nerrs, errors);
     }
   if (obstack_object_size (&solved_conflicts_obstack))
-    {
-      obstack_1grow (&solved_conflicts_obstack, '\0');
-      s->solved_conflicts = obstack_finish (&solved_conflicts_obstack);
-    }
+    s->solved_conflicts = obstack_finish0 (&solved_conflicts_obstack);
   if (obstack_object_size (&solved_conflicts_xml_obstack))
-    {
-      obstack_1grow (&solved_conflicts_xml_obstack, '\0');
-      s->solved_conflicts_xml = obstack_finish (&solved_conflicts_xml_obstack);
-    }
+    s->solved_conflicts_xml = obstack_finish0 (&solved_conflicts_xml_obstack);
 
   /* Loop over all rules which require lookahead in this state.  Check
      for conflicts not resolved above.  */
   for (i = 0; i < reds->num; ++i)
     {
       if (!bitset_disjoint_p (reds->lookahead_tokens[i], lookahead_set))
-       conflicts[s->number] = 1;
+        conflicts[s->number] = 1;
       bitset_or (lookahead_set, lookahead_set, reds->lookahead_tokens[i]);
     }
 }
@@ -399,9 +403,9 @@ conflicts_solve (void)
       set_conflicts (states[i], errors);
 
       /* For uniformity of the code, make sure all the states have a valid
-        `errs' member.  */
+         'errs' member.  */
       if (!states[i]->errs)
-       states[i]->errs = errs_new (0, 0);
+        states[i]->errs = errs_new (0, 0);
     }
 
   free (errors);
@@ -423,11 +427,10 @@ conflicts_update_state_numbers (state_number old_to_new[],
 | Count the number of shift/reduce conflicts.  |
 `---------------------------------------------*/
 
-static int
-count_sr_conflicts (state *s)
+static size_t
+count_state_sr_conflicts (state *s)
 {
   int i;
-  int src_count = 0;
   transitions *trans = s->transitions;
   reductions *reds = s->reductions;
 
@@ -445,56 +448,66 @@ count_sr_conflicts (state *s)
 
   bitset_and (lookahead_set, lookahead_set, shift_set);
 
-  src_count = bitset_count (lookahead_set);
+  return bitset_count (lookahead_set);
+}
+
+/*---------------------------------------------.
+| The total number of shift/reduce conflicts.  |
+`---------------------------------------------*/
 
-  return src_count;
+static size_t
+count_sr_conflicts (void)
+{
+  size_t res = 0;
+  state_number i;
+
+  /* Conflicts by state.  */
+  for (i = 0; i < nstates; i++)
+    if (conflicts[i])
+      res += count_state_sr_conflicts (states[i]);
+  return res;
 }
 
 
+
 /*----------------------------------------------------------------.
 | Count the number of reduce/reduce conflicts.  If ONE_PER_TOKEN, |
 | count one conflict for each token that has any reduce/reduce    |
 | conflicts.  Otherwise, count one conflict for each pair of      |
 | conflicting reductions.                                         |
-+`----------------------------------------------------------------*/
+`----------------------------------------------------------------*/
 
-static int
-count_rr_conflicts (state *s, bool one_per_token)
+static size_t
+count_state_rr_conflicts (state *s, bool one_per_token)
 {
   int i;
   reductions *reds = s->reductions;
-  int rrc_count = 0;
+  size_t res = 0;
 
   for (i = 0; i < ntokens; i++)
     {
       int count = 0;
       int j;
       for (j = 0; j < reds->num; ++j)
-       if (bitset_test (reds->lookahead_tokens[j], i))
-         count++;
-
+        count += bitset_test (reds->lookahead_tokens[j], i);
       if (count >= 2)
-       rrc_count += one_per_token ? 1 : count-1;
+        res += one_per_token ? 1 : count-1;
     }
 
-  return rrc_count;
+  return res;
 }
 
-
-/*--------------------------------------------------------.
-| Report the number of conflicts, using the Yacc format.  |
-`--------------------------------------------------------*/
-
-static void
-conflict_report (FILE *out, int src_num, int rrc_num)
+static size_t
+count_rr_conflicts (bool one_per_token)
 {
-  if (src_num && rrc_num)
-    fprintf (out, _("conflicts: %d shift/reduce, %d reduce/reduce\n"),
-            src_num, rrc_num);
-  else if (src_num)
-    fprintf (out, _("conflicts: %d shift/reduce\n"), src_num);
-  else if (rrc_num)
-    fprintf (out, _("conflicts: %d reduce/reduce\n"), rrc_num);
+  size_t res = 0;
+  state_number i;
+
+  /* Conflicts by state.  */
+  for (i = 0; i < nstates; i++)
+    if (conflicts[i])
+      res += count_state_rr_conflicts (states[i], one_per_token);
+  return res;
 }
 
 
@@ -511,12 +524,20 @@ conflicts_output (FILE *out)
     {
       state *s = states[i];
       if (conflicts[i])
-       {
-         fprintf (out, _("State %d "), i);
-         conflict_report (out, count_sr_conflicts (s),
-                          count_rr_conflicts (s, true));
-         printed_sth = true;
-       }
+        {
+          int src = count_state_sr_conflicts (s);
+          int rrc = count_state_rr_conflicts (s, true);
+          fprintf (out, _("State %d "), i);
+          if (src && rrc)
+            fprintf (out,
+                     _("conflicts: %d shift/reduce, %d reduce/reduce\n"),
+                     src, rrc);
+          else if (src)
+            fprintf (out, _("conflicts: %d shift/reduce\n"), src);
+          else if (rrc)
+            fprintf (out, _("conflicts: %d reduce/reduce\n"), rrc);
+          printed_sth = true;
+        }
     }
   if (printed_sth)
     fputs ("\n\n", out);
@@ -526,24 +547,13 @@ conflicts_output (FILE *out)
 | Total the number of S/R and R/R conflicts.  Unlike the  |
 | code in conflicts_output, however, count EACH pair of   |
 | reductions for the same state and lookahead as one      |
-| conflict.                                              |
+| conflict.                                               |
 `--------------------------------------------------------*/
 
 int
 conflicts_total_count (void)
 {
-  state_number i;
-  int count;
-
-  /* Conflicts by state.  */
-  count = 0;
-  for (i = 0; i < nstates; i++)
-    if (conflicts[i])
-      {
-       count += count_sr_conflicts (states[i]);
-       count += count_rr_conflicts (states[i], false);
-      }
-  return count;
+  return count_sr_conflicts () + count_rr_conflicts (false);
 }
 
 
@@ -554,75 +564,57 @@ conflicts_total_count (void)
 void
 conflicts_print (void)
 {
-  /* Is the number of SR conflicts OK?  Either EXPECTED_CONFLICTS is
-     not set, and then we want 0 SR, or else it is specified, in which
-     case we want equality.  */
-  bool src_ok;
-  bool rrc_ok;
-
-  int src_total = 0;
-  int rrc_total = 0;
-  int src_expected;
-  int rrc_expected;
-
-  /* Conflicts by state.  */
-  {
-    state_number i;
-
-    for (i = 0; i < nstates; i++)
-      if (conflicts[i])
-       {
-         src_total += count_sr_conflicts (states[i]);
-         rrc_total += count_rr_conflicts (states[i], true);
-       }
-  }
-
-  if (! glr_parser && rrc_total > 0 && expected_rr_conflicts != -1)
+  if (! glr_parser && expected_rr_conflicts != -1)
     {
-      warn (_("%%expect-rr applies only to GLR parsers"));
+      complain (NULL, Wother, _("%%expect-rr applies only to GLR parsers"));
       expected_rr_conflicts = -1;
     }
 
-  src_expected = expected_sr_conflicts == -1 ? 0 : expected_sr_conflicts;
-  rrc_expected = expected_rr_conflicts == -1 ? 0 : expected_rr_conflicts;
-  src_ok = src_total == src_expected;
-  rrc_ok = rrc_total == rrc_expected;
-
-  /* If there are as many RR conflicts and SR conflicts as
-     expected, then there is nothing to report.  */
-  if (rrc_ok & src_ok)
-    return;
-
-  /* Report the total number of conflicts on STDERR.  */
-  if (expected_sr_conflicts == -1 && expected_rr_conflicts == -1)
-    {
-      if (!(warnings_flag & warnings_conflicts_sr))
-        src_total = 0;
-      if (!(warnings_flag & warnings_conflicts_rr))
-        rrc_total = 0;
-    }
-  if (src_total | rrc_total)
-    {
-      if (expected_sr_conflicts == -1 && expected_rr_conflicts == -1)
-        set_warning_issued ();
-      if (! yacc_flag)
-       fprintf (stderr, "%s: ", current_file);
-      conflict_report (stderr, src_total, rrc_total);
-    }
+  /* Screams for factoring, but almost useless because of the
+     different strings to translate.  */
+  {
+    int total = count_sr_conflicts ();
+    /* If %expect is not used, but %expect-rr is, then expect 0 sr.  */
+    int expected =
+      (expected_sr_conflicts == -1 && expected_rr_conflicts != -1)
+      ? 0
+      : expected_sr_conflicts;
+    if (expected != -1)
+      {
+        if (expected != total)
+          complain (NULL, complaint,
+                    _("shift/reduce conflicts: %d found, %d expected"),
+                    total, expected);
+      }
+    else if (total)
+      complain (NULL, Wconflicts_sr,
+                ngettext ("%d shift/reduce conflict",
+                          "%d shift/reduce conflicts",
+                          total),
+                total);
+  }
 
-  if (expected_sr_conflicts != -1 || expected_rr_conflicts != -1)
-    {
-      if (! src_ok)
-       complain (ngettext ("expected %d shift/reduce conflict",
-                           "expected %d shift/reduce conflicts",
-                           src_expected),
-                 src_expected);
-      if (! rrc_ok)
-       complain (ngettext ("expected %d reduce/reduce conflict",
-                           "expected %d reduce/reduce conflicts",
-                           rrc_expected),
-                 rrc_expected);
-    }
+  {
+    int total = count_rr_conflicts (true);
+    /* If %expect-rr is not used, but %expect is, then expect 0 rr.  */
+    int expected =
+      (expected_rr_conflicts == -1 && expected_sr_conflicts != -1)
+      ? 0
+      : expected_rr_conflicts;
+    if (expected != -1)
+      {
+        if (expected != total)
+          complain (NULL, complaint,
+                    _("reduce/reduce conflicts: %d found, %d expected"),
+                    total, expected);
+      }
+    else if (total)
+      complain (NULL, Wconflicts_rr,
+                ngettext ("%d reduce/reduce conflict",
+                          "%d reduce/reduce conflicts",
+                          total),
+                total);
+  }
 }
 
 
index 1f9bbc5ee9ae47ed8cab75920d5645bae9423232..c834f0b0d0941fe81542ba396602b546b8cc3e24 100644 (file)
@@ -47,12 +47,13 @@ print_derives (void)
   for (i = ntokens; i < nsyms; i++)
     {
       rule **rp;
-      fprintf (stderr, "\t%s derives\n", symbols[i]->tag);
+      fprintf (stderr, "  %s derives\n", symbols[i]->tag);
       for (rp = derives[i - ntokens]; *rp; ++rp)
-       {
-         fprintf (stderr, "\t\t%3d ", (*rp)->user_number);
-         rule_rhs_print (*rp, stderr);
-       }
+        {
+          fprintf (stderr, "    %3d ", (*rp)->user_number);
+          rule_rhs_print (*rp, stderr);
+          fprintf (stderr, "\n");
+        }
     }
 
   fputs ("\n\n", stderr);
@@ -96,10 +97,10 @@ derives_compute (void)
       rule_list *p = dset[i - ntokens];
       derives[i - ntokens] = q;
       while (p)
-       {
-         *q++ = p->value;
-         p = p->next;
-       }
+        {
+          *q++ = p->value;
+          p = p->next;
+        }
       *q++ = NULL;
     }
 
index 7b7a1918c30dcfb71ae2c58bf2fd15e0e1645fb6..76aa7fe3dfbe0a42de961cc179d2115f5a1e7177 100644 (file)
@@ -34,7 +34,7 @@
 #include "getargs.h"
 #include "gram.h"
 
-/* Initializing some values below (such SPEC_NAME_PREFIX to `yy') is
+/* Initializing some values below (such SPEC_NAME_PREFIX to 'yy') is
    tempting, but don't do that: for the time being our handling of the
    %directive vs --option leaves precedence to the options by deciding
    that if a %directive sets a variable which is really set (i.e., not
@@ -58,20 +58,20 @@ uniqstr grammar_file = NULL;
 uniqstr current_file = NULL;
 
 /* If --output=dir/foo.c was specified,
-   DIR_PREFIX is `dir/' and ALL_BUT_EXT and ALL_BUT_TAB_EXT are `dir/foo'.
+   DIR_PREFIX is 'dir/' and ALL_BUT_EXT and ALL_BUT_TAB_EXT are 'dir/foo'.
 
-   If --output=dir/foo.tab.c was specified, DIR_PREFIX is `dir/',
-   ALL_BUT_EXT is `dir/foo.tab', and ALL_BUT_TAB_EXT is `dir/foo'.
+   If --output=dir/foo.tab.c was specified, DIR_PREFIX is 'dir/',
+   ALL_BUT_EXT is 'dir/foo.tab', and ALL_BUT_TAB_EXT is 'dir/foo'.
 
    If --output was not specified but --file-prefix=dir/foo was specified,
-   ALL_BUT_EXT = `foo.tab' and ALL_BUT_TAB_EXT = `foo'.
+   ALL_BUT_EXT = 'foo.tab' and ALL_BUT_TAB_EXT = 'foo'.
 
    If neither --output nor --file was specified but the input grammar
-   is name dir/foo.y, ALL_BUT_EXT and ALL_BUT_TAB_EXT are `foo'.
+   is name dir/foo.y, ALL_BUT_EXT and ALL_BUT_TAB_EXT are 'foo'.
 
    If neither --output nor --file was specified, DIR_PREFIX is the
    empty string (meaning the current directory); otherwise it is
-   `dir/'.  */
+   'dir/'.  */
 
 char *all_but_ext;
 static char *all_but_tab_ext;
@@ -79,7 +79,7 @@ char *dir_prefix;
 
 /* C source file extension (the parser source).  */
 static char *src_extension = NULL;
-/* Header file extension (if option ``-d'' is specified).  */
+/* Header file extension (if option '`-d'' is specified).  */
 static char *header_extension = NULL;
 \f
 /*-----------------------------------------------------------------.
@@ -134,6 +134,18 @@ xfclose (FILE *ptr)
 }
 \f
 
+FILE *
+xfdopen (int fd, char const *mode)
+{
+  FILE *res = fdopen (fd, mode);
+  if (! res)
+    error (EXIT_FAILURE, get_errno (),
+           /* On a separate line to please the "unmarked_diagnostics"
+              syntax-check. */
+           "fdopen");
+  return res;
+}
+
 /*------------------------------------------------------------------.
 | Compute ALL_BUT_EXT, ALL_BUT_TAB_EXT and output files extensions. |
 `------------------------------------------------------------------*/
@@ -142,7 +154,7 @@ xfclose (FILE *ptr)
 static void
 compute_exts_from_gf (const char *ext)
 {
-  if (strcmp (ext, ".y") == 0)
+  if (STREQ (ext, ".y"))
     {
       src_extension = xstrdup (language->src_extension);
       header_extension = xstrdup (language->header_extension);
@@ -179,7 +191,7 @@ compute_exts_from_src (const char *ext)
    *EXT points to the last period in the basename, or NULL if none.
 
    If there is no *EXT, *TAB is NULL.  Otherwise, *TAB points to
-   `.tab' or `_tab' if present right before *EXT, or is NULL. *TAB
+   '.tab' or '_tab' if present right before *EXT, or is NULL. *TAB
    cannot be equal to *BASE.
 
    None are allocated, they are simply pointers to parts of FILE_NAME.
@@ -202,24 +214,23 @@ compute_exts_from_src (const char *ext)
 
 static void
 file_name_split (const char *file_name,
-                const char **base, const char **tab, const char **ext)
+                 const char **base, const char **tab, const char **ext)
 {
   *base = last_component (file_name);
 
   /* Look for the extension, i.e., look for the last dot. */
-  *ext = mbsrchr (*base, '.');
+  *ext = strrchr (*base, '.');
   *tab = NULL;
 
-  /* If there is an extension, check if there is a `.tab' part right
+  /* If there is an extension, check if there is a '.tab' part right
      before.  */
   if (*ext)
     {
       size_t baselen = *ext - *base;
-      size_t dottablen = 4;
+      size_t dottablen = sizeof (TAB_EXT) - 1;
       if (dottablen < baselen
-         && (strncmp (*ext - dottablen, ".tab", dottablen) == 0
-             || strncmp (*ext - dottablen, "_tab", dottablen) == 0))
-       *tab = *ext - dottablen;
+          && STRPREFIX_LIT (TAB_EXT, *ext - dottablen))
+        *tab = *ext - dottablen;
     }
 }
 
@@ -241,44 +252,44 @@ compute_file_name_parts (void)
 
       /* ALL_BUT_EXT goes up the EXT, excluding it. */
       all_but_ext =
-       xstrndup (spec_outfile,
-                 (strlen (spec_outfile) - (ext ? strlen (ext) : 0)));
+        xstrndup (spec_outfile,
+                  (strlen (spec_outfile) - (ext ? strlen (ext) : 0)));
 
       /* ALL_BUT_TAB_EXT goes up to TAB, excluding it.  */
       all_but_tab_ext =
-       xstrndup (spec_outfile,
-                 (strlen (spec_outfile)
-                  - (tab ? strlen (tab) : (ext ? strlen (ext) : 0))));
+        xstrndup (spec_outfile,
+                  (strlen (spec_outfile)
+                   - (tab ? strlen (tab) : (ext ? strlen (ext) : 0))));
 
       if (ext)
-       compute_exts_from_src (ext);
+        compute_exts_from_src (ext);
     }
   else
     {
       file_name_split (grammar_file, &base, &tab, &ext);
 
       if (spec_file_prefix)
-       {
-         /* If --file-prefix=foo was specified, ALL_BUT_TAB_EXT = `foo'.  */
-         dir_prefix =
+        {
+          /* If --file-prefix=foo was specified, ALL_BUT_TAB_EXT = 'foo'.  */
+          dir_prefix =
             xstrndup (spec_file_prefix,
                       last_component (spec_file_prefix) - spec_file_prefix);
-         all_but_tab_ext = xstrdup (spec_file_prefix);
-       }
+          all_but_tab_ext = xstrdup (spec_file_prefix);
+        }
       else if (yacc_flag)
-       {
-         /* If --yacc, then the output is `y.tab.c'.  */
-         dir_prefix = xstrdup ("");
-         all_but_tab_ext = xstrdup ("y");
-       }
+        {
+          /* If --yacc, then the output is 'y.tab.c'.  */
+          dir_prefix = xstrdup ("");
+          all_but_tab_ext = xstrdup ("y");
+        }
       else
-       {
-         /* Otherwise, ALL_BUT_TAB_EXT is computed from the input
-            grammar: `foo/bar.yy' => `bar'.  */
-         dir_prefix = xstrdup ("");
-         all_but_tab_ext =
-           xstrndup (base, (strlen (base) - (ext ? strlen (ext) : 0)));
-       }
+        {
+          /* Otherwise, ALL_BUT_TAB_EXT is computed from the input
+             grammar: 'foo/bar.yy' => 'bar'.  */
+          dir_prefix = xstrdup ("");
+          all_but_tab_ext =
+            xstrndup (base, (strlen (base) - (ext ? strlen (ext) : 0)));
+        }
 
       if (language->add_tab)
         all_but_ext = concat2 (all_but_tab_ext, TAB_EXT);
@@ -287,7 +298,7 @@ compute_file_name_parts (void)
 
       /* Compute the extensions from the grammar file name.  */
       if (ext && !yacc_flag)
-       compute_exts_from_gf (ext);
+        compute_exts_from_gf (ext);
     }
 }
 
@@ -314,20 +325,20 @@ compute_output_file_names (void)
   if (defines_flag)
     {
       if (! spec_defines_file)
-       spec_defines_file = concat2 (all_but_ext, header_extension);
+        spec_defines_file = concat2 (all_but_ext, header_extension);
     }
 
   if (graph_flag)
     {
       if (! spec_graph_file)
-       spec_graph_file = concat2 (all_but_tab_ext, ".dot");
+        spec_graph_file = concat2 (all_but_tab_ext, ".dot");
       output_file_name_check (&spec_graph_file);
     }
 
   if (xml_flag)
     {
       if (! spec_xml_file)
-       spec_xml_file = concat2 (all_but_tab_ext, ".xml");
+        spec_xml_file = concat2 (all_but_tab_ext, ".xml");
       output_file_name_check (&spec_xml_file);
     }
 
@@ -347,9 +358,9 @@ void
 output_file_name_check (char **file_name)
 {
   bool conflict = false;
-  if (0 == strcmp (*file_name, grammar_file))
+  if (STREQ (*file_name, grammar_file))
     {
-      complain (_("refusing to overwrite the input file %s"),
+      complain (NULL, complaint, _("refusing to overwrite the input file %s"),
                 quote (*file_name));
       conflict = true;
     }
@@ -357,10 +368,10 @@ output_file_name_check (char **file_name)
     {
       int i;
       for (i = 0; i < file_names_count; i++)
-        if (0 == strcmp (file_names[i], *file_name))
+        if (STREQ (file_names[i], *file_name))
           {
-            warn (_("conflicting outputs to file %s"),
-                  quote (*file_name));
+            complain (NULL, Wother, _("conflicting outputs to file %s"),
+                      quote (*file_name));
             conflict = true;
           }
     }
index ccc8870148911315f95bba05a3e2d4b030d8ef21..ebe5037c7ac277ab3f7e01d2d472f5fc32ad87e5 100644 (file)
@@ -65,7 +65,8 @@ void compute_output_file_names (void);
 void output_file_names_free (void);
 void output_file_name_check (char **file_name);
 
-FILE *xfopen (const char *name, const char *mode);
+FILE *xfopen (const char *name, char const *mode);
 void xfclose (FILE *ptr);
+FILE *xfdopen (int fd, char const *mode);
 
 #endif /* !FILES_H_ */
index f56b3f70ea43a243aae2835cbfc8f2b402a84252..d72986e8126664d0b4efde3fa836294cd4cc8d45 100644 (file)
@@ -28,7 +28,7 @@
    + (YY_FLEX_SUBMINOR_VERSION))
 
 /* Pacify "gcc -Wmissing-prototypes" when flex 2.5.31 is used.  */
-# if FLEX_VERSION <= 2005031
+#if FLEX_VERSION <= 2005031
 int   FLEX_PREFIX (get_lineno) (void);
 FILE *FLEX_PREFIX (get_in) (void);
 FILE *FLEX_PREFIX (get_out) (void);
@@ -76,16 +76,13 @@ int   FLEX_PREFIX (lex_destroy) (void);
 
 static struct obstack obstack_for_string;
 
-# define STRING_GROW   \
+# define STRING_GROW                                    \
   obstack_grow (&obstack_for_string, yytext, yyleng)
 
-# define STRING_FINISH                                 \
-  do {                                                 \
-    obstack_1grow (&obstack_for_string, '\0');         \
-    last_string = obstack_finish (&obstack_for_string);        \
-  } while (0)
+# define STRING_FINISH                                  \
+  (last_string = obstack_finish0 (&obstack_for_string))
 
-# define STRING_FREE \
+# define STRING_FREE                                    \
   obstack_free (&obstack_for_string, last_string)
 
 #endif
index 94197f86fc11c565841fc53bcf84eda188743bbd..e6f9d766db7afb5f14fc0e5d5a11b1611cbb17a6 100644 (file)
 #include <c-strcase.h>
 #include <configmake.h>
 #include <error.h>
-
-/* Hack to get <getopt.h> to declare getopt with a prototype.  */
-#if lint && ! defined __GNU_LIBRARY__
-# define __GNU_LIBRARY__
-# define HACK_FOR___GNU_LIBRARY___PROTOTYPE 1
-#endif
-
 #include <getopt.h>
-
-#ifdef HACK_FOR___GNU_LIBRARY___PROTOTYPE
-# undef __GNU_LIBRARY__
-# undef HACK_FOR___GNU_LIBRARY___PROTOTYPE
-#endif
-
 #include <progname.h>
 
 #include "complain.h"
 #include "quote.h"
 #include "uniqstr.h"
 
-bool debug;
 bool defines_flag;
 bool graph_flag;
 bool xml_flag;
-bool locations_flag;
 bool no_lines_flag;
 bool token_table_flag;
-bool yacc_flag;        /* for -y */
-
-bool error_verbose = false;
+bool yacc_flag; /* for -y */
 
 bool nondeterministic_parser = false;
 bool glr_parser = false;
 
-int feature_flag = feature_none;
+int feature_flag = feature_caret;
 int report_flag = report_none;
 int trace_flag = trace_none;
-int warnings_flag = warnings_conflicts_sr | warnings_conflicts_rr
-                    | warnings_other;
 
 static struct bison_language const valid_languages[] = {
   { "c", "c-skel.m4", ".c", ".h", true },
@@ -82,67 +63,82 @@ int language_prio = default_prio;
 struct bison_language const *language = &valid_languages[0];
 const char *include = NULL;
 
-
-/** Decode an option's set of keys.
+/** Decode an option's key.
  *
  *  \param option   option being decoded.
  *  \param keys     array of valid subarguments.
  *  \param values   array of corresponding (int) values.
  *  \param all      the all value.
  *  \param flags    the flags to update
- *  \param args     comma separated list of effective subarguments to decode.
- *                  If 0, then activate all the flags.
+ *  \param arg      the subarguments to decode.
+ *                  If null, then activate all the flags.
+ *  \param no       length of the potential "no-" prefix.
+ *                  Can be 0 or 3. If 3, negate the action of the subargument.
  *
  *  If VALUE != 0 then KEY sets flags and no-KEY clears them.
  *  If VALUE == 0 then KEY clears all flags from \c all and no-KEY sets all
  *  flags from \c all.  Thus no-none = all and no-all = none.
  */
 static void
-flags_argmatch (const char *option,
-               const char * const keys[], const int values[],
-               int all, int *flags, char *args)
+flag_argmatch (const char *option,
+               const char * const keys[], const int values[],
+               int all, int *flags, char *arg, size_t no)
 {
-  if (args)
+  int value = XARGMATCH (option, arg + no, keys, values);
+
+  /* -rnone == -rno-all, and -rno-none == -rall.  */
+  if (!value)
     {
-      args = strtok (args, ",");
-      while (args)
-       {
-         int no = strncmp (args, "no-", 3) == 0 ? 3 : 0;
-         int value = XARGMATCH (option, args + no, keys, values);
-         if (value == 0)
-           {
-             if (no)
-               *flags |= all;
-             else
-               *flags &= ~all;
-           }
-         else
-           {
-             if (no)
-               *flags &= ~value;
-             else
-               *flags |= value;
-           }
-         args = strtok (NULL, ",");
-       }
+      value = all;
+      no = !no;
     }
+
+  if (no)
+    *flags &= ~value;
+  else
+    *flags |= value;
+}
+
+/** Decode an option's set of keys.
+ *
+ *  \param option   option being decoded.
+ *  \param keys     array of valid subarguments.
+ *  \param values   array of corresponding (int) values.
+ *  \param all      the all value.
+ *  \param flags    the flags to update
+ *  \param args     comma separated list of effective subarguments to decode.
+ *                  If 0, then activate all the flags.
+ */
+static void
+flags_argmatch (const char *option,
+                const char * const keys[], const int values[],
+                int all, int *flags, char *args)
+{
+  if (args)
+    for (args = strtok (args, ","); args; args = strtok (NULL, ","))
+      {
+        size_t no = STRPREFIX_LIT ("no-", args) ? 3 : 0;
+        flag_argmatch (option, keys,
+                       values, all, flags, args, no);
+      }
   else
     *flags |= all;
 }
 
+
 /** Decode a set of sub arguments.
  *
  *  \param FlagName  the flag familly to update.
  *  \param Args      the effective sub arguments to decode.
+ *  \param All       the "all" value.
  *
  *  \arg FlagName_args   the list of keys.
  *  \arg FlagName_types  the list of values.
- *  \arg FlagName_all    the all value.
  *  \arg FlagName_flag   the flag to update.
  */
-#define FLAGS_ARGMATCH(FlagName, Args)                                 \
+#define FLAGS_ARGMATCH(FlagName, Args, All)                             \
   flags_argmatch ("--" #FlagName, FlagName ## _args, FlagName ## _types, \
-                 FlagName ## _all, &FlagName ## _flag, Args)
+                  All, &FlagName ## _flag, Args)
 
 
 /*----------------------.
@@ -183,8 +179,6 @@ ARGMATCH_VERIFY (report_args, report_types);
 
 static const char * const trace_args[] =
 {
-  /* In a series of synonyms, present the most meaningful first, so
-     that argmatch_valid be more readable.  */
   "none       - no traces",
   "scan       - grammar scanner traces",
   "parse      - grammar parser traces",
@@ -225,39 +219,6 @@ static const int trace_types[] =
 ARGMATCH_VERIFY (trace_args, trace_types);
 
 
-/*------------------------.
-| --warnings's handling.  |
-`------------------------*/
-
-static const char * const warnings_args[] =
-{
-  /* In a series of synonyms, present the most meaningful first, so
-     that argmatch_valid be more readable.  */
-  "none            - no warnings",
-  "midrule-values  - unset or unused midrule values",
-  "yacc            - incompatibilities with POSIX Yacc",
-  "conflicts-sr    - S/R conflicts",
-  "conflicts-rr    - R/R conflicts",
-  "other           - all other warnings",
-  "all             - all of the above",
-  "error           - warnings are errors",
-  0
-};
-
-static const int warnings_types[] =
-{
-  warnings_none,
-  warnings_midrule_values,
-  warnings_yacc,
-  warnings_conflicts_sr,
-  warnings_conflicts_rr,
-  warnings_other,
-  warnings_all,
-  warnings_error
-};
-
-ARGMATCH_VERIFY (warnings_args, warnings_types);
-
 /*-----------------------.
 | --feature's handling.  |
 `-----------------------*/
@@ -289,14 +250,14 @@ static void
 usage (int status)
 {
   if (status != 0)
-    fprintf (stderr, _("Try `%s --help' for more information.\n"),
-            program_name);
+    fprintf (stderr, _("Try '%s --help' for more information.\n"),
+             program_name);
   else
     {
       /* For ../build-aux/cross-options.pl to work, use the format:
-               ^  -S, --long[=ARGS] (whitespace)
-        A --long option is required.
-        Otherwise, add exceptions to ../build-aux/cross-options.pl.  */
+                ^  -S, --long[=ARGS] (whitespace)
+         A --long option is required.
+         Otherwise, add exceptions to ../build-aux/cross-options.pl.  */
 
       printf (_("Usage: %s [OPTION]... FILE\n"), program_name);
       fputs (_("\
@@ -330,7 +291,8 @@ Operation modes:\n\
 Parser:\n\
   -L, --language=LANGUAGE          specify the output programming language\n\
   -S, --skeleton=FILE              specify the skeleton to use\n\
-  -t, --debug                      instrument the parser for debugging\n\
+  -t, --debug                      instrument the parser for tracing\n\
+                                   same as '-Dparse.trace'\n\
       --locations                  enable location support\n\
   -D, --define=NAME[=VALUE]        similar to '%define NAME \"VALUE\"'\n\
   -F, --force-define=NAME[=VALUE]  override '%define NAME \"VALUE\"'\n\
@@ -349,7 +311,7 @@ Output:\n\
   -d                         likewise but cannot specify FILE (for POSIX Yacc)\n\
   -r, --report=THINGS        also produce details on the automaton\n\
       --report-file=FILE     write report to FILE\n\
-  -v, --verbose              same as `--report=state'\n\
+  -v, --verbose              same as '--report=state'\n\
   -b, --file-prefix=PREFIX   specify a PREFIX for output files\n\
   -o, --output=FILE          leave output to FILE\n\
   -g, --graph[=FILE]         also output a graph of the automaton\n\
@@ -360,35 +322,37 @@ Output:\n\
 
       fputs (_("\
 Warning categories include:\n\
-  `midrule-values'  unset or unused midrule values\n\
-  `yacc'            incompatibilities with POSIX Yacc\n\
-  `conflicts-sr'    S/R conflicts (enabled by default)\n\
-  `conflicts-rr'    R/R conflicts (enabled by default)\n\
-  `deprecated'      obsolete constructs\n\
-  `other'           all other warnings (enabled by default)\n\
-  `all'             all the warnings\n\
-  `no-CATEGORY'     turn off warnings in CATEGORY\n\
-  `none'            turn off all the warnings\n\
-  `error'           treat warnings as errors\n\
+  'midrule-values'    unset or unused midrule values\n\
+  'yacc'              incompatibilities with POSIX Yacc\n\
+  'conflicts-sr'      S/R conflicts (enabled by default)\n\
+  'conflicts-rr'      R/R conflicts (enabled by default)\n\
+  'deprecated'        obsolete constructs\n\
+  'empty-rule'        empty rules without %empty\n\
+  'precedence'        useless precedence and associativity\n\
+  'other'             all other warnings (enabled by default)\n\
+  'all'               all the warnings except 'yacc'\n\
+  'no-CATEGORY'       turn off warnings in CATEGORY\n\
+  'none'              turn off all the warnings\n\
+  'error[=CATEGORY]'  treat warnings as errors\n\
 "), stdout);
       putc ('\n', stdout);
 
       fputs (_("\
 THINGS is a list of comma separated words that can include:\n\
-  `state'        describe the states\n\
-  `itemset'      complete the core item sets with their closure\n\
-  `lookahead'    explicitly associate lookahead tokens to items\n\
-  `solved'       describe shift/reduce conflicts solving\n\
-  `all'          include all the above information\n\
-  `none'         disable the report\n\
+  'state'        describe the states\n\
+  'itemset'      complete the core item sets with their closure\n\
+  'lookahead'    explicitly associate lookahead tokens to items\n\
+  'solved'       describe shift/reduce conflicts solving\n\
+  'all'          include all the above information\n\
+  'none'         disable the report\n\
 "), stdout);
       putc ('\n', stdout);
 
       fputs (_("\
 FEATURE is a list of comma separated words that can include:\n\
-  `caret'        show errors with carets\n\
-  `all'          all of the above\n\
-  `none'         disable all of the above\n\
+  'caret'        show errors with carets\n\
+  'all'          all of the above\n\
+  'none'         disable all of the above\n\
   "), stdout);
 
       putc ('\n', stdout);
@@ -401,7 +365,7 @@ FEATURE is a list of comma separated words that can include:\n\
          Note we still output for 'C' so that it gets included in the
          man page.  */
       const char *lc_messages = setlocale (LC_MESSAGES, NULL);
-      if (lc_messages && strcmp (lc_messages, "en_"))
+      if (lc_messages && !STREQ (lc_messages, "en_"))
         /* TRANSLATORS: Replace LANG_CODE in this URL with your language
            code <http://translationproject.org/team/LANG_CODE.html> to
            form one of the URLs at http://translationproject.org/team/.
@@ -431,14 +395,14 @@ version (void)
   putc ('\n', stdout);
 
   fprintf (stdout,
-          _("Copyright (C) %d Free Software Foundation, Inc.\n"),
-          PACKAGE_COPYRIGHT_YEAR);
+           _("Copyright (C) %d Free Software Foundation, Inc.\n"),
+           PACKAGE_COPYRIGHT_YEAR);
 
   fputs (_("\
 This is free software; see the source for copying conditions.  There is NO\n\
 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
 "),
-        stdout);
+         stdout);
 }
 
 
@@ -455,7 +419,8 @@ skeleton_arg (char const *arg, int prio, location loc)
       skeleton = arg;
     }
   else if (prio == skeleton_prio)
-    complain_at (loc, _("multiple skeleton declarations are invalid"));
+    complain (&loc, complaint,
+              _("multiple skeleton declarations are invalid"));
 }
 
 void
@@ -480,7 +445,7 @@ language_argmatch (char const *arg, int prio, location loc)
   else
     return;
 
-  complain_at (loc, msg, quotearg_colon (arg));
+  complain (&loc, complaint, msg, quotearg_colon (arg));
 }
 
 /*----------------------.
@@ -527,25 +492,25 @@ enum
 static struct option const long_options[] =
 {
   /* Operation modes. */
-  { "help",            no_argument,      0,   'h' },
-  { "version",         no_argument,      0,   'V' },
-  { "print-localedir", no_argument,      0,   PRINT_LOCALEDIR_OPTION },
-  { "print-datadir",   no_argument,      0,   PRINT_DATADIR_OPTION   },
+  { "help",            no_argument,       0,   'h' },
+  { "version",         no_argument,       0,   'V' },
+  { "print-localedir", no_argument,       0,   PRINT_LOCALEDIR_OPTION },
+  { "print-datadir",   no_argument,       0,   PRINT_DATADIR_OPTION   },
   { "warnings",        optional_argument, 0,   'W' },
 
   /* Parser. */
-  { "name-prefix",   required_argument,          0,   'p' },
+  { "name-prefix",   required_argument,   0,   'p' },
   { "include",       required_argument,   0,   'I' },
 
   /* Output. */
-  { "file-prefix", required_argument,  0,   'b' },
-  { "output",     required_argument,   0,   'o' },
-  { "output-file", required_argument,  0,   'o' },
-  { "graph",      optional_argument,   0,   'g' },
+  { "file-prefix", required_argument,   0,   'b' },
+  { "output",      required_argument,   0,   'o' },
+  { "output-file", required_argument,   0,   'o' },
+  { "graph",       optional_argument,   0,   'g' },
   { "xml",         optional_argument,   0,   'x' },
-  { "report",     required_argument,   0,   'r' },
+  { "report",      required_argument,   0,   'r' },
   { "report-file", required_argument,   0,   REPORT_FILE_OPTION },
-  { "verbose",    no_argument,         0,   'v' },
+  { "verbose",     no_argument,         0,   'v' },
 
   /* Hidden. */
   { "trace",         optional_argument,   0,     'T' },
@@ -556,13 +521,13 @@ static struct option const long_options[] =
 
   /* Operation modes.  */
   { "fixed-output-files", no_argument,  0,   'y' },
-  { "yacc",              no_argument,  0,   'y' },
+  { "yacc",               no_argument,  0,   'y' },
 
   /* Parser.  */
-  { "debug",         no_argument,               0,   't' },
-  { "define",        required_argument,         0,   'D' },
+  { "debug",          no_argument,               0,   't' },
+  { "define",         required_argument,         0,   'D' },
   { "force-define",   required_argument,         0,   'F' },
-  { "locations",      no_argument,              0, LOCATIONS_OPTION },
+  { "locations",      no_argument,               0, LOCATIONS_OPTION },
   { "no-lines",       no_argument,               0,   'l' },
   { "raw",            no_argument,               0,     0 },
   { "skeleton",       required_argument,         0,   'S' },
@@ -573,7 +538,7 @@ static struct option const long_options[] =
 };
 
 /* Under DOS, there is no difference on the case.  This can be
-   troublesome when looking for `.tab' etc.  */
+   troublesome when looking for '.tab' etc.  */
 #ifdef MSDOS
 # define AS_FILE_NAME(File) (strlwr (File), (File))
 #else
@@ -599,63 +564,64 @@ getargs (int argc, char *argv[])
   int c;
 
   while ((c = getopt_long (argc, argv, short_options, long_options, NULL))
-        != -1)
+         != -1)
     switch (c)
       {
         /* ASCII Sorting for short options (i.e., upper case then
            lower case), and then long-only options.  */
 
       case 0:
-       /* Certain long options cause getopt_long to return 0.  */
-       break;
+        /* Certain long options cause getopt_long to return 0.  */
+        break;
 
       case 'D': /* -DNAME[=VALUE]. */
       case 'F': /* -FNAME[=VALUE]. */
         {
           char* name = optarg;
-          char* value = mbschr (optarg, '=');
+          char* value = strchr (optarg, '=');
           if (value)
             *value++ = 0;
           muscle_percent_define_insert (name, command_line_location (),
+                                        muscle_string,
                                         value ? value : "",
                                         c == 'D' ? MUSCLE_PERCENT_DEFINE_D
                                                  : MUSCLE_PERCENT_DEFINE_F);
         }
-       break;
+        break;
 
       case 'I':
-       include = AS_FILE_NAME (optarg);
-       break;
+        include = AS_FILE_NAME (optarg);
+        break;
 
       case 'L':
-       language_argmatch (optarg, command_line_prio,
-                          command_line_location ());
-       break;
+        language_argmatch (optarg, command_line_prio,
+                           command_line_location ());
+        break;
 
       case 'S':
-       skeleton_arg (AS_FILE_NAME (optarg), command_line_prio,
-                     command_line_location ());
-       break;
+        skeleton_arg (AS_FILE_NAME (optarg), command_line_prio,
+                      command_line_location ());
+        break;
 
       case 'T':
-       FLAGS_ARGMATCH (trace, optarg);
-       break;
+        FLAGS_ARGMATCH (trace, optarg, trace_all);
+        break;
 
       case 'V':
-       version ();
-       exit (EXIT_SUCCESS);
+        version ();
+        exit (EXIT_SUCCESS);
 
       case 'f':
-        FLAGS_ARGMATCH (feature, optarg);
+        FLAGS_ARGMATCH (feature, optarg, feature_all);
         break;
 
       case 'W':
-       FLAGS_ARGMATCH (warnings, optarg);
-       break;
+        warnings_argmatch (optarg);
+        break;
 
       case 'b':
-       spec_file_prefix = AS_FILE_NAME (optarg);
-       break;
+        spec_file_prefix = AS_FILE_NAME (optarg);
+        break;
 
       case 'd':
         /* Here, the -d and --defines options are differentiated.  */
@@ -668,77 +634,82 @@ getargs (int argc, char *argv[])
         break;
 
       case 'g':
-       graph_flag = true;
-       if (optarg)
+        graph_flag = true;
+        if (optarg)
           {
             free (spec_graph_file);
             spec_graph_file = xstrdup (AS_FILE_NAME (optarg));
           }
-       break;
+        break;
 
       case 'h':
-       usage (EXIT_SUCCESS);
+        usage (EXIT_SUCCESS);
 
       case 'k':
-       token_table_flag = true;
-       break;
+        token_table_flag = true;
+        break;
 
       case 'l':
-       no_lines_flag = true;
-       break;
+        no_lines_flag = true;
+        break;
 
       case 'o':
-       spec_outfile = AS_FILE_NAME (optarg);
-       break;
+        spec_outfile = AS_FILE_NAME (optarg);
+        break;
 
       case 'p':
-       spec_name_prefix = optarg;
-       break;
+        spec_name_prefix = optarg;
+        break;
 
       case 'r':
-       FLAGS_ARGMATCH (report, optarg);
-       break;
+        FLAGS_ARGMATCH (report, optarg, report_all);
+        break;
 
       case 't':
-       debug = true;
-       break;
+        muscle_percent_define_insert ("parse.trace",
+                                      command_line_location (),
+                                      muscle_keyword, "",
+                                      MUSCLE_PERCENT_DEFINE_D);
+        break;
 
       case 'v':
-       report_flag |= report_states;
-       break;
+        report_flag |= report_states;
+        break;
 
       case 'x':
-       xml_flag = true;
-       if (optarg)
+        xml_flag = true;
+        if (optarg)
           {
             free (spec_xml_file);
             spec_xml_file = xstrdup (AS_FILE_NAME (optarg));
           }
-       break;
+        break;
 
       case 'y':
-       yacc_flag = true;
-       break;
+        warning_argmatch ("error=yacc", 0, 6);
+        yacc_flag = true;
+        break;
 
       case LOCATIONS_OPTION:
-       locations_flag = true;
-       break;
+        muscle_percent_define_ensure ("locations",
+                                      command_line_location (), true);
+        break;
 
       case PRINT_LOCALEDIR_OPTION:
-       printf ("%s\n", LOCALEDIR);
-       exit (EXIT_SUCCESS);
+        printf ("%s\n", LOCALEDIR);
+        exit (EXIT_SUCCESS);
 
       case PRINT_DATADIR_OPTION:
-       printf ("%s\n", compute_pkgdatadir ());
-       exit (EXIT_SUCCESS);
+        printf ("%s\n", pkgdatadir ());
+        exit (EXIT_SUCCESS);
 
       case REPORT_FILE_OPTION:
         free (spec_verbose_file);
-       spec_verbose_file = xstrdup (AS_FILE_NAME (optarg));
-       break;
+        spec_verbose_file = xstrdup (AS_FILE_NAME (optarg));
+        break;
 
       default:
-       usage (EXIT_FAILURE);
+        usage (EXIT_FAILURE);
       }
 
   if (argc - optind != 1)
index 63c6aa4c0df399b6ea760fc3b14eb85f5b23e52a..5d4dfb0d12a9f8ab8c1ac54514bfbf6a15dc6b93 100644 (file)
@@ -21,7 +21,7 @@
 #ifndef GETARGS_H_
 # define GETARGS_H_
 
-#include "location.h"
+# include "location.h"
 
 enum { command_line_prio, grammar_prio, default_prio };
 
@@ -34,16 +34,12 @@ extern int skeleton_prio;
 /* for -I */
 extern char const *include;
 
-extern bool debug;                     /* for -t */
-extern bool defines_flag;              /* for -d */
-extern bool graph_flag;                        /* for -g */
-extern bool xml_flag;                  /* for -x */
-extern bool locations_flag;
-extern bool no_lines_flag;             /* for -l */
-extern bool token_table_flag;          /* for -k */
-extern bool yacc_flag;                 /* for -y */
-
-extern bool error_verbose;
+extern bool defines_flag;               /* for -d */
+extern bool graph_flag;                 /* for -g */
+extern bool xml_flag;                   /* for -x */
+extern bool no_lines_flag;              /* for -l */
+extern bool token_table_flag;           /* for -k */
+extern bool yacc_flag;                  /* for -y */
 
 
 /* GLR_PARSER is true if the input file says to use the GLR
@@ -112,24 +108,6 @@ enum trace
 /** What debug items bison displays during its run.  */
 extern int trace_flag;
 
-/*-------------.
-| --warnings.  |
-`-------------*/
-
-enum warnings
-  {
-    warnings_none             = 0,      /**< Issue no warnings.  */
-    warnings_error            = 1 << 0, /**< Warnings are treated as errors.  */
-    warnings_midrule_values   = 1 << 1, /**< Unset or unused midrule values.  */
-    warnings_yacc             = 1 << 2, /**< POSIXME.  */
-    warnings_conflicts_sr     = 1 << 3, /**< S/R conflicts.  */
-    warnings_conflicts_rr     = 1 << 4, /**< R/R conflicts.  */
-    warnings_other            = 1 << 5, /**< All other warnings.  */
-    warnings_all              = ~warnings_error /**< All above warnings.  */
-  };
-/** What warnings are issued.  */
-extern int warnings_flag;
-
 /*-------------.
 | --features.  |
 `-------------*/
@@ -143,6 +121,7 @@ enum feature
 /** What additional features to use.  */
 extern int feature_flag;
 
+
 /** Process the command line arguments.
  *
  *  \param argc   size of \a argv
index 69a4857ed722719fee38e830753f829136417c87..f6cc3c5d87a86a4fc86a90c9025cb8170e01daee 100644 (file)
@@ -47,50 +47,43 @@ symbol_number *token_translations = NULL;
 int max_user_token_number = 256;
 
 bool
-rule_useful_in_grammar_p (rule *r)
+rule_useful_in_grammar_p (rule const *r)
 {
   return r->number < nrules;
 }
 
 bool
-rule_useless_in_grammar_p (rule *r)
+rule_useless_in_grammar_p (rule const *r)
 {
   return !rule_useful_in_grammar_p (r);
 }
 
 bool
-rule_useless_in_parser_p (rule *r)
+rule_useless_in_parser_p (rule const *r)
 {
   return !r->useful && rule_useful_in_grammar_p (r);
 }
 
 void
-rule_lhs_print (rule *r, symbol *previous_lhs, FILE *out)
+rule_lhs_print (rule const *r, symbol const *previous_lhs, FILE *out)
 {
   fprintf (out, "  %3d ", r->number);
   if (previous_lhs != r->lhs)
-    {
-      fprintf (out, "%s:", r->lhs->tag);
-    }
+    fprintf (out, "%s:", r->lhs->tag);
   else
-    {
-      int n;
-      for (n = strlen (previous_lhs->tag); n > 0; --n)
-       fputc (' ', out);
-      fputc ('|', out);
-    }
+    fprintf (out, "%*s|", (int) strlen (previous_lhs->tag), "");
 }
 
 void
-rule_lhs_print_xml (rule *r, FILE *out, int level)
+rule_lhs_print_xml (rule const *r, FILE *out, int level)
 {
   xml_printf (out, level, "<lhs>%s</lhs>", r->lhs->tag);
 }
 
-int
-rule_rhs_length (rule *r)
+size_t
+rule_rhs_length (rule const *r)
 {
-  int res = 0;
+  size_t res = 0;
   item_number *rhsp;
   for (rhsp = r->rhs; *rhsp >= 0; ++rhsp)
     ++res;
@@ -98,31 +91,28 @@ rule_rhs_length (rule *r)
 }
 
 void
-rule_rhs_print (rule *r, FILE *out)
+rule_rhs_print (rule const *r, FILE *out)
 {
-  if (*r->rhs >= 0)
+  if (0 <= *r->rhs)
     {
       item_number *rp;
       for (rp = r->rhs; *rp >= 0; rp++)
-       fprintf (out, " %s", symbols[*rp]->tag);
-      fputc ('\n', out);
+        fprintf (out, " %s", symbols[*rp]->tag);
     }
   else
-    {
-      fprintf (out, " /* %s */\n", _("empty"));
-    }
+    fputs (" %empty", out);
 }
 
 static void
-rule_rhs_print_xml (rule *r, FILE *out, int level)
+rule_rhs_print_xml (rule const *r, FILE *out, int level)
 {
   if (*r->rhs >= 0)
     {
       item_number *rp;
       xml_puts (out, level, "<rhs>");
       for (rp = r->rhs; *rp >= 0; rp++)
-       xml_printf (out, level + 1, "<symbol>%s</symbol>",
-                   xml_escape (symbols[*rp]->tag));
+        xml_printf (out, level + 1, "<symbol>%s</symbol>",
+                    xml_escape (symbols[*rp]->tag));
       xml_puts (out, level, "</rhs>");
     }
   else
@@ -133,13 +123,6 @@ rule_rhs_print_xml (rule *r, FILE *out, int level)
     }
 }
 
-void
-rule_print (rule *r, FILE *out)
-{
-  fprintf (out, "%s:", r->lhs->tag);
-  rule_rhs_print (r, out);
-}
-
 void
 ritem_print (FILE *out)
 {
@@ -163,7 +146,7 @@ ritem_longest_rhs (void)
     {
       int length = rule_rhs_length (&rules[r]);
       if (length > max)
-       max = length;
+        max = length;
     }
 
   return max;
@@ -171,7 +154,7 @@ ritem_longest_rhs (void)
 
 void
 grammar_rules_partial_print (FILE *out, const char *title,
-                            rule_filter filter)
+                             rule_filter filter)
 {
   rule_number r;
   bool first = true;
@@ -181,14 +164,15 @@ grammar_rules_partial_print (FILE *out, const char *title,
   for (r = 0; r < nrules + nuseless_productions; r++)
     {
       if (filter && !filter (&rules[r]))
-       continue;
+        continue;
       if (first)
-       fprintf (out, "%s\n\n", title);
+        fprintf (out, "%s\n\n", title);
       else if (previous_lhs && previous_lhs != rules[r].lhs)
-       fputc ('\n', out);
+        fputc ('\n', out);
       first = false;
       rule_lhs_print (&rules[r], previous_lhs, out);
       rule_rhs_print (&rules[r], out);
+      fprintf (out, "\n");
       previous_lhs = rules[r].lhs;
     }
   if (!first)
@@ -210,7 +194,7 @@ grammar_rules_print_xml (FILE *out, int level)
   for (r = 0; r < nrules + nuseless_productions; r++)
     {
       if (first)
-       xml_puts (out, level + 1, "<rules>");
+        xml_puts (out, level + 1, "<rules>");
       first = false;
       {
         char const *usefulness;
@@ -243,8 +227,8 @@ grammar_dump (FILE *out, const char *title)
 {
   fprintf (out, "%s\n\n", title);
   fprintf (out,
-          "ntokens = %d, nvars = %d, nsyms = %d, nrules = %d, nritems = %d\n\n",
-          ntokens, nvars, nsyms, nrules, nritems);
+           "ntokens = %d, nvars = %d, nsyms = %d, nrules = %d, nritems = %d\n\n",
+           ntokens, nvars, nsyms, nrules, nritems);
 
 
   fprintf (out, "Variables\n---------\n\n");
@@ -254,37 +238,39 @@ grammar_dump (FILE *out, const char *title)
 
     for (i = ntokens; i < nsyms; i++)
       fprintf (out, "%5d  %5d   %5d  %s\n",
-              i,
-              symbols[i]->prec, symbols[i]->assoc,
-              symbols[i]->tag);
+               i,
+               symbols[i]->prec, symbols[i]->assoc,
+               symbols[i]->tag);
     fprintf (out, "\n\n");
   }
 
   fprintf (out, "Rules\n-----\n\n");
   {
     rule_number i;
-    fprintf (out, "Num (Prec, Assoc, Useful, Ritem Range) Lhs -> Rhs (Ritem range) [Num]\n");
+    fprintf (out,
+             "Num (Prec, Assoc, Useful, Ritem Range) Lhs"
+             " -> Rhs (Ritem range) [Num]\n");
     for (i = 0; i < nrules + nuseless_productions; i++)
       {
-       rule *rule_i = &rules[i];
-       item_number *rp = NULL;
-       unsigned int rhs_itemno = rule_i->rhs - ritem;
-       unsigned int rhs_count = 0;
-       /* Find the last RHS index in ritems. */
-       for (rp = rule_i->rhs; *rp >= 0; ++rp)
-         ++rhs_count;
-       fprintf (out, "%3d (%2d, %2d, %2d, %2u-%2u)   %2d ->",
-                i,
-                rule_i->prec ? rule_i->prec->prec : 0,
-                rule_i->prec ? rule_i->prec->assoc : 0,
-                rule_i->useful,
-                rhs_itemno,
-                rhs_itemno + rhs_count - 1,
-                rule_i->lhs->number);
-       /* Dumped the RHS. */
-       for (rp = rule_i->rhs; *rp >= 0; rp++)
-         fprintf (out, " %3d", *rp);
-       fprintf (out, "  [%d]\n", item_number_as_rule_number (*rp));
+        rule const *rule_i = &rules[i];
+        item_number *rp = NULL;
+        unsigned int rhs_itemno = rule_i->rhs - ritem;
+        unsigned int rhs_count = 0;
+        /* Find the last RHS index in ritems. */
+        for (rp = rule_i->rhs; *rp >= 0; ++rp)
+          ++rhs_count;
+        fprintf (out, "%3d (%2d, %2d, %2d, %2u-%2u)   %2d ->",
+                 i,
+                 rule_i->prec ? rule_i->prec->prec : 0,
+                 rule_i->prec ? rule_i->prec->assoc : 0,
+                 rule_i->useful,
+                 rhs_itemno,
+                 rhs_itemno + rhs_count - 1,
+                 rule_i->lhs->number);
+        /* Dumped the RHS. */
+        for (rp = rule_i->rhs; *rp >= 0; rp++)
+          fprintf (out, " %3d", *rp);
+        fprintf (out, "  [%d]\n", item_number_as_rule_number (*rp));
       }
   }
   fprintf (out, "\n\n");
@@ -294,8 +280,9 @@ grammar_dump (FILE *out, const char *title)
     rule_number r;
     for (r = 0; r < nrules + nuseless_productions; r++)
       {
-       fprintf (out, "%-5d  ", r);
-       rule_print (&rules[r], out);
+        fprintf (out, "%-5d  %s:", r, rules[r].lhs->tag);
+        rule_rhs_print (&rules[r], out);
+        fprintf (out, "\n");
       }
   }
   fprintf (out, "\n\n");
@@ -307,19 +294,7 @@ grammar_rules_useless_report (const char *message)
   rule_number r;
   for (r = 0; r < nrules ; ++r)
     if (!rules[r].useful)
-      {
-        if (feature_flag & feature_caret)
-          warn_at (rules[r].location, "%s", message);
-        else
-          {
-            warn_at (rules[r].location, "%s: ", message);
-            if (warnings_flag & warnings_other)
-              {
-                rule_print (&rules[r], stderr);
-                fflush (stderr);
-              }
-          }
-      }
+      complain (&rules[r].location, Wother, "%s", message);
 }
 
 void
index 66cd31717c9c6b7d354c99d4d29e078b81def51b..c1dd9a648ab185577261067053f2bc380952f6d5 100644 (file)
@@ -35,7 +35,7 @@
 
    The rules receive rule numbers 1 to NRULES in the order they are
    written.  More precisely Bison augments the grammar with the
-   initial rule, `$accept: START-SYMBOL $end', which is numbered 1,
+   initial rule, '$accept: START-SYMBOL $end', which is numbered 1,
    all the user rules are 2, 3 etc.  Each time a rule number is
    presented to the user, we subtract 1, so *displayed* rule numbers
    are 0, 1, 2...
@@ -61,7 +61,7 @@
    RULES[R].prec -- the symbol providing the precedence level of R.
 
    RULES[R].precsym -- the symbol attached (via %prec) to give its
-   precedence to R.  Of course, if set, it is equal to `prec', but we
+   precedence to R.  Of course, if set, it is equal to 'prec', but we
    need to distinguish one from the other when reducing: a symbol used
    in a %prec is not useless.
 
 # include "location.h"
 # include "symtab.h"
 
-# define ISTOKEN(i)    ((i) < ntokens)
-# define ISVAR(i)      ((i) >= ntokens)
+# define ISTOKEN(i)     ((i) < ntokens)
+# define ISVAR(i)       ((i) >= ntokens)
 
 extern int nsyms;
 extern int ntokens;
 extern int nvars;
 
 typedef int item_number;
-#define ITEM_NUMBER_MAX INT_MAX
+# define ITEM_NUMBER_MAX INT_MAX
 extern item_number *ritem;
 extern unsigned int nritems;
 
@@ -145,7 +145,7 @@ item_number_is_symbol_number (item_number i)
 
 /* Rule numbers.  */
 typedef int rule_number;
-#define RULE_NUMBER_MAX INT_MAX
+# define RULE_NUMBER_MAX INT_MAX
 extern rule_number nrules;
 
 static inline item_number
@@ -194,6 +194,7 @@ typedef struct
 
   location location;
   bool useful;
+  bool is_predicate;
 
   const char *action;
   location action_location;
@@ -202,34 +203,31 @@ typedef struct
 extern rule *rules;
 
 /* A function that selects a rule.  */
-typedef bool (*rule_filter) (rule *);
+typedef bool (*rule_filter) (rule const *);
 
-/* Return true IFF the rule has a `number' smaller than NRULES.  That is, it is
+/* Return true IFF the rule has a 'number' smaller than NRULES.  That is, it is
    useful in the grammar.  */
-bool rule_useful_in_grammar_p (rule *r);
+bool rule_useful_in_grammar_p (rule const *r);
 
-/* Return true IFF the rule has a `number' higher than NRULES.  That is, it is
+/* Return true IFF the rule has a 'number' higher than NRULES.  That is, it is
    useless in the grammar.  */
-bool rule_useless_in_grammar_p (rule *r);
+bool rule_useless_in_grammar_p (rule const *r);
 
 /* Return true IFF the rule is not flagged as useful but is useful in the
    grammar.  In other words, it was discarded because of conflicts.  */
-bool rule_useless_in_parser_p (rule *r);
+bool rule_useless_in_parser_p (rule const *r);
 
 /* Print this rule's number and lhs on OUT.  If a PREVIOUS_LHS was
    already displayed (by a previous call for another rule), avoid
    useless repetitions.  */
-void rule_lhs_print (rule *r, symbol *previous_lhs, FILE *out);
-void rule_lhs_print_xml (rule *r, FILE *out, int level);
+void rule_lhs_print (rule const *r, symbol const *previous_lhs, FILE *out);
+void rule_lhs_print_xml (rule const *r, FILE *out, int level);
 
 /* Return the length of the RHS.  */
-int rule_rhs_length (rule *r);
+size_t rule_rhs_length (rule const *r);
 
 /* Print this rule's RHS on OUT.  */
-void rule_rhs_print (rule *r, FILE *out);
-
-/* Print this rule on OUT.  */
-void rule_print (rule *r, FILE *out);
+void rule_rhs_print (rule const *r, FILE *out);
 
 
 
@@ -253,7 +251,7 @@ size_t ritem_longest_rhs (void);
 
 /* Print the grammar's rules that match FILTER on OUT under TITLE.  */
 void grammar_rules_partial_print (FILE *out, const char *title,
-                                 rule_filter filter);
+                                  rule_filter filter);
 
 /* Print the grammar's useful rules on OUT.  */
 void grammar_rules_print (FILE *out);
@@ -264,8 +262,8 @@ void grammar_rules_print_xml (FILE *out, int level);
 void grammar_dump (FILE *out, const char *title);
 
 /* Report on STDERR the rules that are not flagged USEFUL, using the
-   MESSAGE (which can be `rule useless in grammar' when invoked after grammar
-   reduction, or `rule useless in parser due to conflicts' after conflicts
+   MESSAGE (which can be 'rule useless in grammar' when invoked after grammar
+   reduction, or 'rule useless in parser due to conflicts' after conflicts
    were taken into account).  */
 void grammar_rules_useless_report (const char *message);
 
index e8d0f0cc2f3a5e236066a252447e76f45fc13d44..0254ef748b3a864a5140e9d55d64b7940c982b42 100644 (file)
@@ -22,7 +22,7 @@
 #ifndef GRAPHVIZ_H_
 # define GRAPHVIZ_H_
 
-#include "state.h"
+# include "state.h"
 
 /** Begin a Dot graph.
  *
index 4692de011e1af68d7dc7923c911c4f596d0af09f..55005231705e38fa5370be6dc21dcbaa3ad9fdb0 100644 (file)
@@ -1095,11 +1095,11 @@ ielr (void)
   /* Examine user options.  */
   {
     char *type = muscle_percent_define_get ("lr.type");
-    if (0 == strcmp (type, "lalr"))
+    if (STREQ (type, "lalr"))
       lr_type = LR_TYPE__LALR;
-    else if (0 == strcmp (type, "ielr"))
+    else if (STREQ (type, "ielr"))
       lr_type = LR_TYPE__IELR;
-    else if (0 == strcmp (type, "canonical-lr"))
+    else if (STREQ (type, "canonical-lr"))
       lr_type = LR_TYPE__CANONICAL_LR;
     else
       aver (false);
index 405c03e29cdcd36876b1db2bdabef856b6e4421e..b60ae363484b89aecb8058f55e7dc321b8daf295 100644 (file)
@@ -20,9 +20,9 @@
 #ifndef IELR_H_
 # define IELR_H_
 
-#include <bitset.h>
+# include <bitset.h>
 
-#include "state.h"
+# include "state.h"
 
 /**
  * \pre
index 53d9a835f21d0dd0e17b777ce927ef4deb83ecff..d99f960fbf903fdad47f62580fb79695c829ffe1 100644 (file)
@@ -84,14 +84,14 @@ set_goto_map (void)
       transitions *sp = states[s]->transitions;
       int i;
       for (i = sp->num - 1; i >= 0 && TRANSITION_IS_GOTO (sp, i); --i)
-       {
-         ngotos++;
+        {
+          ngotos++;
 
-         /* Abort if (ngotos + 1) would overflow.  */
-         aver (ngotos != GOTO_NUMBER_MAXIMUM);
+          /* Abort if (ngotos + 1) would overflow.  */
+          aver (ngotos != GOTO_NUMBER_MAXIMUM);
 
-         goto_map[TRANSITION_SYMBOL (sp, i) - ntokens]++;
-       }
+          goto_map[TRANSITION_SYMBOL (sp, i) - ntokens]++;
+        }
     }
 
   {
@@ -99,8 +99,8 @@ set_goto_map (void)
     int i;
     for (i = ntokens; i < nsyms; i++)
       {
-       temp_map[i - ntokens] = k;
-       k += goto_map[i - ntokens];
+        temp_map[i - ntokens] = k;
+        k += goto_map[i - ntokens];
       }
 
     for (i = ntokens; i < nsyms; i++)
@@ -118,11 +118,11 @@ set_goto_map (void)
       transitions *sp = states[s]->transitions;
       int i;
       for (i = sp->num - 1; i >= 0 && TRANSITION_IS_GOTO (sp, i); --i)
-       {
-         goto_number k = temp_map[TRANSITION_SYMBOL (sp, i) - ntokens]++;
-         from_state[k] = s;
-         to_state[k] = sp->states[i]->number;
-       }
+        {
+          goto_number k = temp_map[TRANSITION_SYMBOL (sp, i) - ntokens]++;
+          from_state[k] = s;
+          to_state[k] = sp->states[i]->number;
+        }
     }
 
   free (temp_map);
@@ -146,11 +146,11 @@ map_goto (state_number s0, symbol_number sym)
       middle = (low + high) / 2;
       s = from_state[middle];
       if (s == s0)
-       return middle;
+        return middle;
       else if (s < s0)
-       low = middle + 1;
+        low = middle + 1;
       else
-       high = middle - 1;
+        high = middle - 1;
     }
 }
 
@@ -173,24 +173,24 @@ initialize_F (void)
 
       int j;
       FOR_EACH_SHIFT (sp, j)
-       bitset_set (goto_follows[i], TRANSITION_SYMBOL (sp, j));
+        bitset_set (goto_follows[i], TRANSITION_SYMBOL (sp, j));
 
       for (; j < sp->num; j++)
-       {
-         symbol_number sym = TRANSITION_SYMBOL (sp, j);
-         if (nullable[sym - ntokens])
-           edge[nedges++] = map_goto (stateno, sym);
-       }
+        {
+          symbol_number sym = TRANSITION_SYMBOL (sp, j);
+          if (nullable[sym - ntokens])
+            edge[nedges++] = map_goto (stateno, sym);
+        }
 
       if (nedges == 0)
-       reads[i] = NULL;
+        reads[i] = NULL;
       else
-       {
-         reads[i] = xnmalloc (nedges + 1, sizeof reads[i][0]);
-         memcpy (reads[i], edge, nedges * sizeof edge[0]);
-         reads[i][nedges] = END_NODE;
-         nedges = 0;
-       }
+        {
+          reads[i] = xnmalloc (nedges + 1, sizeof reads[i][0]);
+          memcpy (reads[i], edge, nedges * sizeof edge[0]);
+          reads[i][nedges] = END_NODE;
+          nedges = 0;
+        }
     }
 
   relation_digraph (reads, ngotos, &goto_follows);
@@ -231,53 +231,53 @@ build_relations (void)
       rule **rulep;
 
       for (rulep = derives[symbol1 - ntokens]; *rulep; rulep++)
-       {
-         bool done;
-         int length = 1;
-         item_number const *rp;
-         state *s = states[from_state[i]];
-         states1[0] = s->number;
-
-         for (rp = (*rulep)->rhs; ! item_number_is_rule_number (*rp); rp++)
-           {
-             s = transitions_to (s->transitions,
-                                 item_number_as_symbol_number (*rp));
-             states1[length++] = s->number;
-           }
-
-         if (!s->consistent)
-           add_lookback_edge (s, *rulep, i);
-
-         length--;
-         done = false;
-         while (!done)
-           {
-             done = true;
-             /* Each rhs ends in a rule number, and there is a
-                sentinel (ritem[-1]=0) before the first rhs, so it is safe to
-                decrement RP here.  */
-             rp--;
-             if (ISVAR (*rp))
-               {
-                 /* Downcasting from item_number to symbol_number.  */
-                 edge[nedges++] = map_goto (states1[--length],
-                                            item_number_as_symbol_number (*rp));
-                 if (nullable[*rp - ntokens])
-                   done = false;
-               }
-           }
-       }
+        {
+          bool done;
+          int length = 1;
+          item_number const *rp;
+          state *s = states[from_state[i]];
+          states1[0] = s->number;
+
+          for (rp = (*rulep)->rhs; ! item_number_is_rule_number (*rp); rp++)
+            {
+              s = transitions_to (s->transitions,
+                                  item_number_as_symbol_number (*rp));
+              states1[length++] = s->number;
+            }
+
+          if (!s->consistent)
+            add_lookback_edge (s, *rulep, i);
+
+          length--;
+          done = false;
+          while (!done)
+            {
+              done = true;
+              /* Each rhs ends in a rule number, and there is a
+                 sentinel (ritem[-1]=0) before the first rhs, so it is safe to
+                 decrement RP here.  */
+              rp--;
+              if (ISVAR (*rp))
+                {
+                  /* Downcasting from item_number to symbol_number.  */
+                  edge[nedges++] = map_goto (states1[--length],
+                                             item_number_as_symbol_number (*rp));
+                  if (nullable[*rp - ntokens])
+                    done = false;
+                }
+            }
+        }
 
       if (nedges == 0)
-       includes[i] = NULL;
+        includes[i] = NULL;
       else
-       {
-         int j;
-         includes[i] = xnmalloc (nedges + 1, sizeof includes[i][0]);
-         for (j = 0; j < nedges; j++)
-           includes[i][j] = edge[j];
-         includes[i][nedges] = END_NODE;
-       }
+        {
+          int j;
+          includes[i] = xnmalloc (nedges + 1, sizeof includes[i][0]);
+          for (j = 0; j < nedges; j++)
+            includes[i][j] = edge[j];
+          includes[i][nedges] = END_NODE;
+        }
     }
 
   free (edge);
@@ -342,7 +342,7 @@ state_lookahead_tokens_count (state *s, bool default_reduction_only_for_accept)
   /* We need a lookahead either to distinguish different reductions
      (i.e., there are two or more), or to distinguish a reduction from a
      shift.  Otherwise, it is straightforward, and the state is
-     `consistent'.  However, do not treat a state with any reductions as
+     'consistent'.  However, do not treat a state with any reductions as
      consistent unless it is the accepting state (because there is never
      a lookahead token that makes sense there, and so no lookahead token
      should be read) if the user has otherwise disabled default
@@ -371,9 +371,8 @@ initialize_LA (void)
   bool default_reduction_only_for_accept;
   {
     char *default_reductions =
-      muscle_percent_define_get ("lr.default-reductions");
-    default_reduction_only_for_accept =
-      0 == strcmp (default_reductions, "accepting");
+      muscle_percent_define_get ("lr.default-reduction");
+    default_reduction_only_for_accept = STREQ (default_reductions, "accepting");
     free (default_reductions);
   }
 
@@ -397,10 +396,10 @@ initialize_LA (void)
         state_lookahead_tokens_count (states[i],
                                       default_reduction_only_for_accept);
       if (count)
-       {
-         states[i]->reductions->lookahead_tokens = pLA;
-         pLA += count;
-       }
+        {
+          states[i]->reductions->lookahead_tokens = pLA;
+          pLA += count;
+        }
     }
 }
 
@@ -422,21 +421,21 @@ lookahead_tokens_print (FILE *out)
       int n_lookahead_tokens = 0;
 
       if (reds->lookahead_tokens)
-       for (k = 0; k < reds->num; ++k)
-         if (reds->lookahead_tokens[k])
-           ++n_lookahead_tokens;
+        for (k = 0; k < reds->num; ++k)
+          if (reds->lookahead_tokens[k])
+            ++n_lookahead_tokens;
 
       fprintf (out, "State %d: %d lookahead tokens\n",
-              i, n_lookahead_tokens);
+               i, n_lookahead_tokens);
 
       if (reds->lookahead_tokens)
-       for (j = 0; j < reds->num; ++j)
-         BITSET_FOR_EACH (iter, reds->lookahead_tokens[j], k, 0)
-         {
-           fprintf (out, "   on %d (%s) -> rule %d\n",
-                    k, symbols[k]->tag,
-                    reds->rules[j]->number);
-         };
+        for (j = 0; j < reds->num; ++j)
+          BITSET_FOR_EACH (iter, reds->lookahead_tokens[j], k, 0)
+          {
+            fprintf (out, "   on %d (%s) -> rule %d\n",
+                     k, symbols[k]->tag,
+                     reds->rules[j]->number);
+          };
     }
   fprintf (out, "Lookahead tokens: END\n");
 }
diff --git a/src/local.mk b/src/local.mk
new file mode 100644 (file)
index 0000000..9e0848c
--- /dev/null
@@ -0,0 +1,123 @@
+# Copyright (C) 2001-2013 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/>.
+
+LDADD = lib/libbison.a $(LIBINTL)
+
+bin_PROGRAMS = src/bison
+# Prettify Automake-computed names of compiled objects.
+src_bison_SHORTNAME = bison
+
+src_bison_CFLAGS = $(AM_CFLAGS) $(WERROR_CFLAGS)
+src_bison_SOURCES =                             \
+  src/AnnotationList.c                          \
+  src/AnnotationList.h                          \
+  src/InadequacyList.c                          \
+  src/InadequacyList.h                          \
+  src/LR0.c                                     \
+  src/LR0.h                                     \
+  src/Sbitset.c                                 \
+  src/Sbitset.h                                 \
+  src/assoc.c                                   \
+  src/assoc.h                                   \
+  src/closure.c                                 \
+  src/closure.h                                 \
+  src/complain.c                                \
+  src/complain.h                                \
+  src/conflicts.c                               \
+  src/conflicts.h                               \
+  src/derives.c                                 \
+  src/derives.h                                 \
+  src/files.c                                   \
+  src/files.h                                   \
+  src/flex-scanner.h                            \
+  src/getargs.c                                 \
+  src/getargs.h                                 \
+  src/gram.c                                    \
+  src/gram.h                                    \
+  src/graphviz.c                                \
+  src/graphviz.h                                \
+  src/lalr.c                                    \
+  src/lalr.h                                    \
+  src/ielr.c                                    \
+  src/ielr.h                                    \
+  src/location.c                                \
+  src/location.h                                \
+  src/main.c                                    \
+  src/muscle-tab.c                              \
+  src/muscle-tab.h                              \
+  src/named-ref.c                               \
+  src/named-ref.h                               \
+  src/nullable.c                                \
+  src/nullable.h                                \
+  src/output.c                                  \
+  src/output.h                                  \
+  src/parse-gram.y                              \
+  src/print-xml.c                               \
+  src/print-xml.h                               \
+  src/print.c                                   \
+  src/print.h                                   \
+  src/print_graph.c                             \
+  src/print_graph.h                             \
+  src/reader.c                                  \
+  src/reader.h                                  \
+  src/reduce.c                                  \
+  src/reduce.h                                  \
+  src/relation.c                                \
+  src/relation.h                                \
+  src/scan-code-c.c                             \
+  src/scan-code.h                               \
+  src/scan-gram-c.c                             \
+  src/scan-gram.h                               \
+  src/scan-skel-c.c                             \
+  src/scan-skel.h                               \
+  src/state.c                                   \
+  src/state.h                                   \
+  src/symlist.c                                 \
+  src/symlist.h                                 \
+  src/symtab.c                                  \
+  src/symtab.h                                  \
+  src/system.h                                  \
+  src/tables.c                                  \
+  src/tables.h                                  \
+  src/uniqstr.c                                 \
+  src/uniqstr.h
+
+EXTRA_src_bison_SOURCES =                       \
+  src/scan-code.l                               \
+  src/scan-gram.l                               \
+  src/scan-skel.l
+
+BUILT_SOURCES +=                                \
+  src/parse-gram.c                              \
+  src/parse-gram.h                              \
+  src/scan-code.c                               \
+  src/scan-gram.c                               \
+  src/scan-skel.c
+
+
+## ------ ##
+## yacc.  ##
+## ------ ##
+
+bin_SCRIPTS = $(YACC_SCRIPT)
+EXTRA_SCRIPTS = src/yacc
+MOSTLYCLEANFILES += src/yacc
+
+src/yacc:
+       $(AM_V_GEN)rm -f $@ $@.tmp
+       $(AM_V_at)echo '#! /bin/sh' >$@.tmp
+       $(AM_V_at)echo "exec '$(bindir)/bison' -y "'"$$@"' >>$@.tmp
+       $(AM_V_at)chmod a+x $@.tmp
+       $(AM_V_at)mv $@.tmp $@
index f565b24aa698724bd9eccace33741f6e9b35aad8..662b2a12a07bde5c07b0fabbd698a1661d3ad0f7 100644 (file)
@@ -42,7 +42,7 @@ add_column_width (int column, char const *buf, size_t bufsize)
   if (buf)
     {
       if (INT_MAX / 2 <= bufsize)
-       return INT_MAX;
+        return INT_MAX;
       width = mbsnwidth (buf, bufsize, 0);
     }
   else
@@ -69,19 +69,19 @@ location_compute (location *loc, boundary *cur, char const *token, size_t size)
     switch (*p)
       {
       case '\n':
-       line += line < INT_MAX;
-       column = 1;
-       p0 = p + 1;
-       break;
+        line += line < INT_MAX;
+        column = 1;
+        p0 = p + 1;
+        break;
 
       case '\t':
-       column = add_column_width (column, p0, p - p0);
-       column = add_column_width (column, NULL, 8 - ((column - 1) & 7));
-       p0 = p + 1;
-       break;
+        column = add_column_width (column, p0, p - p0);
+        column = add_column_width (column, NULL, 8 - ((column - 1) & 7));
+        p0 = p + 1;
+        break;
 
       default:
-       break;
+        break;
       }
 
   cur->line = line;
@@ -90,16 +90,14 @@ location_compute (location *loc, boundary *cur, char const *token, size_t size)
   loc->end = *cur;
 
   if (line == INT_MAX && loc->start.line != INT_MAX)
-    warn_at (*loc, _("line number overflow"));
+    complain (loc, Wother, _("line number overflow"));
   if (column == INT_MAX && loc->start.column != INT_MAX)
-    warn_at (*loc, _("column number overflow"));
+    complain (loc, Wother, _("column number overflow"));
 }
 
 
-/* Output to OUT the location LOC.
-   Warning: it uses quotearg's slot 3.  */
 unsigned
-location_print (FILE *out, location loc)
+location_print (location loc, FILE *out)
 {
   unsigned res = 0;
   int end_col = 0 != loc.end.column ? loc.end.column - 1 : 0;
@@ -155,10 +153,13 @@ cleanup_caret ()
 {
   if (caret_info.source)
     fclose (caret_info.source);
+  caret_info.source = NULL;
+  caret_info.line = 1;
+  caret_info.offset = 0;
 }
 
 void
-location_caret (FILE *out, location loc)
+location_caret (location loc, FILE *out)
 {
   /* FIXME: find a way to support multifile locations, and only open once each
      file. That would make the procedure future-proof.  */
@@ -168,8 +169,8 @@ location_caret (FILE *out, location loc)
     return;
 
   /* If the line we want to quote is seekable (the same line as the previous
-     location), just seek it. If it was before, we lost track of it, so
-     return to the start of file.  */
+     location), just seek it. If it was a previous line, we lost track of it,
+     so return to the start of file.  */
   if (caret_info.line <= loc.start.line)
     fseek (caret_info.source, caret_info.offset, SEEK_SET);
   else
@@ -181,35 +182,36 @@ location_caret (FILE *out, location loc)
 
   /* Advance to the line's position, keeping track of the offset.  */
   while (caret_info.line < loc.start.line)
-    caret_info.line += fgetc (caret_info.source) == '\n';
+    caret_info.line += getc (caret_info.source) == '\n';
   caret_info.offset = ftell (caret_info.source);
 
   /* Read the actual line.  Don't update the offset, so that we keep a pointer
      to the start of the line.  */
   {
-    char *buf = NULL;
-    size_t size = 0;
-    ssize_t len = getline (&buf, &size, caret_info.source);
-    if (0 < len)
+    char c = getc (caret_info.source);
+    if (c != EOF)
       {
-        /* The caret of a multiline location ends with the first line.  */
-        int end = loc.start.line != loc.end.line ? len : loc.end.column;
-
         /* Quote the file, indent by a single column.  */
-        fputc (' ', out);
-        fwrite (buf, 1, len, out);
+        putc (' ', out);
+        do
+          putc (c, out);
+        while ((c = getc (caret_info.source)) != EOF && c != '\n');
+        putc ('\n', out);
 
-        /* Print the caret, with the same indent as above.  */
-        fprintf (out, " %*s", loc.start.column - 1, "");
         {
-          int i = loc.start.column;
-          do
-            fputc ('^', out);
-          while (++i < end);
-        }
-        fputc ('\n', out);
+          /* The caret of a multiline location ends with the first line.  */
+          size_t len = loc.start.line != loc.end.line
+            ? ftell (caret_info.source) - caret_info.offset
+            : loc.end.column;
+          int i;
+
+          /* Print the carets (at least one), with the same indent as above.*/
+          fprintf (out, " %*s", loc.start.column - 1, "");
+          for (i = loc.start.column; i == loc.start.column || i < len; ++i)
+            putc ('^', out);
+          }
+        putc ('\n', out);
       }
-    free (buf);
   }
 }
 
@@ -217,12 +219,12 @@ void
 boundary_set_from_string (boundary *bound, char *loc_str)
 {
   /* Must search in reverse since the file name field may
-   * contain `.' or `:'.  */
-  char *delim = mbsrchr (loc_str, '.');
+   * contain '.' or ':'.  */
+  char *delim = strrchr (loc_str, '.');
   aver (delim);
   *delim = '\0';
   bound->column = atoi (delim+1);
-  delim = mbsrchr (loc_str, ':');
+  delim = strrchr (loc_str, ':');
   aver (delim);
   *delim = '\0';
   bound->line = atoi (delim+1);
index 2129a6266e861aba91d2dd8451908f16cb2cc190..8f1c5ae1df2ee40839d6480ec8946b77b0ea4a07 100644 (file)
@@ -73,8 +73,8 @@ static inline bool
 equal_boundaries (boundary a, boundary b)
 {
   return (a.column == b.column
-         && a.line == b.line
-         && UNIQSTR_EQ (a.file, b.file));
+          && a.line == b.line
+          && UNIQSTR_EQ (a.file, b.file));
 }
 
 /* A location, that is, a region of source code.  */
@@ -88,26 +88,27 @@ typedef struct
 
 } location;
 
-#define GRAM_LTYPE location
+# define GRAM_LTYPE location
 
-#define EMPTY_LOCATION_INIT {{NULL, 0, 0}, {NULL, 0, 0}}
+# define EMPTY_LOCATION_INIT {{NULL, 0, 0}, {NULL, 0, 0}}
 extern location const empty_location;
 
 /* Set *LOC and adjust scanner cursor to account for token TOKEN of
    size SIZE.  */
 void location_compute (location *loc,
-                      boundary *cur, char const *token, size_t size);
+                       boundary *cur, char const *token, size_t size);
 
-/* Print location to file. Return number of actually printed
-   characters.  */
-unsigned location_print (FILE *out, location loc);
+/* Print location to file.
+   Return number of actually printed characters.
+   Warning: uses quotearg's slot 3. */
+unsigned location_print (location loc, FILE *out);
 
 /* Free any allocated ressources and close any open file handles that are
    left-over by the usage of location_caret.  */
 void cleanup_caret (void);
 
 /* Output to OUT the line and caret corresponding to location LOC.  */
-void location_caret (FILE *out, location loc);
+void location_caret (location loc, FILE *out);
 
 /* Return -1, 0, 1, depending whether a is before, equal, or
    after b.  */
@@ -120,7 +121,7 @@ location_cmp (location a, location b)
   return res;
 }
 
-/* LOC_STR must be formatted as `file:line.column', it will be modified.  */
+/* LOC_STR must be formatted as 'file:line.column', it will be modified.  */
 void boundary_set_from_string (boundary *bound, char *loc_str);
 
 #endif /* ! defined LOCATION_H_ */
index ef59b1f232738a574d639e62a7e1237864ad9cee..aa8c7bfa058793bdf5747761334348fb6fc0a2f5 100644 (file)
@@ -66,7 +66,7 @@ main (int argc, char *argv[])
 
   {
     char const *cp = getenv ("LC_CTYPE");
-    if (cp && !strcmp (cp, "C"))
+    if (cp && STREQ (cp, "C"))
       set_custom_quoting (&quote_quoting_options, "'", "'");
     else
       set_quoting_style (&quote_quoting_options, locale_quoting_style);
@@ -76,6 +76,7 @@ main (int argc, char *argv[])
 
   uniqstrs_new ();
   muscle_init ();
+  complain_init ();
 
   getargs (argc, argv);
 
@@ -94,7 +95,7 @@ main (int argc, char *argv[])
   reader ();
   timevar_pop (TV_READER);
 
-  if (complaint_issued)
+  if (complaint_status == status_complaint)
     goto finish;
 
   /* Find useless nonterminals and productions and reduce the grammar. */
@@ -125,7 +126,7 @@ main (int argc, char *argv[])
      declarations.  */
   timevar_push (TV_CONFLICTS);
   conflicts_solve ();
-  if (!muscle_percent_define_flag_if ("lr.keep-unreachable-states"))
+  if (!muscle_percent_define_flag_if ("lr.keep-unreachable-state"))
     {
       state_number *old_to_new = xnmalloc (nstates, sizeof *old_to_new);
       state_number nstates_old = nstates;
@@ -142,8 +143,9 @@ main (int argc, char *argv[])
   tables_generate ();
   timevar_pop (TV_ACTIONS);
 
-  grammar_rules_useless_report
-    (_("rule useless in parser due to conflicts"));
+  grammar_rules_useless_report (_("rule useless in parser due to conflicts"));
+
+  print_precedence_warnings ();
 
   /* Output file names. */
   compute_output_file_names ();
@@ -174,7 +176,7 @@ main (int argc, char *argv[])
 
   /* Stop if there were errors, to avoid trashing previous output
      files.  */
-  if (complaint_issued)
+  if (complaint_status == status_complaint)
     goto finish;
 
   /* Lookahead tokens are no longer needed. */
@@ -218,5 +220,5 @@ main (int argc, char *argv[])
 
   cleanup_caret ();
 
-  return complaint_issued ? EXIT_FAILURE : EXIT_SUCCESS;
+  return complaint_status ? EXIT_FAILURE : EXIT_SUCCESS;
 }
index 97c26ea10acbc86d126054ac59d1cd87941cb050..10a0a5cbba7d0f68d1e75275a44378e2f60f66b5 100644 (file)
 #include "muscle-tab.h"
 #include "quote.h"
 
+muscle_kind
+muscle_kind_new (char const *k)
+{
+  if (STREQ (k, "code"))
+    return muscle_code;
+  else if (STREQ (k, "keyword"))
+    return muscle_keyword;
+  else if (STREQ (k, "string"))
+    return muscle_string;
+  aver (0);
+}
+
+char const *
+muscle_kind_string (muscle_kind k)
+{
+  switch (k)
+    {
+    case muscle_code:    return "code";
+    case muscle_keyword: return "keyword";
+    case muscle_string:  return "string";
+    }
+  aver (0);
+}
+
+
 /* A key-value pair, along with storage that can be reclaimed when
    this pair is no longer needed.  */
 typedef struct
@@ -35,6 +60,7 @@ typedef struct
   char const *key;
   char const *value;
   char *storage;
+  muscle_kind kind;
 } muscle_entry;
 
 /* An obstack used to create some entries.  */
@@ -50,7 +76,7 @@ hash_compare_muscles (void const *x, void const *y)
 {
   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
@@ -60,10 +86,18 @@ hash_muscle (const void *x, size_t tablesize)
   return hash_string (m->key, tablesize);
 }
 
-/*-----------------------------------------------------------------.
-| Create the MUSCLE_TABLE, and initialize it with default values.  |
-| Also set up the MUSCLE_OBSTACK.                                  |
-`-----------------------------------------------------------------*/
+/* Create a fresh muscle name KEY, and insert in the hash table.  */
+static void *
+muscle_entry_new (char const *key)
+{
+  muscle_entry *res = xmalloc (sizeof *res);
+  res->key = key;
+  res->value = NULL;
+  res->storage = NULL;
+  if (!hash_insert (muscle_table, res))
+    xalloc_die ();
+  return res;
+}
 
 static void
 muscle_entry_free (void *entry)
@@ -80,17 +114,13 @@ 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);
 }
 
 
-/*------------------------------------------------------------.
-| Free all the memory consumed by the muscle machinery only.  |
-`------------------------------------------------------------*/
-
 void
 muscle_free (void)
 {
@@ -98,32 +128,26 @@ muscle_free (void)
   obstack_free (&muscle_obstack, NULL);
 }
 
+/* Look for the muscle named KEY.  Return NULL if does not exist.  */
+static
+muscle_entry *
+muscle_lookup (char const *key)
+{
+  muscle_entry probe;
+  probe.key = key;
+  return hash_lookup (muscle_table, &probe);
+}
 
 
-/*------------------------------------------------------------.
-| Insert (KEY, VALUE).  If KEY already existed, overwrite the |
-| previous value.                                             |
-`------------------------------------------------------------*/
-
 void
 muscle_insert (char const *key, char const *value)
 {
-  muscle_entry probe;
-  muscle_entry *entry;
-
-  probe.key = key;
-  entry = hash_lookup (muscle_table, &probe);
-
-  if (!entry)
-    {
-      /* First insertion in the hash. */
-      entry = xmalloc (sizeof *entry);
-      entry->key = key;
-      if (!hash_insert (muscle_table, entry))
-        xalloc_die ();
-    }
-  else
+  muscle_entry *entry = muscle_lookup (key);
+  if (entry)
     free (entry->storage);
+  else
+    /* First insertion in the hash. */
+    entry = muscle_entry_new (key);
   entry->value = value;
   entry->storage = NULL;
 }
@@ -138,34 +162,24 @@ muscle_insert (char const *key, char const *value)
 void
 muscle_grow (const char *key, const char *val, const char *separator)
 {
-  muscle_entry probe;
-  muscle_entry *entry = NULL;
+  muscle_entry *entry = muscle_lookup (key);
 
-  probe.key = key;
-  entry = hash_lookup (muscle_table, &probe);
-
-  if (!entry)
-    {
-      /* First insertion in the hash. */
-      entry = xmalloc (sizeof *entry);
-      entry->key = key;
-      if (!hash_insert (muscle_table, entry))
-        xalloc_die ();
-      entry->value = entry->storage = xstrdup (val);
-    }
-  else
+  if (entry)
     {
       /* Grow the current value. */
       char *new_val;
-      obstack_sgrow (&muscle_obstack, entry->value);
+      obstack_printf (&muscle_obstack, "%s%s%s", entry->value, separator, val);
       free (entry->storage);
-      obstack_sgrow (&muscle_obstack, separator);
-      obstack_sgrow (&muscle_obstack, val);
-      obstack_1grow (&muscle_obstack, 0);
-      new_val = obstack_finish (&muscle_obstack);
+      new_val = obstack_finish0 (&muscle_obstack);
       entry->value = entry->storage = xstrdup (new_val);
       obstack_free (&muscle_obstack, new_val);
     }
+  else
+    {
+      /* First insertion in the hash. */
+      entry = muscle_entry_new (key);
+      entry->value = entry->storage = xstrdup (val);
+    }
 }
 
 /*------------------------------------------------------------------.
@@ -181,8 +195,7 @@ muscle_syncline_grow (char const *key, location loc)
   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);
+  extension = obstack_finish0 (&muscle_obstack);
   muscle_grow (key, extension, "");
   obstack_free (&muscle_obstack, extension);
 }
@@ -201,8 +214,9 @@ muscle_code_grow (const char *key, const char *val, location loc)
 }
 
 
-void muscle_pair_list_grow (const char *muscle,
-                           const char *a1, const char *a2)
+void
+muscle_pair_list_grow (const char *muscle,
+                       const char *a1, const char *a2)
 {
   char *pair;
   obstack_sgrow (&muscle_obstack, "[");
@@ -210,56 +224,34 @@ void muscle_pair_list_grow (const char *muscle,
   obstack_sgrow (&muscle_obstack, ", ");
   obstack_quote (&muscle_obstack, a2);
   obstack_sgrow (&muscle_obstack, "]");
-  obstack_1grow (&muscle_obstack, 0);
-  pair = obstack_finish (&muscle_obstack);
+  pair = obstack_finish0 (&muscle_obstack);
   muscle_grow (muscle, pair, ",\n");
   obstack_free (&muscle_obstack, pair);
 }
 
 
-/*----------------------------------------------------------------------------.
-| Find the value of muscle KEY.  Unlike MUSCLE_FIND, this is always reliable  |
-| to determine whether KEY has a value.                                       |
-`----------------------------------------------------------------------------*/
-
 char const *
 muscle_find_const (char const *key)
 {
-  muscle_entry probe;
-  muscle_entry *result = NULL;
-
-  probe.key = key;
-  result = hash_lookup (muscle_table, &probe);
-  if (result)
-    return result->value;
-  return NULL;
+  muscle_entry *entry = muscle_lookup (key);
+  return entry ? entry->value : NULL;
 }
 
 
-/*----------------------------------------------------------------------------.
-| Find the value of muscle KEY.  Abort if muscle_insert was invoked more      |
-| recently than muscle_grow for KEY since muscle_find can't return a          |
-| char const *.                                                               |
-`----------------------------------------------------------------------------*/
-
 char *
 muscle_find (char const *key)
 {
-  muscle_entry probe;
-  muscle_entry *result = NULL;
-
-  probe.key = key;
-  result = hash_lookup (muscle_table, &probe);
-  if (result)
+  muscle_entry *entry = muscle_lookup (key);
+  if (entry)
     {
-      aver (result->value == result->storage);
-      return result->storage;
+      aver (entry->value == entry->storage);
+      return entry->storage;
     }
   return NULL;
 }
 
 
-/* In the format `file_name:line.column', append BOUND to MUSCLE.  Use
+/* In the format 'file_name:line.column', append BOUND to MUSCLE.  Use
    digraphs for special characters in the file name.  */
 
 static void
@@ -268,19 +260,14 @@ muscle_boundary_grow (char const *key, boundary bound)
   char *extension;
   obstack_sgrow  (&muscle_obstack, "[[");
   obstack_escape (&muscle_obstack, bound.file);
-  obstack_1grow  (&muscle_obstack, ':');
-  obstack_printf (&muscle_obstack, "%d", bound.line);
-  obstack_1grow  (&muscle_obstack, '.');
-  obstack_printf (&muscle_obstack, "%d", bound.column);
-  obstack_sgrow  (&muscle_obstack, "]]");
-  obstack_1grow  (&muscle_obstack, '\0');
-  extension = obstack_finish (&muscle_obstack);
+  obstack_printf (&muscle_obstack, ":%d.%d]]", bound.line, bound.column);
+  extension = obstack_finish0 (&muscle_obstack);
   muscle_grow (key, extension, "");
   obstack_free (&muscle_obstack, extension);
 }
 
 
-/* In the format `[[file_name:line.column]], [[file_name:line.column]]',
+/* In the format '[[file_name:line.column]], [[file_name:line.column]]',
    append LOC to MUSCLE.  Use digraphs for special characters in each
    file name.  */
 
@@ -315,11 +302,10 @@ muscle_location_grow (char const *key, location loc)
 static char *
 string_decode (char const *key)
 {
-  char const *value;
+  char const *value = muscle_find_const (key);
   char *value_decoded;
   char *result;
 
-  value = muscle_find_const (key);
   if (!value)
     return NULL;
   do {
@@ -358,8 +344,7 @@ location_decode (char const *key)
           {
             char *boundary_str;
             aver (*++value == ']');
-            obstack_1grow (&muscle_obstack, '\0');
-            boundary_str = obstack_finish (&muscle_obstack);
+            boundary_str = obstack_finish0 (&muscle_obstack);
             switch (*++value)
               {
                 case ',':
@@ -396,11 +381,45 @@ muscle_user_name_list_grow (char const *key, char const *user_name,
   muscle_grow (key, "]]", "");
 }
 
+
+/** Return an allocated string that represents the %define directive
+    that performs the assignment.
+
+    @param assignment "VAR", or "VAR=VAL".
+    @param value      default value if VAL \a assignment has no '='.
+
+    For instance:
+    "foo", NULL      => "%define foo"
+    "foo", "baz"     => "%define foo baz"
+    "foo=bar", NULL  => "%define foo bar"
+    "foo=bar", "baz" => "%define foo bar"
+    "foo=", NULL     => "%define foo"
+    "foo=", "baz"    => "%define foo"
+ */
+
+static
+char *
+define_directive (char const *assignment, char const *value)
+{
+  char *eq = strchr (assignment, '=');
+  char const *fmt = !eq && value && *value ? "%%define %s %s" : "%%define %s";
+  char *res = xmalloc (strlen (fmt) + strlen (assignment)
+                       + (value ? strlen (value) : 0));
+  sprintf (res, fmt, assignment, value);
+  eq = strchr (res, '=');
+  if (eq)
+    *eq = eq[1] ? ' ' : '\0';
+  return res;
+}
+
 /** If the \a variable name is obsolete, return the name to use,
- * otherwise \a variable. */
+ * otherwise \a variable.  If the \a value is obsolete, update it too.
+ *
+ * Allocates the returned value.  */
 static
-char const *
-muscle_percent_variable_update (char const *variable)
+char *
+muscle_percent_variable_update (char const *variable, location variable_loc,
+                                char const **value)
 {
   typedef struct
   {
@@ -410,47 +429,77 @@ muscle_percent_variable_update (char const *variable)
   const conversion_type conversion[] =
     {
       { "api.push_pull", "api.push-pull", },
+      { "api.tokens.prefix", "api.token.prefix", },
+      { "lex_symbol", "api.token.constructor", },
       { "location_type", "api.location.type", },
-      { "lr.keep_unreachable_states", "lr.keep-unreachable-states", },
+      { "lr.default-reductions", "lr.default-reduction", },
+      { "lr.keep-unreachable-states", "lr.keep-unreachable-state", },
+      { "lr.keep_unreachable_states", "lr.keep-unreachable-state", },
+      { "namespace", "api.namespace", },
+      { "stype", "api.value.type", },
+      { "variant=",     "api.value.type=variant", },
+      { "variant=true", "api.value.type=variant", },
+      { NULL, NULL, }
     };
-  char const *res = variable;
-  int i;
-  for (i = 0; i < ARRAY_CARDINALITY (conversion); ++i)
-    if (STREQ (conversion[i].obsolete, variable))
-      {
-        res = conversion[i].updated;
-        break;
-      }
-  return res;
+  conversion_type const *c;
+  for (c = conversion; c->obsolete; ++c)
+    {
+      char const *eq = strchr (c->obsolete, '=');
+      if (eq
+          ? (!strncmp (c->obsolete, variable, eq - c->obsolete)
+             && STREQ (eq + 1, *value))
+          : STREQ (c->obsolete, variable))
+        {
+          char *old = define_directive (c->obsolete, *value);
+          char *upd = define_directive (c->updated, *value);
+          deprecated_directive (&variable_loc, old, upd);
+          free (old);
+          free (upd);
+          char *res = xstrdup (c->updated);
+          {
+            char *eq2 = strchr (res, '=');
+            if (eq2)
+              {
+                *eq2 = '\0';
+                *value = eq2 + 1;
+              }
+          }
+          return res;
+        }
+    }
+  return xstrdup (variable);
 }
 
 void
 muscle_percent_define_insert (char const *var, location variable_loc,
+                              muscle_kind kind,
                               char const *value,
                               muscle_percent_define_how how)
 {
   /* Backward compatibility.  */
-  char const *variable = muscle_percent_variable_update (var);
+  char *variable = muscle_percent_variable_update (var, variable_loc, &value);
   char const *name = UNIQSTR_CONCAT ("percent_define(", variable, ")");
   char const *loc_name = UNIQSTR_CONCAT ("percent_define_loc(", variable, ")");
   char const *syncline_name =
     UNIQSTR_CONCAT ("percent_define_syncline(", variable, ")");
   char const *how_name = UNIQSTR_CONCAT ("percent_define_how(", variable, ")");
+  char const *kind_name =
+    UNIQSTR_CONCAT ("percent_define_kind(", variable, ")");
 
   /* Command-line options are processed before the grammar file.  */
   if (how == MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE
       && muscle_find_const (name))
     {
+      muscle_percent_define_how how_old = atoi (muscle_find_const (how_name));
       unsigned i = 0;
-      muscle_percent_define_how how_old =
-        atoi (muscle_find_const (how_name));
       if (how_old == MUSCLE_PERCENT_DEFINE_F)
-        return;
-      complain_at_indent (variable_loc, &i,
-                          _("%%define variable %s redefined"), quote (variable));
+        goto end;
+      complain_indent (&variable_loc, complaint, &i,
+                       _("%%define variable %s redefined"),
+                       quote (variable));
       i += SUB_INDENT;
-      complain_at_indent (muscle_percent_define_get_loc (variable), &i,
-                          _("previous definition"));
+      location loc = muscle_percent_define_get_loc (variable);
+      complain_indent (&loc, complaint, &i, _("previous definition"));
     }
 
   MUSCLE_INSERT_STRING (name, value);
@@ -461,63 +510,73 @@ muscle_percent_define_insert (char const *var, location variable_loc,
   muscle_user_name_list_grow ("percent_define_user_variables", variable,
                               variable_loc);
   MUSCLE_INSERT_INT (how_name, how);
+  MUSCLE_INSERT_STRING (kind_name, muscle_kind_string (kind));
+ end:
+  free (variable);
 }
 
-char *
-muscle_percent_define_get (char const *variable)
+/* 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 *name;
-  char const *usage_name;
-  char *value;
+  char const *name = UNIQSTR_CONCAT ("percent_define(", variable, ")");
+  char const *val = value ? "" : "false";
 
-  name = UNIQSTR_CONCAT ("percent_define(", variable, ")");
-  usage_name = UNIQSTR_CONCAT ("percent_define_bison_variables(",
-                               variable, ")");
+  /* Don't complain is VARIABLE is already defined, but be sure to set
+     its value to VAL.  */
+  if (!muscle_find_const (name))
+    muscle_percent_define_insert (variable, loc, muscle_keyword, val,
+                                  MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE);
+  if (muscle_percent_define_flag_if (variable) != value)
+    muscle_percent_define_insert (variable, loc, muscle_keyword, val,
+                                  MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE);
+}
 
-  muscle_insert (usage_name, "");
-  value = string_decode (name);
+char *
+muscle_percent_define_get (char const *variable)
+{
+  char const *name = UNIQSTR_CONCAT ("percent_define(", variable, ")");
+  char const *usage_name =
+    UNIQSTR_CONCAT ("percent_define_bison_variables(", variable, ")");
+  char *value = string_decode (name);
   if (!value)
     value = xstrdup ("");
+
+  muscle_insert (usage_name, "");
   return value;
 }
 
 location
 muscle_percent_define_get_loc (char const *variable)
 {
-  char const *loc_name;
-  loc_name = UNIQSTR_CONCAT ("percent_define_loc(", variable, ")");
+  char const *loc_name = UNIQSTR_CONCAT ("percent_define_loc(", variable, ")");
   if (!muscle_find_const (loc_name))
-    fatal(_("%s: undefined %%define variable %s"),
-          "muscle_percent_define_get_loc", quote (variable));
+    complain (NULL, fatal, _("%s: undefined %%define variable %s"),
+              "muscle_percent_define_get_loc", quote (variable));
   return location_decode (loc_name);
 }
 
 char const *
 muscle_percent_define_get_syncline (char const *variable)
 {
-  char const *syncline_name;
-  char const *syncline;
-  syncline_name =
+  char const *syncline_name =
     UNIQSTR_CONCAT ("percent_define_syncline(", variable, ")");
-  syncline = muscle_find_const (syncline_name);
+  char const *syncline = muscle_find_const (syncline_name);
   if (!syncline)
-    fatal(_("%s: undefined %%define variable %s"),
-          "muscle_percent_define_get_syncline", quote (variable));
+    complain (NULL, fatal, _("%s: undefined %%define variable %s"),
+              "muscle_percent_define_get_syncline", quote (variable));
   return syncline;
 }
 
 bool
 muscle_percent_define_ifdef (char const *variable)
 {
-  char const *name;
-  char const *usage_name;
-  char const *value;
-
-  name = UNIQSTR_CONCAT ("percent_define(", variable, ")");
-  usage_name =
+  char const *name = UNIQSTR_CONCAT ("percent_define(", variable, ")");
+  char const *usage_name =
     UNIQSTR_CONCAT ("percent_define_bison_variables(", variable, ")");
-
-  value = muscle_find_const (name);
+  char const *value = muscle_find_const (name);
   if (value)
     {
       muscle_insert (usage_name, "");
@@ -530,31 +589,30 @@ muscle_percent_define_ifdef (char const *variable)
 bool
 muscle_percent_define_flag_if (char const *variable)
 {
-  char const *invalid_boolean_name;
-  bool result = false;
-
-  invalid_boolean_name =
+  char const *invalid_boolean_name =
     UNIQSTR_CONCAT ("percent_define_invalid_boolean(", variable, ")");
+  bool result = false;
 
   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 (&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 (NULL, fatal, _("%s: undefined %%define variable %s"),
+              "muscle_percent_define_flag", quote (variable));
 
   return result;
 }
@@ -562,12 +620,9 @@ muscle_percent_define_flag_if (char const *variable)
 void
 muscle_percent_define_default (char const *variable, char const *value)
 {
-  char const *name;
-  char const *loc_name;
-  char const *syncline_name;
-  name = UNIQSTR_CONCAT ("percent_define(", variable, ")");
-  loc_name = UNIQSTR_CONCAT ("percent_define_loc(", variable, ")");
-  syncline_name =
+  char const *name = UNIQSTR_CONCAT ("percent_define(", variable, ")");
+  char const *loc_name = UNIQSTR_CONCAT ("percent_define_loc(", variable, ")");
+  char const *syncline_name =
     UNIQSTR_CONCAT ("percent_define_syncline(", variable, ")");
   if (!muscle_find_const (name))
     {
@@ -588,30 +643,26 @@ muscle_percent_define_check_values (char const * const *values)
   for (; *values; ++values)
     {
       char const * const *variablep = values;
-      char const *name;
-      char *value;
-
-      name = UNIQSTR_CONCAT ("percent_define(", *variablep, ")");
-
-      value = string_decode (name);
+      char const *name = UNIQSTR_CONCAT ("percent_define(", *variablep, ")");
+      char *value = string_decode (name);
       if (value)
         {
           for (++values; *values; ++values)
             {
-              if (0 == strcmp (value, *values))
+              if (STREQ (value, *values))
                 break;
             }
           if (!*values)
             {
               unsigned i = 0;
               location loc = muscle_percent_define_get_loc (*variablep);
-              complain_at_indent (loc, &i,
-                                _("invalid value for %%define variable %s: %s"),
-                                  quote (*variablep), quote_n (1, value));
+              complain_indent (&loc, complaint, &i,
+                               _("invalid value for %%define variable %s: %s"),
+                               quote (*variablep), quote_n (1, value));
               i += SUB_INDENT;
               for (values = variablep + 1; *values; ++values)
-                complain_at_indent (loc, &i, _("accepted value: %s"),
-                                    quote (*values));
+                complain_indent (&loc, complaint | no_caret | silent, &i,
+                                 _("accepted value: %s"), quote (*values));
             }
           else
             {
@@ -621,8 +672,8 @@ muscle_percent_define_check_values (char const * const *values)
           free (value);
         }
       else
-        fatal (_("%s: undefined %%define variable %s"),
-               "muscle_percent_define_check_values", quote (*variablep));
+        complain (NULL, fatal, _("%s: undefined %%define variable %s"),
+                  "muscle_percent_define_check_values", quote (*variablep));
     }
 }
 
@@ -630,8 +681,7 @@ void
 muscle_percent_code_grow (char const *qualifier, location qualifier_loc,
                           char const *code, location code_loc)
 {
-  char const *name;
-  name = UNIQSTR_CONCAT ("percent_code(", qualifier, ")");
+  char const *name = UNIQSTR_CONCAT ("percent_code(", qualifier, ")");
   muscle_code_grow (name, code, code_loc);
   muscle_user_name_list_grow ("percent_code_user_qualifiers", qualifier,
                                qualifier_loc);
@@ -645,8 +695,9 @@ muscle_percent_code_grow (char const *qualifier, location qualifier_loc,
 static inline bool
 muscle_m4_output (muscle_entry *entry, FILE *out)
 {
-  fprintf (out, "m4_define([b4_%s],\n", entry->key);
-  fprintf (out, "[[%s]])\n\n\n", entry->value);
+  fprintf (out,
+           "m4_define([b4_%s],\n"
+           "[[%s]])\n\n\n", entry->key, entry->value);
   return true;
 }
 
@@ -657,11 +708,6 @@ muscle_m4_output_processor (void *entry, void *out)
 }
 
 
-/*----------------------------------------------------------------.
-| Output the definition of all the current muscles into a list of |
-| m4_defines.                                                     |
-`----------------------------------------------------------------*/
-
 void
 muscles_m4_output (FILE *out)
 {
index 6278f3b9e04768d1d3646171f455cb75e87e30e5..af6b615c3195f6a5bb9fb594b4cc7fb5da071f8d 100644 (file)
@@ -1,7 +1,6 @@
 /* Muscle table manager for Bison,
 
-   Copyright (C) 2001-2003, 2006-2007, 2009-2013 Free Software
-   Foundation, Inc.
+   Copyright (C) 2001-2003, 2006-2013 Free Software Foundation, Inc.
 
    This file is part of Bison, the GNU Compiler Compiler.
 
 
 # include "location.h"
 
+/* The kind of value associated to this muscle, depending on the
+   syntax of the value: keyword (no delimiter, e.g., true), string
+   (double quotes, e.g., "foo.h"), or code (braces, e.g., {int}).  */
+typedef enum
+{
+  muscle_code,
+  muscle_keyword,
+  muscle_string
+} muscle_kind;
+
+/* Conversion from string.  */
+muscle_kind muscle_kind_new (char const *k);
+
+/* Conversion to string.  */
+char const *muscle_kind_string (muscle_kind k);
+
+
+/* Create the MUSCLE_TABLE, and initialize it with default values.
+   Also set up the MUSCLE_OBSTACK.  */
 void muscle_init (void);
+
+/* Insert (KEY, VALUE).  If KEY already existed, overwrite the
+   previous value.  Otherwise create as a muscle_string type.  */
 void muscle_insert (char const *key, char const *value);
+
+/* Find the value of muscle KEY.  Unlike MUSCLE_FIND, this is always
+   reliable to determine whether KEY has a value.  */
 char const *muscle_find_const (char const *key);
+
+/* Find the value of muscle KEY.  Abort if muscle_insert was invoked
+   more recently than muscle_grow for KEY since muscle_find can't
+   return a char const *.  */
 char *muscle_find (char const *key);
+
+/* Free all the memory consumed by the muscle machinery only.  */
 void muscle_free (void);
 
 
 /* An obstack dedicated to receive muscle keys and values.  */
 extern struct obstack muscle_obstack;
 
-#define MUSCLE_INSERT_BOOL(Key, Value)                          \
-  do {                                                          \
-    int v = Value;                                              \
-    MUSCLE_INSERT_INT (Key, v);                                 \
+# define MUSCLE_INSERT_BOOL(Key, Value)         \
+  do {                                          \
+    int v__ = Value;                            \
+    MUSCLE_INSERT_INT (Key, v__);               \
   } while (0)
 
-#define MUSCLE_INSERT_INT(Key, Value)                           \
+# define MUSCLE_INSERTF(Key, Format, Value)                     \
   do {                                                          \
-    obstack_printf (&muscle_obstack, "%d", Value);              \
-    obstack_1grow (&muscle_obstack, 0);                         \
-    muscle_insert (Key, obstack_finish (&muscle_obstack));      \
+    obstack_printf (&muscle_obstack, Format, Value);            \
+    muscle_insert (Key, obstack_finish0 (&muscle_obstack));     \
   } while (0)
 
-#define MUSCLE_INSERT_LONG_INT(Key, Value)                      \
-  do {                                                          \
-    obstack_printf (&muscle_obstack, "%ld", Value);             \
-    obstack_1grow (&muscle_obstack, 0);                         \
-    muscle_insert (Key, obstack_finish (&muscle_obstack));      \
-  } while (0)
+# define MUSCLE_INSERT_INT(Key, Value)          \
+  MUSCLE_INSERTF(Key, "%d", 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)
+# define MUSCLE_INSERT_LONG_INT(Key, Value)     \
+  MUSCLE_INSERTF(Key, "%ld", Value)
 
-#define MUSCLE_INSERT_STRING(Key, Value)                        \
+/* Key -> Value, but don't apply escaping to Value. */
+# define MUSCLE_INSERT_STRING_RAW(Key, Value)   \
+  MUSCLE_INSERTF(Key, "%s", Value)
+
+/* Key -> Value, applying M4 escaping to Value. */
+# define MUSCLE_INSERT_STRING(Key, Value)                       \
   do {                                                          \
     obstack_escape (&muscle_obstack, Value);                    \
-    obstack_1grow (&muscle_obstack, 0);                         \
-    muscle_insert (Key, obstack_finish (&muscle_obstack));      \
+    muscle_insert (Key, obstack_finish0 (&muscle_obstack));     \
   } while (0)
 
-#define MUSCLE_INSERT_C_STRING(Key, Value)                      \
-  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)
+/* Key -> Value, applying C escaping to Value (and then M4). */
+# define MUSCLE_INSERT_C_STRING(Key, Value)                     \
+  MUSCLE_INSERT_STRING(Key, quotearg_style (c_quoting_style, Value))
+
 
 /* Append VALUE to the current value of KEY.  If KEY did not already
    exist, create it.  Use MUSCLE_OBSTACK.  De-allocate the previously
    associated value.  Copy VALUE and SEPARATOR.  */
-
 void muscle_grow (const char *key, const char *value, const char *separator);
 
 
 /* Append VALUE to the current value of KEY, using muscle_grow.  But
    in addition, issue a synchronization line for the location LOC.  */
-
 void muscle_code_grow (const char *key, const char *value, location loc);
 
 
@@ -99,14 +119,15 @@ void muscle_pair_list_grow (const char *muscle,
 
 /* 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 `]'.  */
+   with digraphs, so it must not contain '[' or ']'.  */
 void muscle_user_name_list_grow (char const *key, char const *user_name,
                                  location loc);
 
 /* Indicates whether a variable's value was specified with -D/--define, with
    -F/--force-define, or in the grammar file.  */
 typedef enum {
-  MUSCLE_PERCENT_DEFINE_D = 0, MUSCLE_PERCENT_DEFINE_F,
+  MUSCLE_PERCENT_DEFINE_D = 0,
+  MUSCLE_PERCENT_DEFINE_F,
   MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE
 } muscle_percent_define_how;
 
@@ -120,9 +141,17 @@ typedef enum {
    this as a user occurrence of VARIABLE by invoking
    muscle_user_name_list_grow.  */
 void muscle_percent_define_insert (char const *variable, location variable_loc,
+                                   muscle_kind kind,
                                    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
@@ -186,6 +215,8 @@ void muscle_percent_define_check_values (char const * const *values);
 void muscle_percent_code_grow (char const *qualifier, location qualifier_loc,
                                char const *code, location code_loc);
 
+/* Output the definition of all the current muscles into a list of
+   m4_defines.  */
 void muscles_m4_output (FILE *out);
 
 #endif /* not MUSCLE_TAB_H_ */
index 9ae9d62cbc2a8af08ae290f8dcd775a196be9212..84d02d7adbdbe4139dbd52008f47644b6fab1365 100644 (file)
@@ -20,8 +20,8 @@
 #ifndef NAMED_REF_H_
 # define NAMED_REF_H_
 
-#include "location.h"
-#include "uniqstr.h"
+# include "location.h"
+# include "uniqstr.h"
 
 /* Named reference object. Keeps information about
    a symbolic name of a symbol in a rule. */
index 209b3d29143c8f806babf7968150ccad3f4bd993..a150f5f5c7828f11dde035e018bb02fd3f0dcb6c 100644 (file)
@@ -47,8 +47,8 @@ nullable_print (FILE *out)
   int i;
   fputs ("NULLABLE\n", out);
   for (i = ntokens; i < nsyms; i++)
-    fprintf (out, "\t%s: %s\n", symbols[i]->tag,
-            nullable[i - ntokens] ? "yes" : "no");
+    fprintf (out, "  %s: %s\n", symbols[i]->tag,
+             nullable[i - ntokens] ? "yes" : "no");
   fputs ("\n\n", out);
 }
 
@@ -77,52 +77,52 @@ nullable_compute (void)
   for (ruleno = 0; ruleno < nrules; ++ruleno)
     if (rules[ruleno].useful)
       {
-       rule *rules_ruleno = &rules[ruleno];
-       if (rules_ruleno->rhs[0] >= 0)
-         {
-           /* This rule has a non empty RHS. */
-           item_number *rp = NULL;
-           bool any_tokens = false;
-           for (rp = rules_ruleno->rhs; *rp >= 0; ++rp)
-             if (ISTOKEN (*rp))
-               any_tokens = true;
-
-           /* This rule has only nonterminals: schedule it for the second
-              pass.  */
-           if (!any_tokens)
-             for (rp = rules_ruleno->rhs; *rp >= 0; ++rp)
-               {
-                 rcount[ruleno]++;
-                 p->next = rsets[*rp - ntokens];
-                 p->value = rules_ruleno;
-                 rsets[*rp - ntokens] = p;
-                 p++;
-               }
-         }
-       else
-         {
-           /* This rule has an empty RHS. */
-           aver (item_number_as_rule_number (rules_ruleno->rhs[0])
-                 == ruleno);
-           if (rules_ruleno->useful
-               && ! nullable[rules_ruleno->lhs->number - ntokens])
-             {
-               nullable[rules_ruleno->lhs->number - ntokens] = true;
-               *s2++ = rules_ruleno->lhs->number;
-             }
-         }
+        rule *rules_ruleno = &rules[ruleno];
+        if (rules_ruleno->rhs[0] >= 0)
+          {
+            /* This rule has a non empty RHS. */
+            item_number *rp = NULL;
+            bool any_tokens = false;
+            for (rp = rules_ruleno->rhs; *rp >= 0; ++rp)
+              if (ISTOKEN (*rp))
+                any_tokens = true;
+
+            /* This rule has only nonterminals: schedule it for the second
+               pass.  */
+            if (!any_tokens)
+              for (rp = rules_ruleno->rhs; *rp >= 0; ++rp)
+                {
+                  rcount[ruleno]++;
+                  p->next = rsets[*rp - ntokens];
+                  p->value = rules_ruleno;
+                  rsets[*rp - ntokens] = p;
+                  p++;
+                }
+          }
+        else
+          {
+            /* This rule has an empty RHS. */
+            aver (item_number_as_rule_number (rules_ruleno->rhs[0])
+                  == ruleno);
+            if (rules_ruleno->useful
+                && ! nullable[rules_ruleno->lhs->number - ntokens])
+              {
+                nullable[rules_ruleno->lhs->number - ntokens] = true;
+                *s2++ = rules_ruleno->lhs->number;
+              }
+          }
       }
 
   while (s1 < s2)
     for (p = rsets[*s1++ - ntokens]; p; p = p->next)
       {
-       rule *r = p->value;
-       if (--rcount[r->number] == 0)
-         if (r->useful && ! nullable[r->lhs->number - ntokens])
-           {
-             nullable[r->lhs->number - ntokens] = true;
-             *s2++ = r->lhs->number;
-           }
+        rule *r = p->value;
+        if (--rcount[r->number] == 0)
+          if (r->useful && ! nullable[r->lhs->number - ntokens])
+            {
+              nullable[r->lhs->number - ntokens] = true;
+              *s2++ = r->lhs->number;
+            }
       }
 
   free (squeue);
index ed25db0c00e054c2ff7cc7a9359c63f4384649ae..b543cbab97192754a6be7a18667249335e58c79e 100644 (file)
@@ -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>
@@ -52,51 +53,48 @@ 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_printf (&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_printf (&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_printf (&format_obstack, "%s_min", name);                    \
-  obstack_1grow (&format_obstack, 0);                                  \
-  MUSCLE_INSERT_LONG_INT (obstack_finish (&format_obstack), lmin);     \
-  obstack_printf (&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_printf (&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_printf (&format_obstack, "%6d", table_data[i]);           \
+      if (table_data[i] < min)                                          \
+        min = table_data[i];                                            \
+      if (max < table_data[i])                                          \
+        max = table_data[i];                                            \
+    }                                                                   \
+  muscle_insert (name, obstack_finish0 (&format_obstack));              \
+                                                                        \
+  lmin = min;                                                           \
+  lmax = max;                                                           \
+  /* Build 'NAME_min' and 'NAME_max' in the obstack. */                 \
+  obstack_printf (&format_obstack, "%s_min", name);                     \
+  MUSCLE_INSERT_LONG_INT (obstack_finish0 (&format_obstack), lmin);     \
+  obstack_printf (&format_obstack, "%s_max", name);                     \
+  MUSCLE_INSERT_LONG_INT (obstack_finish0 (&format_obstack), lmax);     \
 }
 
 GENERATE_MUSCLE_INSERT_TABLE(muscle_insert_unsigned_int_table, unsigned int)
@@ -104,7 +102,6 @@ GENERATE_MUSCLE_INSERT_TABLE(muscle_insert_int_table, int)
 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)
 
 
@@ -152,13 +149,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.  */
   {
@@ -170,30 +168,29 @@ prepare_symbols (void)
     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, ' ');
+        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[");
 
     /* Finish table and store. */
-    obstack_1grow (&format_obstack, 0);
-    muscle_insert ("tname", obstack_finish (&format_obstack));
+    muscle_insert ("tname", obstack_finish0 (&format_obstack));
   }
 
   /* Output YYTOKNUM. */
@@ -203,71 +200,60 @@ prepare_symbols (void)
     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);
 }
 
 /*--------------------------------------------.
@@ -282,7 +268,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);
@@ -291,6 +277,73 @@ prepare_states (void)
 }
 
 
+/*-------------------------------------------------------.
+| 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)
+    res = (*lhs)->number - (*rhs)->number;
+  return res;
+}
+
+
+/*----------------------------------------------------------------.
+| 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.  |
@@ -305,17 +358,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);
+        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)
@@ -327,105 +381,95 @@ 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_printf (&format_obstack, "symbol(%d, %s)",        \
+                      i, Entry);                                \
+      key = obstack_finish0 (&format_obstack);
 
-/*---------------------------------------------------.
-| Output the symbol destructors or printers to OUT.  |
-`---------------------------------------------------*/
+#define SET_KEY2(Entry, Suffix)                                 \
+      obstack_printf (&format_obstack, "symbol(%d, %s_%s)",     \
+                      i, Entry, Suffix);                        \
+      key = obstack_finish0 (&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);
 }
 
 
@@ -436,30 +480,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
@@ -471,11 +515,12 @@ prepare_actions (void)
      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.  |
 `--------------------------------------------*/
@@ -484,13 +529,11 @@ static void
 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
@@ -501,48 +544,28 @@ muscles_output (FILE *out)
 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
@@ -552,6 +575,7 @@ output_skeleton (void)
      <http://lists.gnu.org/archive/html/bug-bison/2008-07/msg00000.html>
      for details.  */
   {
+    char const *argv[10];
     int i = 0;
     argv[i++] = m4;
 
@@ -568,47 +592,44 @@ output_skeleton (void)
       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);
 }
@@ -616,21 +637,14 @@ output_skeleton (void)
 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);
   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);
@@ -666,7 +680,7 @@ prepare (void)
     /* 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 ());
   }
 }
 
@@ -684,6 +698,7 @@ output (void)
   prepare_rules ();
   prepare_states ();
   prepare_actions ();
+  prepare_symbol_definitions ();
 
   prepare ();
 
@@ -694,8 +709,8 @@ output (void)
 }
 
 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;
 }
index f82a7ac50abad83db5848ac494a2bf0e16f500ed..63a0ca803a2cf6855929869ba6bf5c1c326c6650 100644 (file)
@@ -23,6 +23,8 @@
 
 /* Output the parsing tables and the parser code to FTABLE.  */
 void output (void);
-char const *compute_pkgdatadir (void);
+
+/* Where our data files are installed.  */
+char const *pkgdatadir (void);
 
 #endif /* !OUTPUT_H_ */
index a36b7426824962ca7ca81f2b910585d14aa13dc5..2cf9e86c815a0df084a556679b7c6547508bc36f 100644 (file)
@@ -1,19 +1,19 @@
-/* A Bison parser, made by GNU Bison 2.6.5.63-3ada.  */
+/* A Bison parser, made by GNU Bison 2.7.1127-02879-dirty.  */
 
 /* Bison implementation for Yacc-like parsers in C
-   
-      Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc.
-   
+
+   Copyright (C) 1984, 1989-1990, 2000-2013 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/>.  */
 
@@ -26,7 +26,7 @@
    special exception, which will cause the skeleton and the resulting
    Bison output files to be licensed under the GNU General Public
    License without this special exception.
-   
+
    This special exception was added by the Free Software Foundation in
    version 2.2 of Bison.  */
 
 #define YYBISON 1
 
 /* Bison version.  */
-#define YYBISON_VERSION "2.6.5.63-3ada"
+#define YYBISON_VERSION "2.7.1127-02879-dirty"
 
 /* Skeleton name.  */
 #define YYSKELETON_NAME "yacc.c"
 
 /* Pure parsers.  */
-#define YYPURE 1
+#define YYPURE 2
 
 /* Push parsers.  */
 #define YYPUSH 0
 #define yyparse         gram_parse
 #define yylex           gram_lex
 #define yyerror         gram_error
-#define yylval          gram_lval
-#define yychar          gram_char
 #define yydebug         gram_debug
 #define yynerrs         gram_nerrs
-#define yylloc          gram_lloc
+
 
 /* Copy the first part of user declarations.  */
-/* Line 360 of yacc.c  */
-#line 1 "parse-gram.y"
+#line 1 "src/parse-gram.y" /* yacc.c:356  */
 /* Bison Grammar Parser                             -*- C -*-
 
    Copyright (C) 2002-2013 Free Software Foundation, Inc.
 #include "files.h"
 #include "getargs.h"
 #include "gram.h"
-#include "muscle-tab.h"
 #include "named-ref.h"
 #include "quotearg.h"
 #include "reader.h"
 #include "symlist.h"
+#include "symtab.h"
 #include "scan-gram.h"
 #include "scan-code.h"
 #include "xmemdup0.h"
 static YYLTYPE lloc_default (YYLTYPE const *, int);
 
 #define YY_LOCATION_PRINT(File, Loc) \
-         location_print (File, Loc)
+          location_print (Loc, File)
 
 static void version_check (location const *loc, char const *version);
 
-/* Request detailed syntax error messages, and pass them to GRAM_ERROR.
-   FIXME: depends on the undocumented availability of YYLLOC.  */
-#undef  yyerror
-#define yyerror(Msg) \
-       gram_error (&yylloc, Msg)
 static void gram_error (location const *, char const *);
 
+/* A string that describes a char (e.g., 'a' -> "'a'").  */
 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)
-{
-  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
-
-/* Line 360 of yacc.c  */
-#line 173 "parse-gram.c"
+#line 125 "src/parse-gram.c" /* yacc.c:356  */
 
 # ifndef YY_NULL
 #  if defined __cplusplus && 201103L <= __cplusplus
@@ -188,13 +140,13 @@ current_lhs(symbol *sym, location loc, named_ref *ref)
 #endif
 
 /* In a future release of Bison, this section will be replaced
-   by #include "parse-gram.h".  */
-#ifndef YY_GRAM_Y_TAB_H_INCLUDED
-# define YY_GRAM_Y_TAB_H_INCLUDED
-/* Enabling traces.  */
+   by #include "src/parse-gram.h".  */
+#ifndef YY_GRAM_SRC_PARSE_GRAM_H_INCLUDED
+# define YY_GRAM_SRC_PARSE_GRAM_H_INCLUDED
+/* Debug traces.  */
 #ifndef GRAM_DEBUG
 # if defined YYDEBUG
-#  if YYDEBUG
+#if YYDEBUG
 #   define GRAM_DEBUG 1
 #  else
 #   define GRAM_DEBUG 0
@@ -206,190 +158,198 @@ current_lhs(symbol *sym, location loc, named_ref *ref)
 #if GRAM_DEBUG
 extern int gram_debug;
 #endif
+/* "%code requires" blocks.  */
+#line 218 "src/parse-gram.y" /* yacc.c:372  */
+
+  typedef enum
+  {
+    param_none   = 0,
+    param_lex    = 1 << 0,
+    param_parse  = 1 << 1,
+    param_both   = param_lex | param_parse
+  } param_type;
+
+#line 649 "src/parse-gram.y" /* yacc.c:372  */
+#include "muscle-tab.h"
 
-/* Tokens.  */
+#line 176 "src/parse-gram.c" /* yacc.c:372  */
+
+/* Token type.  */
 #ifndef GRAM_TOKENTYPE
 # define GRAM_TOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum gram_tokentype {
-     GRAM_EOF = 0,
-     STRING = 258,
-     INT = 259,
-     PERCENT_TOKEN = 260,
-     PERCENT_NTERM = 261,
-     PERCENT_TYPE = 262,
-     PERCENT_DESTRUCTOR = 263,
-     PERCENT_PRINTER = 264,
-     PERCENT_LEFT = 265,
-     PERCENT_RIGHT = 266,
-     PERCENT_NONASSOC = 267,
-     PERCENT_PREC = 268,
-     PERCENT_DPREC = 269,
-     PERCENT_MERGE = 270,
-     PERCENT_CODE = 271,
-     PERCENT_DEBUG = 272,
-     PERCENT_DEFAULT_PREC = 273,
-     PERCENT_DEFINE = 274,
-     PERCENT_DEFINES = 275,
-     PERCENT_ERROR_VERBOSE = 276,
-     PERCENT_EXPECT = 277,
-     PERCENT_EXPECT_RR = 278,
-     PERCENT_FILE_PREFIX = 279,
-     PERCENT_GLR_PARSER = 280,
-     PERCENT_INITIAL_ACTION = 281,
-     PERCENT_LANGUAGE = 282,
-     PERCENT_LEX_PARAM = 283,
-     PERCENT_LOCATIONS = 284,
-     PERCENT_NAME_PREFIX = 285,
-     PERCENT_NO_DEFAULT_PREC = 286,
-     PERCENT_NO_LINES = 287,
-     PERCENT_NONDETERMINISTIC_PARSER = 288,
-     PERCENT_OUTPUT = 289,
-     PERCENT_PARSE_PARAM = 290,
-     PERCENT_PURE_PARSER = 291,
-     PERCENT_REQUIRE = 292,
-     PERCENT_SKELETON = 293,
-     PERCENT_START = 294,
-     PERCENT_TOKEN_TABLE = 295,
-     PERCENT_VERBOSE = 296,
-     PERCENT_YACC = 297,
-     BRACED_CODE = 298,
-     BRACKETED_ID = 299,
-     CHAR = 300,
-     EPILOGUE = 301,
-     EQUAL = 302,
-     ID = 303,
-     ID_COLON = 304,
-     PERCENT_PERCENT = 305,
-     PIPE = 306,
-     PROLOGUE = 307,
-     SEMICOLON = 308,
-     TYPE = 309,
-     TYPE_TAG_ANY = 310,
-     TYPE_TAG_NONE = 311,
-     PERCENT_UNION = 312
-   };
+  enum gram_tokentype
+  {
+    GRAM_EOF = 0,
+    STRING = 258,
+    PERCENT_TOKEN = 259,
+    PERCENT_NTERM = 260,
+    PERCENT_TYPE = 261,
+    PERCENT_DESTRUCTOR = 262,
+    PERCENT_PRINTER = 263,
+    PERCENT_LEFT = 264,
+    PERCENT_RIGHT = 265,
+    PERCENT_NONASSOC = 266,
+    PERCENT_PRECEDENCE = 267,
+    PERCENT_PREC = 268,
+    PERCENT_DPREC = 269,
+    PERCENT_MERGE = 270,
+    PERCENT_CODE = 271,
+    PERCENT_DEFAULT_PREC = 272,
+    PERCENT_DEFINE = 273,
+    PERCENT_DEFINES = 274,
+    PERCENT_ERROR_VERBOSE = 275,
+    PERCENT_EXPECT = 276,
+    PERCENT_EXPECT_RR = 277,
+    PERCENT_FLAG = 278,
+    PERCENT_FILE_PREFIX = 279,
+    PERCENT_GLR_PARSER = 280,
+    PERCENT_INITIAL_ACTION = 281,
+    PERCENT_LANGUAGE = 282,
+    PERCENT_NAME_PREFIX = 283,
+    PERCENT_NO_DEFAULT_PREC = 284,
+    PERCENT_NO_LINES = 285,
+    PERCENT_NONDETERMINISTIC_PARSER = 286,
+    PERCENT_OUTPUT = 287,
+    PERCENT_REQUIRE = 288,
+    PERCENT_SKELETON = 289,
+    PERCENT_START = 290,
+    PERCENT_TOKEN_TABLE = 291,
+    PERCENT_VERBOSE = 292,
+    PERCENT_YACC = 293,
+    BRACED_CODE = 294,
+    BRACED_PREDICATE = 295,
+    BRACKETED_ID = 296,
+    CHAR = 297,
+    EPILOGUE = 298,
+    EQUAL = 299,
+    ID = 300,
+    ID_COLON = 301,
+    PERCENT_PERCENT = 302,
+    PIPE = 303,
+    PROLOGUE = 304,
+    SEMICOLON = 305,
+    TAG = 306,
+    TAG_ANY = 307,
+    TAG_NONE = 308,
+    INT = 309,
+    PERCENT_PARAM = 310,
+    PERCENT_UNION = 311,
+    PERCENT_EMPTY = 312
+  };
 #endif
-/* Tokens.  */
-#define GRAM_EOF 0
-#define STRING 258
-#define INT 259
-#define PERCENT_TOKEN 260
-#define PERCENT_NTERM 261
-#define PERCENT_TYPE 262
-#define PERCENT_DESTRUCTOR 263
-#define PERCENT_PRINTER 264
-#define PERCENT_LEFT 265
-#define PERCENT_RIGHT 266
-#define PERCENT_NONASSOC 267
-#define PERCENT_PREC 268
-#define PERCENT_DPREC 269
-#define PERCENT_MERGE 270
-#define PERCENT_CODE 271
-#define PERCENT_DEBUG 272
-#define PERCENT_DEFAULT_PREC 273
-#define PERCENT_DEFINE 274
-#define PERCENT_DEFINES 275
-#define PERCENT_ERROR_VERBOSE 276
-#define PERCENT_EXPECT 277
-#define PERCENT_EXPECT_RR 278
-#define PERCENT_FILE_PREFIX 279
-#define PERCENT_GLR_PARSER 280
-#define PERCENT_INITIAL_ACTION 281
-#define PERCENT_LANGUAGE 282
-#define PERCENT_LEX_PARAM 283
-#define PERCENT_LOCATIONS 284
-#define PERCENT_NAME_PREFIX 285
-#define PERCENT_NO_DEFAULT_PREC 286
-#define PERCENT_NO_LINES 287
-#define PERCENT_NONDETERMINISTIC_PARSER 288
-#define PERCENT_OUTPUT 289
-#define PERCENT_PARSE_PARAM 290
-#define PERCENT_PURE_PARSER 291
-#define PERCENT_REQUIRE 292
-#define PERCENT_SKELETON 293
-#define PERCENT_START 294
-#define PERCENT_TOKEN_TABLE 295
-#define PERCENT_VERBOSE 296
-#define PERCENT_YACC 297
-#define BRACED_CODE 298
-#define BRACKETED_ID 299
-#define CHAR 300
-#define EPILOGUE 301
-#define EQUAL 302
-#define ID 303
-#define ID_COLON 304
-#define PERCENT_PERCENT 305
-#define PIPE 306
-#define PROLOGUE 307
-#define SEMICOLON 308
-#define TYPE 309
-#define TYPE_TAG_ANY 310
-#define TYPE_TAG_NONE 311
-#define PERCENT_UNION 312
-
-
 
+/* Value type.  */
 #if ! defined GRAM_STYPE && ! defined GRAM_STYPE_IS_DECLARED
-typedef union GRAM_STYPE
+typedef union GRAM_STYPE GRAM_STYPE;
+union GRAM_STYPE
 {
-/* Line 376 of yacc.c  */
-#line 115 "parse-gram.y"
+#line 170 "src/parse-gram.y" /* yacc.c:372  */
+unsigned char character;
+#line 177 "src/parse-gram.y" /* yacc.c:372  */
 
-  symbol *symbol;
-  symbol_list *list;
-  int integer;
-  char const *chars;
   char *code;
-  assoc assoc;
-  uniqstr uniqstr;
-  unsigned char character;
-  named_ref *named_ref;
+  char const *chars;
+
+#line 188 "src/parse-gram.y" /* yacc.c:372  */
+uniqstr uniqstr;
+#line 196 "src/parse-gram.y" /* yacc.c:372  */
+int integer;
+#line 200 "src/parse-gram.y" /* yacc.c:372  */
+symbol *symbol;
+#line 205 "src/parse-gram.y" /* yacc.c:372  */
+assoc assoc;
+#line 208 "src/parse-gram.y" /* yacc.c:372  */
+symbol_list *list;
+#line 211 "src/parse-gram.y" /* yacc.c:372  */
+named_ref *named_ref;
+#line 238 "src/parse-gram.y" /* yacc.c:372  */
+param_type param;
+#line 413 "src/parse-gram.y" /* yacc.c:372  */
+code_props_type code_type;
+#line 651 "src/parse-gram.y" /* yacc.c:372  */
+
+  struct
+  {
+    char const *chars;
+    muscle_kind kind;
+  } value;
 
 
-/* Line 376 of yacc.c  */
-#line 353 "parse-gram.c"
-} GRAM_STYPE;
+#line 279 "src/parse-gram.c" /* yacc.c:372  */
+};
 # define GRAM_STYPE_IS_TRIVIAL 1
-# define gram_stype GRAM_STYPE /* obsolescent; will be withdrawn */
 # define GRAM_STYPE_IS_DECLARED 1
 #endif
 
+/* Location type.  */
 #if ! defined GRAM_LTYPE && ! defined GRAM_LTYPE_IS_DECLARED
-typedef struct GRAM_LTYPE
+typedef struct GRAM_LTYPE GRAM_LTYPE;
+struct GRAM_LTYPE
 {
   int first_line;
   int first_column;
   int last_line;
   int last_column;
-} GRAM_LTYPE;
-# define gram_ltype GRAM_LTYPE /* obsolescent; will be withdrawn */
+};
 # define GRAM_LTYPE_IS_DECLARED 1
 # define GRAM_LTYPE_IS_TRIVIAL 1
 #endif
 
 
-#ifdef YYPARSE_PARAM
-#if defined __STDC__ || defined __cplusplus
-int gram_parse (void *YYPARSE_PARAM);
-#else
-int gram_parse ();
-#endif
-#else /* ! YYPARSE_PARAM */
-#if defined __STDC__ || defined __cplusplus
+
 int gram_parse (void);
-#else
-int gram_parse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
 
-#endif /* !YY_GRAM_Y_TAB_H_INCLUDED  */
+#endif /* !YY_GRAM_SRC_PARSE_GRAM_H_INCLUDED  */
 
 /* Copy the second part of user declarations.  */
 
-/* Line 379 of yacc.c  */
-#line 393 "parse-gram.c"
+#line 307 "src/parse-gram.c" /* yacc.c:375  */
+/* Unqualified %code blocks.  */
+#line 53 "src/parse-gram.y" /* yacc.c:376  */
+
+  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
+
+#line 228 "src/parse-gram.y" /* yacc.c:376  */
+
+  /** 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;
+
+
+#line 353 "src/parse-gram.c" /* yacc.c:376  */
 
 #ifdef short
 # undef short
@@ -403,11 +363,8 @@ typedef unsigned char yytype_uint8;
 
 #ifdef YYTYPE_INT8
 typedef YYTYPE_INT8 yytype_int8;
-#elif (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-typedef signed char yytype_int8;
 #else
-typedef short int yytype_int8;
+typedef signed char yytype_int8;
 #endif
 
 #ifdef YYTYPE_UINT16
@@ -427,8 +384,7 @@ typedef short int yytype_int16;
 #  define YYSIZE_T __SIZE_TYPE__
 # elif defined size_t
 #  define YYSIZE_T size_t
-# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
+# elif ! defined YYSIZE_T
 #  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
 #  define YYSIZE_T size_t
 # else
@@ -451,37 +407,19 @@ typedef short int yytype_int16;
 #endif
 
 /* Suppress unused-variable warnings by "using" E.  */
-#if ! defined lint || defined __GNUC__
+#ifdef __GNUC__
 # define YYUSE(E) ((void) (E))
 #else
 # define YYUSE(E) /* empty */
 #endif
 
-/* Identity function, used to suppress warnings about constant conditions.  */
-#ifndef lint
-# define YYID(N) (N)
-#else
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static int
-YYID (int yyi)
-#else
-static int
-YYID (yyi)
-    int yyi;
-#endif
-{
-  return yyi;
-}
-#endif
-
 #if 1
 
 /* The parser invokes alloca or malloc; define the necessary symbols.  */
 
 # ifdef YYSTACK_ALLOC
-   /* Pacify GCC's `empty if-body' warning.  */
-#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+   /* Pacify GCC's 'empty if-body' warning.  */
+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
 #  ifndef YYSTACK_ALLOC_MAXIMUM
     /* The OS might guarantee only one guard page at the bottom of the stack,
        and a page size can be as small as 4096 bytes.  So we cannot safely
@@ -497,7 +435,7 @@ YYID (yyi)
 #  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
@@ -505,15 +443,13 @@ YYID (yyi)
 #  endif
 #  ifndef YYMALLOC
 #   define YYMALLOC malloc
-#   if ! defined malloc && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
+#   if ! defined malloc && ! defined EXIT_SUCCESS
 void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
 #   endif
 #  endif
 #  ifndef YYFREE
 #   define YYFREE free
-#   if ! defined free && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
+#   if ! defined free && ! defined EXIT_SUCCESS
 void free (void *); /* INFRINGES ON USER NAME SPACE */
 #   endif
 #  endif
@@ -524,8 +460,8 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */
 
 #if (! defined yyoverflow \
      && (! defined __cplusplus \
-        || (defined GRAM_LTYPE_IS_TRIVIAL && GRAM_LTYPE_IS_TRIVIAL \
-            && defined GRAM_STYPE_IS_TRIVIAL && GRAM_STYPE_IS_TRIVIAL)))
+         || (defined GRAM_LTYPE_IS_TRIVIAL && GRAM_LTYPE_IS_TRIVIAL \
+             && defined GRAM_STYPE_IS_TRIVIAL && GRAM_STYPE_IS_TRIVIAL)))
 
 /* A type that is properly aligned for any stack member.  */
 union yyalloc
@@ -551,16 +487,16 @@ 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);                          \
-      }                                                                        \
-    while (YYID (0))
+# 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 (0)
 
 #endif
 
@@ -579,7 +515,7 @@ union yyalloc
           for (yyi = 0; yyi < (Count); yyi++)   \
             (Dst)[yyi] = (Src)[yyi];            \
         }                                       \
-      while (YYID (0))
+      while (0)
 #  endif
 # endif
 #endif /* !YYCOPY_NEEDED */
@@ -587,25 +523,27 @@ union yyalloc
 /* YYFINAL -- State number of the termination state.  */
 #define YYFINAL  3
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   160
+#define YYLAST   165
 
 /* YYNTOKENS -- Number of terminals.  */
 #define YYNTOKENS  58
 /* YYNNTS -- Number of nonterminals.  */
-#define YYNNTS  34
+#define YYNNTS  38
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  108
-/* YYNRULES -- Number of states.  */
-#define YYNSTATES  148
+#define YYNRULES  111
+/* YYNSTATES -- Number of states.  */
+#define YYNSTATES  145
 
-/* 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  2
 #define YYMAXUTOK   312
 
-#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 yytype_uint8 yytranslate[] =
 {
        0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
@@ -643,70 +581,21 @@ static const yytype_uint8 yytranslate[] =
 };
 
 #if GRAM_DEBUG
-/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
-   YYRHS.  */
-static const yytype_uint16 yyprhs[] =
-{
-       0,     0,     3,     8,     9,    12,    14,    16,    18,    22,
-      24,    27,    29,    32,    35,    38,    42,    44,    47,    50,
-      53,    55,    58,    62,    64,    66,    69,    73,    76,    78,
-      81,    84,    86,    88,    90,    92,    94,    96,    99,   103,
-     107,   109,   111,   114,   118,   119,   121,   125,   126,   130,
-     131,   135,   139,   143,   145,   147,   149,   150,   152,   154,
-     157,   159,   162,   164,   167,   169,   172,   174,   176,   178,
-     180,   182,   184,   187,   190,   194,   196,   199,   201,   204,
-     206,   209,   212,   213,   218,   220,   224,   227,   228,   232,
-     236,   240,   244,   248,   249,   251,   253,   255,   256,   258,
-     260,   262,   264,   266,   268,   270,   272,   274,   275
-};
-
-/* YYRHS -- A `-1'-separated list of the rules' RHS.  */
-static const yytype_int8 yyrhs[] =
-{
-      59,     0,    -1,    60,    50,    77,    91,    -1,    -1,    60,
-      61,    -1,    62,    -1,    52,    -1,    17,    -1,    19,    84,
-      85,    -1,    20,    -1,    20,     3,    -1,    21,    -1,    22,
-       4,    -1,    23,     4,    -1,    24,     3,    -1,    24,    47,
-       3,    -1,    25,    -1,    26,    43,    -1,    27,     3,    -1,
-      28,    43,    -1,    29,    -1,    30,     3,    -1,    30,    47,
-       3,    -1,    32,    -1,    33,    -1,    34,     3,    -1,    34,
-      47,     3,    -1,    35,    43,    -1,    36,    -1,    37,     3,
-      -1,    38,     3,    -1,    40,    -1,    41,    -1,    42,    -1,
-      53,    -1,    67,    -1,    64,    -1,    39,    89,    -1,     8,
-      43,    73,    -1,     9,    43,    73,    -1,    18,    -1,    31,
-      -1,    16,    86,    -1,    16,    48,    86,    -1,    -1,    48,
-      -1,    57,    63,    86,    -1,    -1,     6,    65,    76,    -1,
-      -1,     5,    66,    76,    -1,     7,    54,    72,    -1,    68,
-      69,    70,    -1,    10,    -1,    11,    -1,    12,    -1,    -1,
-      54,    -1,    71,    -1,    70,    71,    -1,    89,    -1,    89,
-       4,    -1,    89,    -1,    72,    89,    -1,    74,    -1,    73,
-      74,    -1,    89,    -1,    54,    -1,    55,    -1,    56,    -1,
-      54,    -1,    87,    -1,    87,     4,    -1,    87,    90,    -1,
-      87,     4,    90,    -1,    75,    -1,    76,    75,    -1,    78,
-      -1,    77,    78,    -1,    79,    -1,    62,    53,    -1,     1,
-      53,    -1,    -1,    88,    83,    80,    81,    -1,    82,    -1,
-      81,    51,    82,    -1,    81,    53,    -1,    -1,    82,    89,
-      83,    -1,    82,    43,    83,    -1,    82,    13,    89,    -1,
-      82,    14,     4,    -1,    82,    15,    54,    -1,    -1,    44,
-      -1,    48,    -1,     3,    -1,    -1,    48,    -1,     3,    -1,
-      43,    -1,    48,    -1,    45,    -1,    49,    -1,    87,    -1,
-      90,    -1,     3,    -1,    -1,    50,    46,    -1
-};
-
-/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
+  /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,   230,   230,   238,   240,   244,   245,   255,   256,   261,
-     262,   267,   268,   269,   270,   271,   272,   277,   286,   287,
-     288,   289,   290,   291,   292,   293,   294,   295,   296,   311,
-     312,   336,   337,   338,   339,   343,   344,   345,   349,   361,
-     373,   377,   381,   388,   403,   404,   408,   420,   420,   425,
-     425,   430,   441,   456,   457,   458,   462,   463,   468,   470,
-     475,   476,   481,   483,   488,   489,   493,   494,   495,   496,
-     501,   506,   511,   517,   523,   534,   535,   544,   545,   551,
-     552,   553,   560,   560,   568,   569,   570,   575,   577,   579,
-     581,   583,   585,   590,   592,   603,   604,   609,   610,   611,
-     620,   640,   642,   651,   656,   657,   662,   669,   671
+       0,   261,   261,   270,   271,   275,   276,   286,   290,   295,
+     296,   301,   307,   308,   309,   310,   315,   324,   325,   326,
+     327,   328,   329,   329,   330,   331,   355,   356,   357,   358,
+     362,   363,   372,   373,   374,   378,   390,   394,   398,   405,
+     416,   417,   427,   428,   432,   444,   444,   449,   449,   454,
+     465,   480,   481,   482,   483,   487,   488,   493,   495,   500,
+     505,   515,   517,   522,   523,   527,   528,   532,   533,   534,
+     539,   544,   549,   555,   561,   572,   573,   582,   583,   589,
+     590,   591,   598,   598,   606,   607,   608,   613,   616,   618,
+     620,   622,   624,   626,   628,   633,   634,   644,   645,   670,
+     671,   672,   673,   682,   702,   704,   713,   718,   719,   724,
+     732,   733
 };
 #endif
 
@@ -715,34 +604,34 @@ static const yytype_uint16 yyrline[] =
    First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
 static const char *const yytname[] =
 {
-  "\"end of file\"", "error", "$undefined", "\"string\"", "\"integer\"",
-  "\"%token\"", "\"%nterm\"", "\"%type\"", "\"%destructor\"",
-  "\"%printer\"", "\"%left\"", "\"%right\"", "\"%nonassoc\"", "\"%prec\"",
-  "\"%dprec\"", "\"%merge\"", "\"%code\"", "\"%debug\"",
+  "\"end of file\"", "error", "$undefined", "\"string\"", "\"%token\"",
+  "\"%nterm\"", "\"%type\"", "\"%destructor\"", "\"%printer\"",
+  "\"%left\"", "\"%right\"", "\"%nonassoc\"", "\"%precedence\"",
+  "\"%prec\"", "\"%dprec\"", "\"%merge\"", "\"%code\"",
   "\"%default-prec\"", "\"%define\"", "\"%defines\"", "\"%error-verbose\"",
-  "\"%expect\"", "\"%expect-rr\"", "\"%file-prefix\"", "\"%glr-parser\"",
-  "\"%initial-action\"", "\"%language\"", "\"%lex-param\"",
-  "\"%locations\"", "\"%name-prefix\"", "\"%no-default-prec\"",
-  "\"%no-lines\"", "\"%nondeterministic-parser\"", "\"%output\"",
-  "\"%parse-param\"", "\"%pure-parser\"", "\"%require\"", "\"%skeleton\"",
-  "\"%start\"", "\"%token-table\"", "\"%verbose\"", "\"%yacc\"",
-  "\"{...}\"", "\"[identifier]\"", "\"char\"", "\"epilogue\"", "\"=\"",
-  "\"identifier\"", "\"identifier:\"", "\"%%\"", "\"|\"", "\"%{...%}\"",
-  "\";\"", "\"type\"", "\"<*>\"", "\"<>\"", "\"%union\"", "$accept",
-  "input", "prologue_declarations", "prologue_declaration",
-  "grammar_declaration", "union_name", "symbol_declaration", "$@1", "$@2",
-  "precedence_declaration", "precedence_declarator", "type.opt",
-  "symbols.prec", "symbol.prec", "symbols.1", "generic_symlist",
-  "generic_symlist_item", "symbol_def", "symbol_defs.1", "grammar",
-  "rules_or_grammar_declaration", "rules", "$@3", "rhses.1", "rhs",
-  "named_ref.opt", "variable", "content.opt", "braceless", "id",
-  "id_colon", "symbol", "string_as_id", "epilogue.opt", YY_NULL
+  "\"%expect\"", "\"%expect-rr\"", "\"%<flag>\"", "\"%file-prefix\"",
+  "\"%glr-parser\"", "\"%initial-action\"", "\"%language\"",
+  "\"%name-prefix\"", "\"%no-default-prec\"", "\"%no-lines\"",
+  "\"%nondeterministic-parser\"", "\"%output\"", "\"%require\"",
+  "\"%skeleton\"", "\"%start\"", "\"%token-table\"", "\"%verbose\"",
+  "\"%yacc\"", "\"{...}\"", "\"%?{...}\"", "\"[identifier]\"", "\"char\"",
+  "\"epilogue\"", "\"=\"", "\"identifier\"", "\"identifier:\"", "\"%%\"",
+  "\"|\"", "\"%{...%}\"", "\";\"", "\"<tag>\"", "\"<*>\"", "\"<>\"",
+  "\"integer\"", "\"%param\"", "\"%union\"", "\"%empty\"", "$accept",
+  "input", "prologue_declarations", "prologue_declaration", "$@1",
+  "params", "grammar_declaration", "code_props_type", "union_name",
+  "symbol_declaration", "$@2", "$@3", "precedence_declaration",
+  "precedence_declarator", "tag.opt", "symbols.prec", "symbol.prec",
+  "symbols.1", "generic_symlist", "generic_symlist_item", "tag",
+  "symbol_def", "symbol_defs.1", "grammar", "rules_or_grammar_declaration",
+  "rules", "$@4", "rhses.1", "rhs", "named_ref.opt", "variable", "value",
+  "braceless", "id", "id_colon", "symbol", "string_as_id", "epilogue.opt", YY_NULL
 };
 #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 yytype_uint16 yytoknum[] =
 {
        0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
@@ -754,197 +643,187 @@ static const yytype_uint16 yytoknum[] =
 };
 # endif
 
-/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
-static const yytype_uint8 yyr1[] =
+#define YYPACT_NINF -115
+
+#define yypact_value_is_default(Yystate) \
+  (!!((Yystate) == (-115)))
+
+#define YYTABLE_NINF -111
+
+#define yytable_value_is_error(Yytable_value) \
+  0
+
+  /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+     STATE-NUM.  */
+static const yytype_int8 yypact[] =
 {
-       0,    58,    59,    60,    60,    61,    61,    61,    61,    61,
-      61,    61,    61,    61,    61,    61,    61,    61,    61,    61,
-      61,    61,    61,    61,    61,    61,    61,    61,    61,    61,
-      61,    61,    61,    61,    61,    62,    62,    62,    62,    62,
-      62,    62,    62,    62,    63,    63,    62,    65,    64,    66,
-      64,    64,    67,    68,    68,    68,    69,    69,    70,    70,
-      71,    71,    72,    72,    73,    73,    74,    74,    74,    74,
-      75,    75,    75,    75,    75,    76,    76,    77,    77,    78,
-      78,    78,    80,    79,    81,    81,    81,    82,    82,    82,
-      82,    82,    82,    83,    83,    84,    84,    85,    85,    85,
-      86,    87,    87,    88,    89,    89,    90,    91,    91
+    -115,    16,   109,  -115,  -115,  -115,   -28,  -115,  -115,  -115,
+    -115,  -115,  -115,   -14,  -115,    25,    23,  -115,   -27,   -20,
+    -115,    39,  -115,     7,    48,    71,  -115,  -115,  -115,    72,
+      73,    74,    -2,  -115,  -115,  -115,    56,  -115,  -115,  -115,
+      33,  -115,  -115,    40,  -115,  -115,    37,    54,    54,    -2,
+    -115,    50,  -115,  -115,  -115,     2,  -115,  -115,  -115,  -115,
+    -115,  -115,  -115,  -115,  -115,  -115,  -115,  -115,  -115,  -115,
+    -115,  -115,    51,  -115,    53,     3,  -115,  -115,    49,    65,
+    -115,    50,    42,  -115,    -2,  -115,  -115,    54,    -1,    54,
+      -2,  -115,  -115,  -115,  -115,  -115,  -115,  -115,  -115,    63,
+    -115,  -115,  -115,  -115,  -115,    69,  -115,  -115,  -115,  -115,
+      42,  -115,  -115,  -115,    -2,  -115,    38,  -115,   106,  -115,
+    -115,  -115,  -115,  -115,  -115,  -115,  -115,  -115,   -15,    41,
+    -115,  -115,    -2,    57,    59,    49,  -115,  -115,    49,    41,
+    -115,  -115,  -115,  -115,  -115
 };
 
-/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
-static const yytype_uint8 yyr2[] =
+  /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
+     Performed when YYTABLE does not specify something else to do.  Zero
+     means the default is an error.  */
+static const yytype_uint8 yydefact[] =
 {
-       0,     2,     4,     0,     2,     1,     1,     1,     3,     1,
-       2,     1,     2,     2,     2,     3,     1,     2,     2,     2,
-       1,     2,     3,     1,     1,     2,     3,     2,     1,     2,
-       2,     1,     1,     1,     1,     1,     1,     2,     3,     3,
-       1,     1,     2,     3,     0,     1,     3,     0,     3,     0,
-       3,     3,     3,     1,     1,     1,     0,     1,     1,     2,
-       1,     2,     1,     2,     1,     2,     1,     1,     1,     1,
-       1,     1,     2,     2,     3,     1,     2,     1,     2,     1,
-       2,     2,     0,     4,     1,     3,     2,     0,     3,     3,
-       3,     3,     3,     0,     1,     1,     1,     0,     1,     1,
-       1,     1,     1,     1,     1,     1,     1,     0,     2
+       3,     0,     0,     1,    47,    45,     0,    40,    41,    51,
+      52,    53,    54,     0,    36,     0,     9,    11,     0,     0,
+       7,     0,    15,     0,     0,     0,    37,    19,    20,     0,
+       0,     0,     0,    26,    27,    28,     0,     6,    29,    22,
+      42,     4,     5,     0,    33,    32,    55,     0,     0,     0,
+     103,     0,    38,    98,    97,    99,    10,    12,    13,    14,
+      16,    17,    18,    21,    24,    25,   109,   105,   104,   107,
+      34,   108,     0,   106,     0,     0,    77,    79,    95,     0,
+      43,     0,     0,    56,     0,    70,    75,    48,    71,    46,
+      49,    61,    39,   101,   100,     8,   102,    81,    80,     0,
+      78,     2,    96,    82,    31,    23,    44,    67,    68,    69,
+      35,    63,    66,    65,    50,    57,    59,    76,    72,    73,
+      62,   111,    87,    30,    64,    58,    60,    74,    83,    84,
+      87,    86,     0,     0,     0,    95,    90,    91,    95,    85,
+      92,    93,    94,    89,    88
 };
 
-/* 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 yytype_uint8 yydefact[] =
+  /* YYPGOTO[NTERM-NUM].  */
+static const yytype_int8 yypgoto[] =
 {
-       3,     0,     0,     1,    49,    47,     0,     0,     0,    53,
-      54,    55,     0,     7,    40,     0,     9,    11,     0,     0,
-       0,    16,     0,     0,     0,    20,     0,    41,    23,    24,
-       0,     0,    28,     0,     0,     0,    31,    32,    33,     0,
-       6,    34,    44,     4,     5,    36,    35,    56,     0,     0,
-       0,     0,     0,   100,     0,    42,    96,    95,    97,    10,
-      12,    13,    14,     0,    17,    18,    19,    21,     0,    25,
-       0,    27,    29,    30,   106,   102,   101,   104,    37,   105,
-       0,   103,     0,     0,    77,    79,    93,    45,     0,    57,
-       0,    70,    75,    50,    71,    48,    51,    62,    67,    68,
-      69,    38,    64,    66,    39,    43,    99,    98,     8,    15,
-      22,    26,    81,    80,     0,    78,     2,    94,    82,    46,
-      52,    58,    60,    76,    72,    73,    63,    65,   108,    87,
-      59,    61,    74,    83,    84,    87,    86,     0,     0,     0,
-      93,    93,    85,    90,    91,    92,    89,    88
+    -115,  -115,  -115,  -115,  -115,  -115,   120,  -115,  -115,  -115,
+    -115,  -115,  -115,  -115,  -115,  -115,     9,  -115,  -115,    14,
+    -115,   -50,   100,  -115,    75,  -115,  -115,  -115,    19,  -114,
+    -115,  -115,   -33,   -18,  -115,   -32,   -82,  -115
 };
 
-/* YYDEFGOTO[NTERM-NUM].  */
+  /* YYDEFGOTO[NTERM-NUM].  */
 static const yytype_int16 yydefgoto[] =
 {
-      -1,     1,     2,    43,    82,    88,    45,    49,    48,    46,
-      47,    90,   120,   121,    96,   101,   102,    92,    93,    83,
-      84,    85,   129,   133,   134,   118,    58,   108,    55,    77,
-      86,   103,    79,   116
+      -1,     1,     2,    41,    79,   105,    74,    43,    81,    44,
+      48,    47,    45,    46,    84,   114,   115,    90,   110,   111,
+     112,    86,    87,    75,    76,    77,   122,   128,   129,   103,
+      55,    95,    52,    69,    78,   113,    71,   101
 };
 
-/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
-   STATE-NUM.  */
-#define YYPACT_NINF -91
-static const yytype_int16 yypact[] =
+  /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM.  If
+     positive, shift that token.  If negative, reduce the rule whose
+     number is the opposite.  If YYTABLE_NINF, syntax error.  */
+static const yytype_int16 yytable[] =
 {
-     -91,     3,   103,   -91,   -91,   -91,   -36,     2,    10,   -91,
-     -91,   -91,     9,   -91,   -91,    32,    60,   -91,    65,    67,
-      27,   -91,    41,    73,    51,   -91,    39,   -91,   -91,   -91,
-      40,    52,   -91,    93,    95,    33,   -91,   -91,   -91,    15,
-     -91,   -91,    53,   -91,   -91,   -91,   -91,    46,    43,    43,
-      33,    11,    11,   -91,    61,   -91,   -91,   -91,    35,   -91,
-     -91,   -91,   -91,   100,   -91,   -91,   -91,   -91,   102,   -91,
-     113,   -91,   -91,   -91,   -91,   -91,   -91,   -91,   -91,   -91,
-      64,   -91,    94,     1,   -91,   -91,    62,   -91,    61,   -91,
-      33,   -91,   -91,    43,    86,    43,    33,   -91,   -91,   -91,
-     -91,    11,   -91,   -91,    11,   -91,   -91,   -91,   -91,   -91,
-     -91,   -91,   -91,   -91,    72,   -91,   -91,   -91,   -91,   -91,
-      33,   -91,   142,   -91,   145,   -91,   -91,   -91,   -91,   -91,
-     -91,   -91,   -91,    17,    34,   -91,   -91,    33,   146,    97,
-      62,    62,    34,   -91,   -91,   -91,   -91,   -91
+      70,    66,    66,  -110,    72,    93,   119,     4,     5,     6,
+       7,     8,     9,    10,    11,    12,     3,    91,    92,    13,
+      14,   143,    96,    49,   144,    50,    56,    57,    53,    88,
+      88,    51,    26,   130,    58,   131,   127,   117,    32,   117,
+      67,    50,    59,    68,    66,    66,    60,    94,   106,    73,
+      99,    61,   116,   118,   132,   133,   134,    72,   120,    40,
+       4,     5,     6,     7,     8,     9,    10,    11,    12,    88,
+      54,    88,    13,    14,    62,    63,    64,    65,    80,    82,
+     135,   136,   116,    67,    67,    26,    68,    68,    83,    50,
+     102,    32,   126,   107,   108,   109,    67,   138,   137,    68,
+     140,    97,    73,    98,   104,    85,   121,   138,   123,    66,
+     142,   141,    40,     4,     5,     6,     7,     8,     9,    10,
+      11,    12,    42,   125,   124,    13,    14,    15,    16,    17,
+      18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
+      28,    29,    30,    31,    32,    33,    34,    35,    89,   139,
+     100,     0,     0,     0,     0,     0,    36,     0,    37,    38,
+       0,     0,     0,     0,    39,    40
 };
 
-/* YYPGOTO[NTERM-NUM].  */
-static const yytype_int16 yypgoto[] =
+static const yytype_int16 yycheck[] =
 {
-     -91,   -91,   -91,   -91,   147,   -91,   -91,   -91,   -91,   -91,
-     -91,   -91,   -91,    37,   -91,   106,   -60,   -33,   105,   -91,
-      69,   -91,   -91,   -91,    24,   -48,   -91,   -91,   -49,   -20,
-     -91,   -35,   -90,   -91
+      32,     3,     3,     0,     1,     3,    88,     4,     5,     6,
+       7,     8,     9,    10,    11,    12,     0,    49,    51,    16,
+      17,   135,    55,    51,   138,    39,     3,    54,     3,    47,
+      48,    45,    29,    48,    54,    50,   118,    87,    35,    89,
+      42,    39,     3,    45,     3,     3,    39,    45,    81,    46,
+      47,     3,    84,    54,    13,    14,    15,     1,    90,    56,
+       4,     5,     6,     7,     8,     9,    10,    11,    12,    87,
+      45,    89,    16,    17,     3,     3,     3,     3,    45,    39,
+      39,    40,   114,    42,    42,    29,    45,    45,    51,    39,
+      41,    35,    54,    51,    52,    53,    42,   129,    57,    45,
+     132,    50,    46,    50,    39,    51,    43,   139,    39,     3,
+      51,    54,    56,     4,     5,     6,     7,     8,     9,    10,
+      11,    12,     2,   114,   110,    16,    17,    18,    19,    20,
+      21,    22,    23,    24,    25,    26,    27,    28,    29,    30,
+      31,    32,    33,    34,    35,    36,    37,    38,    48,   130,
+      75,    -1,    -1,    -1,    -1,    -1,    47,    -1,    49,    50,
+      -1,    -1,    -1,    -1,    55,    56
 };
 
-/* 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 -108
-static const yytype_int16 yytable[] =
+  /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+     symbol of state STATE-NUM.  */
+static const yytype_uint8 yystos[] =
 {
-      78,  -107,    80,     3,   125,   105,     4,     5,     6,     7,
-       8,     9,    10,    11,    74,    97,    80,    12,    50,    14,
-       4,     5,     6,     7,     8,     9,    10,    11,    94,    94,
-      62,    12,    27,    14,   132,    56,    74,    74,   106,   119,
-      35,   127,    67,    69,   127,    51,    27,   137,   138,   139,
-      81,   114,    53,    52,    35,   122,    75,    54,    42,    76,
-     123,   126,   123,    59,    81,    98,    99,   100,   135,    60,
-     136,    61,    42,    94,    63,    94,    65,   140,    75,    75,
-      57,    76,    76,   107,    64,   122,    68,    70,    75,    74,
-     124,    76,   146,   147,    66,    71,    72,    91,    73,   141,
-      89,    87,   143,   109,    53,   110,   117,   141,     4,     5,
-       6,     7,     8,     9,    10,    11,   111,   112,   128,    12,
-      13,    14,    15,    16,    17,    18,    19,    20,    21,    22,
+       0,    59,    60,     0,     4,     5,     6,     7,     8,     9,
+      10,    11,    12,    16,    17,    18,    19,    20,    21,    22,
       23,    24,    25,    26,    27,    28,    29,    30,    31,    32,
-      33,    34,    35,    36,    37,    38,   131,   113,    74,    44,
-     144,   145,   115,    39,    95,    40,    41,   130,   104,   142,
-      42
+      33,    34,    35,    36,    37,    38,    47,    49,    50,    55,
+      56,    61,    64,    65,    67,    70,    71,    69,    68,    51,
+      39,    45,    90,     3,    45,    88,     3,    54,    54,     3,
+      39,     3,     3,     3,     3,     3,     3,    42,    45,    91,
+      93,    94,     1,    46,    64,    81,    82,    83,    92,    62,
+      45,    66,    39,    51,    72,    51,    79,    80,    91,    80,
+      75,    93,    90,     3,    45,    89,    90,    50,    50,    47,
+      82,    95,    41,    87,    39,    63,    90,    51,    52,    53,
+      76,    77,    78,    93,    73,    74,    93,    79,    54,    94,
+      93,    43,    84,    39,    77,    74,    54,    94,    85,    86,
+      48,    50,    13,    14,    15,    39,    40,    57,    93,    86,
+      93,    54,    51,    87,    87
 };
 
-#define yypact_value_is_default(Yystate) \
-  (!!((Yystate) == (-91)))
-
-#define yytable_value_is_error(Yytable_value) \
-  YYID (0)
-
-static const yytype_uint8 yycheck[] =
+  /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
+static const yytype_uint8 yyr1[] =
 {
-      35,     0,     1,     0,    94,    54,     5,     6,     7,     8,
-       9,    10,    11,    12,     3,    50,     1,    16,    54,    18,
-       5,     6,     7,     8,     9,    10,    11,    12,    48,    49,
-       3,    16,    31,    18,   124,     3,     3,     3,     3,    88,
-      39,   101,     3,     3,   104,    43,    31,    13,    14,    15,
-      49,    50,    43,    43,    39,    90,    45,    48,    57,    48,
-      93,    96,    95,     3,    49,    54,    55,    56,    51,     4,
-      53,     4,    57,    93,    47,    95,     3,    43,    45,    45,
-      48,    48,    48,    48,    43,   120,    47,    47,    45,     3,
-       4,    48,   140,   141,    43,    43,     3,    54,     3,   134,
-      54,    48,   137,     3,    43,     3,    44,   142,     5,     6,
-       7,     8,     9,    10,    11,    12,     3,    53,    46,    16,
-      17,    18,    19,    20,    21,    22,    23,    24,    25,    26,
-      27,    28,    29,    30,    31,    32,    33,    34,    35,    36,
-      37,    38,    39,    40,    41,    42,     4,    53,     3,     2,
-       4,    54,    83,    50,    49,    52,    53,   120,    52,   135,
-      57
+       0,    58,    59,    60,    60,    61,    61,    61,    61,    61,
+      61,    61,    61,    61,    61,    61,    61,    61,    61,    61,
+      61,    61,    62,    61,    61,    61,    61,    61,    61,    61,
+      63,    63,    64,    64,    64,    64,    64,    64,    64,    64,
+      65,    65,    66,    66,    64,    68,    67,    69,    67,    67,
+      70,    71,    71,    71,    71,    72,    72,    73,    73,    74,
+      74,    75,    75,    76,    76,    77,    77,    78,    78,    78,
+      79,    79,    79,    79,    79,    80,    80,    81,    81,    82,
+      82,    82,    84,    83,    85,    85,    85,    86,    86,    86,
+      86,    86,    86,    86,    86,    87,    87,    88,    88,    89,
+      89,    89,    89,    90,    91,    91,    92,    93,    93,    94,
+      95,    95
 };
 
-/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
-   symbol of state STATE-NUM.  */
-static const yytype_uint8 yystos[] =
+  /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN.  */
+static const yytype_uint8 yyr2[] =
 {
-       0,    59,    60,     0,     5,     6,     7,     8,     9,    10,
-      11,    12,    16,    17,    18,    19,    20,    21,    22,    23,
-      24,    25,    26,    27,    28,    29,    30,    31,    32,    33,
-      34,    35,    36,    37,    38,    39,    40,    41,    42,    50,
-      52,    53,    57,    61,    62,    64,    67,    68,    66,    65,
-      54,    43,    43,    43,    48,    86,     3,    48,    84,     3,
-       4,     4,     3,    47,    43,     3,    43,     3,    47,     3,
-      47,    43,     3,     3,     3,    45,    48,    87,    89,    90,
-       1,    49,    62,    77,    78,    79,    88,    48,    63,    54,
-      69,    54,    75,    76,    87,    76,    72,    89,    54,    55,
-      56,    73,    74,    89,    73,    86,     3,    48,    85,     3,
-       3,     3,    53,    53,    50,    78,    91,    44,    83,    86,
-      70,    71,    89,    75,     4,    90,    89,    74,    46,    80,
-      71,     4,    90,    81,    82,    51,    53,    13,    14,    15,
-      43,    89,    82,    89,     4,    54,    83,    83
+       0,     2,     4,     0,     2,     1,     1,     1,     3,     1,
+       2,     1,     2,     2,     2,     1,     2,     2,     2,     1,
+       1,     2,     0,     3,     2,     2,     1,     1,     1,     1,
+       2,     1,     1,     1,     2,     3,     1,     1,     2,     3,
+       1,     1,     0,     1,     3,     0,     3,     0,     3,     3,
+       3,     1,     1,     1,     1,     0,     1,     1,     2,     1,
+       2,     1,     2,     1,     2,     1,     1,     1,     1,     1,
+       1,     1,     2,     2,     3,     1,     2,     1,     2,     1,
+       2,     2,     0,     4,     1,     3,     2,     0,     3,     3,
+       2,     2,     3,     3,     3,     0,     1,     1,     1,     0,
+       1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
+       0,     2
 };
 
-#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 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 YYRECOVERING()  (!!yyerrstatus)
 
@@ -961,14 +840,14 @@ do                                                              \
     }                                                           \
   else                                                          \
     {                                                           \
-      yyerror (YY_("syntax error: cannot back up")); \
-      YYERROR;                                                 \
-    }                                                          \
-while (YYID (0))
+      yyerror (&yylloc, YY_("syntax error: cannot back up")); \
+      YYERROR;                                                  \
+    }                                                           \
+while (0)
 
 /* Error token number */
-#define YYTERROR       1
-#define YYERRCODE      256
+#define YYTERROR        1
+#define YYERRCODE       256
 
 
 /* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
@@ -978,7 +857,7 @@ while (YYID (0))
 #ifndef YYLLOC_DEFAULT
 # define YYLLOC_DEFAULT(Current, Rhs, N)                                \
     do                                                                  \
-      if (YYID (N))                                                     \
+      if (N)                                                            \
         {                                                               \
           (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;        \
           (Current).first_column = YYRHSLOC (Rhs, 1).first_column;      \
@@ -992,224 +871,253 @@ while (YYID (0))
           (Current).first_column = (Current).last_column =              \
             YYRHSLOC (Rhs, 0).last_column;                              \
         }                                                               \
-    while (YYID (0))
+    while (0)
 #endif
 
 #define YYRHSLOC(Rhs, K) ((Rhs)[K])
 
 
+/* Enable debugging if requested.  */
+#if GRAM_DEBUG
+
+# ifndef YYFPRINTF
+#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args)                        \
+do {                                            \
+  if (yydebug)                                  \
+    YYFPRINTF Args;                             \
+} while (0)
+
+
 /* YY_LOCATION_PRINT -- Print the location on the stream.
    This macro was not mandated originally: define only if we know
    we won't break user code: when these are the locations we know.  */
 
 #ifndef YY_LOCATION_PRINT
 # if defined GRAM_LTYPE_IS_TRIVIAL && GRAM_LTYPE_IS_TRIVIAL
-#  define YY_LOCATION_PRINT(File, Loc)                                   \
-  do {                                                                   \
-    fprintf (File, "%d.%d", (Loc).first_line, (Loc).first_column);       \
-    if ((Loc).first_line < (Loc).last_line)                              \
-      fprintf (File, "-%d.%d", (Loc).last_line,  (Loc).last_column - 1); \
-    else if ((Loc).first_column < (Loc).last_column - 1)                 \
-      fprintf (File, "-%d", (Loc).last_column - 1);                      \
-  } while (0)
-# else
-#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
-# endif
-#endif
 
+/* Print *YYLOCP on YYO.  Private, do not rely on its existence. */
 
-/* YYLEX -- calling `yylex' with the right arguments.  */
-#ifdef YYLEX_PARAM
-# define YYLEX yylex (&yylval, &yylloc, YYLEX_PARAM)
-#else
-# define YYLEX yylex (&yylval, &yylloc)
-#endif
+__attribute__((__unused__))
+static unsigned
+yy_location_print_ (FILE *yyo, YYLTYPE const * const yylocp)
+{
+  unsigned res = 0;
+  int end_col = 0 != yylocp->last_column ? yylocp->last_column - 1 : 0;
+  if (0 <= yylocp->first_line)
+    {
+      res += YYFPRINTF (yyo, "%d", yylocp->first_line);
+      if (0 <= yylocp->first_column)
+        res += YYFPRINTF (yyo, ".%d", yylocp->first_column);
+    }
+  if (0 <= yylocp->last_line)
+    {
+      if (yylocp->first_line < yylocp->last_line)
+        {
+          res += YYFPRINTF (yyo, "-%d", yylocp->last_line);
+          if (0 <= end_col)
+            res += YYFPRINTF (yyo, ".%d", end_col);
+        }
+      else if (0 <= end_col && yylocp->first_column < end_col)
+        res += YYFPRINTF (yyo, "-%d", end_col);
+    }
+  return res;
+ }
 
-/* Enable debugging if requested.  */
-#if GRAM_DEBUG
+#  define YY_LOCATION_PRINT(File, Loc)          \
+  yy_location_print_ (File, &(Loc))
 
-# ifndef YYFPRINTF
-#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
-#  define YYFPRINTF fprintf
+# else
+#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
 # endif
+#endif
 
-# 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, 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, Location); \
+      YYFPRINTF (stderr, "\n");                                           \
+    }                                                                     \
+} while (0)
 
 
 /*--------------------------------.
 | Print this symbol on YYOUTPUT.  |
 `--------------------------------*/
 
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
 static void
 yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp)
-#else
-static void
-yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp)
-    FILE *yyoutput;
-    int yytype;
-    YYSTYPE const * const yyvaluep;
-    YYLTYPE const * const yylocationp;
-#endif
 {
   FILE *yyo = yyoutput;
   YYUSE (yyo);
+  YYUSE (yylocationp);
   if (!yyvaluep)
     return;
-  YYUSE (yylocationp);
 # ifdef YYPRINT
   if (yytype < YYNTOKENS)
     YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
-# else
-  YYUSE (yyoutput);
 # endif
   switch (yytype)
     {
-      case 3: /* "string" */
-/* Line 812 of yacc.c  */
-#line 205 "parse-gram.y"
-       { fputs (quotearg_style (c_quoting_style, ((*yyvaluep).chars)), stderr); };
-/* Line 812 of yacc.c  */
-#line 1091 "parse-gram.c"
-       break;
-      case 4: /* "integer" */
-/* Line 812 of yacc.c  */
-#line 217 "parse-gram.y"
-       { fprintf (stderr, "%d", ((*yyvaluep).integer)); };
-/* Line 812 of yacc.c  */
-#line 1098 "parse-gram.c"
-       break;
-      case 43: /* "{...}" */
-/* Line 812 of yacc.c  */
-#line 207 "parse-gram.y"
-       { fprintf (stderr, "{\n%s\n}", ((*yyvaluep).code)); };
-/* Line 812 of yacc.c  */
-#line 1105 "parse-gram.c"
-       break;
-      case 44: /* "[identifier]" */
-/* Line 812 of yacc.c  */
-#line 212 "parse-gram.y"
-       { fprintf (stderr, "[%s]", ((*yyvaluep).uniqstr)); };
-/* Line 812 of yacc.c  */
-#line 1112 "parse-gram.c"
-       break;
-      case 45: /* "char" */
-/* Line 812 of yacc.c  */
-#line 199 "parse-gram.y"
-       { fputs (char_name (((*yyvaluep).character)), stderr); };
-/* Line 812 of yacc.c  */
-#line 1119 "parse-gram.c"
-       break;
-      case 46: /* "epilogue" */
-/* Line 812 of yacc.c  */
-#line 207 "parse-gram.y"
-       { fprintf (stderr, "{\n%s\n}", ((*yyvaluep).chars)); };
-/* Line 812 of yacc.c  */
-#line 1126 "parse-gram.c"
-       break;
-      case 48: /* "identifier" */
-/* Line 812 of yacc.c  */
-#line 211 "parse-gram.y"
-       { fputs (((*yyvaluep).uniqstr), stderr); };
-/* Line 812 of yacc.c  */
-#line 1133 "parse-gram.c"
-       break;
-      case 49: /* "identifier:" */
-/* Line 812 of yacc.c  */
-#line 213 "parse-gram.y"
-       { fprintf (stderr, "%s:", ((*yyvaluep).uniqstr)); };
-/* Line 812 of yacc.c  */
-#line 1140 "parse-gram.c"
-       break;
-      case 52: /* "%{...%}" */
-/* Line 812 of yacc.c  */
-#line 207 "parse-gram.y"
-       { fprintf (stderr, "{\n%s\n}", ((*yyvaluep).chars)); };
-/* Line 812 of yacc.c  */
-#line 1147 "parse-gram.c"
-       break;
-      case 54: /* "type" */
-/* Line 812 of yacc.c  */
-#line 214 "parse-gram.y"
-       { fprintf (stderr, "<%s>", ((*yyvaluep).uniqstr)); };
-/* Line 812 of yacc.c  */
-#line 1154 "parse-gram.c"
-       break;
-      case 71: /* symbol.prec */
-/* Line 812 of yacc.c  */
-#line 220 "parse-gram.y"
-       { fprintf (stderr, "%s", ((*yyvaluep).symbol)->tag); };
-/* Line 812 of yacc.c  */
-#line 1161 "parse-gram.c"
-       break;
-      case 84: /* variable */
-/* Line 812 of yacc.c  */
-#line 211 "parse-gram.y"
-       { fputs (((*yyvaluep).uniqstr), stderr); };
-/* Line 812 of yacc.c  */
-#line 1168 "parse-gram.c"
-       break;
-      case 85: /* content.opt */
-/* Line 812 of yacc.c  */
-#line 207 "parse-gram.y"
-       { fprintf (stderr, "{\n%s\n}", ((*yyvaluep).chars)); };
-/* Line 812 of yacc.c  */
-#line 1175 "parse-gram.c"
-       break;
-      case 86: /* braceless */
-/* Line 812 of yacc.c  */
-#line 207 "parse-gram.y"
-       { fprintf (stderr, "{\n%s\n}", ((*yyvaluep).chars)); };
-/* Line 812 of yacc.c  */
-#line 1182 "parse-gram.c"
-       break;
-      case 87: /* id */
-/* Line 812 of yacc.c  */
-#line 220 "parse-gram.y"
-       { fprintf (stderr, "%s", ((*yyvaluep).symbol)->tag); };
-/* Line 812 of yacc.c  */
-#line 1189 "parse-gram.c"
-       break;
-      case 88: /* id_colon */
-/* Line 812 of yacc.c  */
-#line 221 "parse-gram.y"
-       { fprintf (stderr, "%s:", ((*yyvaluep).symbol)->tag); };
-/* Line 812 of yacc.c  */
-#line 1196 "parse-gram.c"
-       break;
-      case 89: /* symbol */
-/* Line 812 of yacc.c  */
-#line 220 "parse-gram.y"
-       { fprintf (stderr, "%s", ((*yyvaluep).symbol)->tag); };
-/* Line 812 of yacc.c  */
-#line 1203 "parse-gram.c"
-       break;
-      case 90: /* string_as_id */
-/* Line 812 of yacc.c  */
-#line 220 "parse-gram.y"
-       { fprintf (stderr, "%s", ((*yyvaluep).symbol)->tag); };
-/* Line 812 of yacc.c  */
-#line 1210 "parse-gram.c"
-       break;
+    case 3: /* "string"  */
+#line 183 "src/parse-gram.y" /* yacc.c:706  */
+      { fputs (quotearg_style (c_quoting_style, ((*yyvaluep).chars)), yyo); }
+#line 973 "src/parse-gram.c" /* yacc.c:706  */
+        break;
+
+    case 23: /* "%<flag>"  */
+#line 193 "src/parse-gram.y" /* yacc.c:706  */
+      { fprintf (yyo, "%%%s", ((*yyvaluep).uniqstr)); }
+#line 979 "src/parse-gram.c" /* yacc.c:706  */
+        break;
+
+    case 39: /* "{...}"  */
+#line 185 "src/parse-gram.y" /* yacc.c:706  */
+      { fprintf (yyo, "{\n%s\n}", ((*yyvaluep).code)); }
+#line 985 "src/parse-gram.c" /* yacc.c:706  */
+        break;
+
+    case 41: /* "[identifier]"  */
+#line 191 "src/parse-gram.y" /* yacc.c:706  */
+      { fprintf (yyo, "[%s]", ((*yyvaluep).uniqstr)); }
+#line 991 "src/parse-gram.c" /* yacc.c:706  */
+        break;
+
+    case 42: /* "char"  */
+#line 172 "src/parse-gram.y" /* yacc.c:706  */
+      { fputs (char_name (((*yyvaluep).character)), yyo); }
+#line 997 "src/parse-gram.c" /* yacc.c:706  */
+        break;
+
+    case 43: /* "epilogue"  */
+#line 185 "src/parse-gram.y" /* yacc.c:706  */
+      { fprintf (yyo, "{\n%s\n}", ((*yyvaluep).chars)); }
+#line 1003 "src/parse-gram.c" /* yacc.c:706  */
+        break;
+
+    case 45: /* "identifier"  */
+#line 190 "src/parse-gram.y" /* yacc.c:706  */
+      { fputs (((*yyvaluep).uniqstr), yyo); }
+#line 1009 "src/parse-gram.c" /* yacc.c:706  */
+        break;
+
+    case 46: /* "identifier:"  */
+#line 192 "src/parse-gram.y" /* yacc.c:706  */
+      { fprintf (yyo, "%s:", ((*yyvaluep).uniqstr)); }
+#line 1015 "src/parse-gram.c" /* yacc.c:706  */
+        break;
+
+    case 49: /* "%{...%}"  */
+#line 185 "src/parse-gram.y" /* yacc.c:706  */
+      { fprintf (yyo, "{\n%s\n}", ((*yyvaluep).chars)); }
+#line 1021 "src/parse-gram.c" /* yacc.c:706  */
+        break;
+
+    case 51: /* "<tag>"  */
+#line 194 "src/parse-gram.y" /* yacc.c:706  */
+      { fprintf (yyo, "<%s>", ((*yyvaluep).uniqstr)); }
+#line 1027 "src/parse-gram.c" /* yacc.c:706  */
+        break;
+
+    case 54: /* "integer"  */
+#line 198 "src/parse-gram.y" /* yacc.c:706  */
+      { fprintf (yyo, "%d", ((*yyvaluep).integer)); }
+#line 1033 "src/parse-gram.c" /* yacc.c:706  */
+        break;
+
+    case 55: /* "%param"  */
+#line 241 "src/parse-gram.y" /* yacc.c:706  */
+      {
+  switch (((*yyvaluep).param))
+    {
+#define CASE(In, Out)                                           \
+      case param_ ## In: fputs ("%" #Out, yyo); break
+      CASE (lex,   lex-param);
+      CASE (parse, parse-param);
+      CASE (both,  param);
+#undef CASE
+      case param_none: aver (false); break;
+    }
+}
+#line 1050 "src/parse-gram.c" /* yacc.c:706  */
+        break;
+
+    case 65: /* code_props_type  */
+#line 414 "src/parse-gram.y" /* yacc.c:706  */
+      { fprintf (yyo, "%s", code_props_type_string (((*yyvaluep).code_type))); }
+#line 1056 "src/parse-gram.c" /* yacc.c:706  */
+        break;
+
+    case 74: /* symbol.prec  */
+#line 202 "src/parse-gram.y" /* yacc.c:706  */
+      { fprintf (yyo, "%s", ((*yyvaluep).symbol)->tag); }
+#line 1062 "src/parse-gram.c" /* yacc.c:706  */
+        break;
+
+    case 78: /* tag  */
+#line 194 "src/parse-gram.y" /* yacc.c:706  */
+      { fprintf (yyo, "<%s>", ((*yyvaluep).uniqstr)); }
+#line 1068 "src/parse-gram.c" /* yacc.c:706  */
+        break;
+
+    case 88: /* variable  */
+#line 190 "src/parse-gram.y" /* yacc.c:706  */
+      { fputs (((*yyvaluep).uniqstr), yyo); }
+#line 1074 "src/parse-gram.c" /* yacc.c:706  */
+        break;
+
+    case 89: /* value  */
+#line 660 "src/parse-gram.y" /* yacc.c:706  */
+      {
+  switch (((*yyvaluep).value).kind)
+    {
+    case muscle_code:    fprintf (yyo,  "{%s}",  ((*yyvaluep).value).chars); break;
+    case muscle_keyword: fprintf (yyo,   "%s",   ((*yyvaluep).value).chars); break;
+    case muscle_string:  fprintf (yyo, "\"%s\"", ((*yyvaluep).value).chars); break;
+    }
+}
+#line 1087 "src/parse-gram.c" /* yacc.c:706  */
+        break;
+
+    case 90: /* braceless  */
+#line 185 "src/parse-gram.y" /* yacc.c:706  */
+      { fprintf (yyo, "{\n%s\n}", ((*yyvaluep).chars)); }
+#line 1093 "src/parse-gram.c" /* yacc.c:706  */
+        break;
+
+    case 91: /* id  */
+#line 202 "src/parse-gram.y" /* yacc.c:706  */
+      { fprintf (yyo, "%s", ((*yyvaluep).symbol)->tag); }
+#line 1099 "src/parse-gram.c" /* yacc.c:706  */
+        break;
+
+    case 92: /* id_colon  */
+#line 203 "src/parse-gram.y" /* yacc.c:706  */
+      { fprintf (yyo, "%s:", ((*yyvaluep).symbol)->tag); }
+#line 1105 "src/parse-gram.c" /* yacc.c:706  */
+        break;
+
+    case 93: /* symbol  */
+#line 202 "src/parse-gram.y" /* yacc.c:706  */
+      { fprintf (yyo, "%s", ((*yyvaluep).symbol)->tag); }
+#line 1111 "src/parse-gram.c" /* yacc.c:706  */
+        break;
+
+    case 94: /* string_as_id  */
+#line 202 "src/parse-gram.y" /* yacc.c:706  */
+      { fprintf (yyo, "%s", ((*yyvaluep).symbol)->tag); }
+#line 1117 "src/parse-gram.c" /* yacc.c:706  */
+        break;
+
       default:
-       break;
+        break;
     }
 }
 
@@ -1218,23 +1126,11 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp)
 | Print this symbol on YYOUTPUT.  |
 `--------------------------------*/
 
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
 static void
 yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp)
-#else
-static void
-yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp)
-    FILE *yyoutput;
-    int yytype;
-    YYSTYPE const * const yyvaluep;
-    YYLTYPE const * const yylocationp;
-#endif
 {
-  if (yytype < YYNTOKENS)
-    YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
-  else
-    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+  YYFPRINTF (yyoutput, "%s %s (",
+             yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
 
   YY_LOCATION_PRINT (yyoutput, *yylocationp);
   YYFPRINTF (yyoutput, ": ");
@@ -1247,16 +1143,8 @@ yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp)
 | TOP (included).                                                   |
 `------------------------------------------------------------------*/
 
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
 static void
 yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
-#else
-static void
-yy_stack_print (yybottom, yytop)
-    yytype_int16 *yybottom;
-    yytype_int16 *yytop;
-#endif
 {
   YYFPRINTF (stderr, "Stack now");
   for (; yybottom <= yytop; yybottom++)
@@ -1267,50 +1155,42 @@ yy_stack_print (yybottom, yytop)
   YYFPRINTF (stderr, "\n");
 }
 
-# define YY_STACK_PRINT(Bottom, Top)                           \
-do {                                                           \
-  if (yydebug)                                                 \
-    yy_stack_print ((Bottom), (Top));                          \
-} while (YYID (0))
+# define YY_STACK_PRINT(Bottom, Top)                            \
+do {                                                            \
+  if (yydebug)                                                  \
+    yy_stack_print ((Bottom), (Top));                           \
+} while (0)
 
 
 /*------------------------------------------------.
 | Report that the YYRULE is going to be reduced.  |
 `------------------------------------------------*/
 
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_reduce_print (YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule)
-#else
 static void
-yy_reduce_print (yyvsp, yylsp, yyrule)
-    YYSTYPE *yyvsp;
-    YYLTYPE *yylsp;
-    int yyrule;
-#endif
+yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule)
 {
+  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],
-                      &(yyvsp[(yyi + 1) - (yynrhs)])
-                      , &(yylsp[(yyi + 1) - (yynrhs)])                );
+      yy_symbol_print (stderr,
+                       yystos[yyssp[yyi + 1 - yynrhs]],
+                       &(yyvsp[(yyi + 1) - (yynrhs)])
+                       , &(yylsp[(yyi + 1) - (yynrhs)])                       );
       YYFPRINTF (stderr, "\n");
     }
 }
 
-# define YY_REDUCE_PRINT(Rule)         \
-do {                                   \
-  if (yydebug)                         \
-    yy_reduce_print (yyvsp, yylsp, Rule); \
-} while (YYID (0))
+# define YY_REDUCE_PRINT(Rule)          \
+do {                                    \
+  if (yydebug)                          \
+    yy_reduce_print (yyssp, yyvsp, yylsp, Rule); \
+} while (0)
 
 /* Nonzero means print parse trace.  It is left uninitialized so that
    multiple parsers can coexist.  */
@@ -1324,7 +1204,7 @@ int yydebug;
 
 
 /* YYINITDEPTH -- initial size of the parser's stacks.  */
-#ifndef        YYINITDEPTH
+#ifndef YYINITDEPTH
 # define YYINITDEPTH 200
 #endif
 
@@ -1441,7 +1321,7 @@ do {                                                             \
           goto yyerrlab;                                         \
       }                                                          \
     }                                                            \
-} while (YYID (0))
+} while (0)
 
 /* Discard any previous initial lookahead context because of Event,
    which may be a lookahead change or an invalidation of the currently
@@ -1464,7 +1344,7 @@ do {                                                                     \
                    Event "\n");                                          \
       yy_lac_established = 0;                                            \
     }                                                                    \
-} while (YYID (0))
+} while (0)
 #else
 # define YY_LAC_DISCARD(Event) yy_lac_established = 0
 #endif
@@ -1580,15 +1460,8 @@ yy_lac (yytype_int16 *yyesa, yytype_int16 **yyes,
 #   define yystrlen strlen
 #  else
 /* Return the length of YYSTR.  */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
 static YYSIZE_T
 yystrlen (const char *yystr)
-#else
-static YYSIZE_T
-yystrlen (yystr)
-    const char *yystr;
-#endif
 {
   YYSIZE_T yylen;
   for (yylen = 0; yystr[yylen]; yylen++)
@@ -1604,16 +1477,8 @@ yystrlen (yystr)
 #  else
 /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
    YYDEST.  */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
 static char *
 yystpcpy (char *yydest, const char *yysrc)
-#else
-static char *
-yystpcpy (yydest, yysrc)
-    char *yydest;
-    const char *yysrc;
-#endif
 {
   char *yyd = yydest;
   const char *yys = yysrc;
@@ -1643,27 +1508,27 @@ yytnamerr (char *yyres, const char *yystr)
       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: ;
     }
 
@@ -1691,7 +1556,6 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
 {
   YYSIZE_T yysize0 = yytnamerr (YY_NULL, yytname[yytoken]);
   YYSIZE_T yysize = yysize0;
-  YYSIZE_T yysize1;
   enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
   /* Internationalized format string. */
   const char *yyformat = YY_NULL;
@@ -1702,10 +1566,6 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
   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
@@ -1752,11 +1612,13 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
                     break;
                   }
                 yyarg[yycount++] = yytname[yyx];
-                yysize1 = yysize + yytnamerr (YY_NULL, yytname[yyx]);
-                if (! (yysize <= yysize1
-                       && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
-                  return 2;
-                yysize = yysize1;
+                {
+                  YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULL, yytname[yyx]);
+                  if (! (yysize <= yysize1
+                         && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+                    return 2;
+                  yysize = yysize1;
+                }
               }
         }
 # if GRAM_DEBUG
@@ -1780,10 +1642,12 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
 # undef YYCASE_
     }
 
-  yysize1 = yysize + yystrlen (yyformat);
-  if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
-    return 2;
-  yysize = yysize1;
+  {
+    YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
+    if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+      return 2;
+    yysize = yysize1;
+  }
 
   if (*yymsg_alloc < yysize)
     {
@@ -1820,32 +1684,19 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
 | Release the memory associated to this symbol.  |
 `-----------------------------------------------*/
 
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
 static void
 yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp)
-#else
-static void
-yydestruct (yymsg, yytype, yyvaluep, yylocationp)
-    const char *yymsg;
-    int yytype;
-    YYSTYPE *yyvaluep;
-    YYLTYPE *yylocationp;
-#endif
 {
   YYUSE (yyvaluep);
   YYUSE (yylocationp);
-
   if (!yymsg)
     yymsg = "Deleting";
   YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
 
   switch (yytype)
     {
-
       default:
-       break;
+        break;
     }
 }
 
@@ -1856,27 +1707,8 @@ yydestruct (yymsg, yytype, yyvaluep, yylocationp)
 | yyparse.  |
 `----------*/
 
-#ifdef YYPARSE_PARAM
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (void *YYPARSE_PARAM)
-#else
-int
-yyparse (YYPARSE_PARAM)
-    void *YYPARSE_PARAM;
-#endif
-#else /* ! YYPARSE_PARAM */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
 int
 yyparse (void)
-#else
-int
-yyparse ()
-
-#endif
-#endif
 {
 /* The lookahead symbol.  */
 int yychar;
@@ -1896,6 +1728,11 @@ int yychar;
 static YYSTYPE yyval_default;
 # define YY_INITIAL_VALUE(Value) = Value
 #endif
+static YYLTYPE yyloc_default
+# if defined GRAM_LTYPE_IS_TRIVIAL && GRAM_LTYPE_IS_TRIVIAL
+  = { 1, 1, 1, 1 }
+# endif
+;
 #ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
 # define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
 # define YY_IGNORE_MAYBE_UNINITIALIZED_END
@@ -1908,11 +1745,7 @@ static YYSTYPE yyval_default;
 YYSTYPE yylval YY_INITIAL_VALUE(yyval_default);
 
 /* Location data for the lookahead symbol.  */
-YYLTYPE yylloc
-# if defined GRAM_LTYPE_IS_TRIVIAL && GRAM_LTYPE_IS_TRIVIAL
-  = { 1, 1, 1, 1 }
-# endif
-;
+YYLTYPE yylloc = yyloc_default;
 
 
     /* Number of syntax errors so far.  */
@@ -1923,9 +1756,9 @@ YYLTYPE yylloc
     int yyerrstatus;
 
     /* The stacks and their tools:
-       `yyss': related to states.
-       `yyvs': related to semantic values.
-       `yyls': related to locations.
+       'yyss': related to states.
+       'yyvs': related to semantic values.
+       'yyls': related to locations.
 
        Refer to the stacks through separate pointers, to allow yyoverflow
        to reallocate them elsewhere.  */
@@ -1995,16 +1828,14 @@ YYLTYPE yylloc
   yychar = YYEMPTY; /* Cause a token to be read.  */
 
 /* User initialization code.  */
-/* Line 1560 of yacc.c  */
-#line 107 "parse-gram.y"
+#line 96 "src/parse-gram.y" /* yacc.c:1451  */
 {
   /* Bison's grammar can initial empty locations, hence a default
      location is needed. */
   boundary_set (&yylloc.start, current_file, 1, 1);
   boundary_set (&yylloc.end, current_file, 1, 1);
 }
-/* Line 1560 of yacc.c  */
-#line 2008 "parse-gram.c"
+#line 1839 "src/parse-gram.c" /* yacc.c:1451  */
   yylsp[0] = yylloc;
   goto yysetstate;
 
@@ -2026,26 +1857,26 @@ YYLTYPE yylloc
 
 #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;
-       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),
-                   &yyls1, yysize * sizeof (*yylsp),
-                   &yystacksize);
-
-       yyls = yyls1;
-       yyss = yyss1;
-       yyvs = yyvs1;
+        /* 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;
+        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),
+                    &yyls1, yysize * sizeof (*yylsp),
+                    &yystacksize);
+
+        yyls = yyls1;
+        yyss = yyss1;
+        yyvs = yyvs1;
       }
 #else /* no yyoverflow */
 # ifndef YYSTACK_RELOCATE
@@ -2053,23 +1884,23 @@ YYLTYPE yylloc
 # 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);
-       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);
+        YYSTACK_RELOCATE (yyls_alloc, yyls);
 #  undef YYSTACK_RELOCATE
-       if (yyss1 != yyssa)
-         YYSTACK_FREE (yyss1);
+        if (yyss1 != yyssa)
+          YYSTACK_FREE (yyss1);
       }
 # endif
 #endif /* no yyoverflow */
@@ -2079,10 +1910,10 @@ YYLTYPE yylloc
       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));
@@ -2111,7 +1942,7 @@ yybackup:
   if (yychar == YYEMPTY)
     {
       YYDPRINTF ((stderr, "Reading a token: "));
-      yychar = YYLEX;
+      yychar = yylex (&yylval, &yylloc);
     }
 
   if (yychar <= YYEOF)
@@ -2181,7 +2012,7 @@ yyreduce:
   yylen = yyr2[yyn];
 
   /* If YYLEN is nonzero, implement the default value of the action:
-     `$$ = $1'.
+     '$$ = $1'.
 
      Otherwise, the following line sets YYVAL to garbage.
      This behavior is undocumented and Bison
@@ -2198,192 +2029,154 @@ yyreduce:
     switch (yyn)
       {
           case 6:
-/* Line 1778 of yacc.c  */
-#line 246 "parse-gram.y"
+#line 277 "src/parse-gram.y" /* yacc.c:1668  */
     {
       code_props plain_code;
-      code_props_plain_init (&plain_code, (yyvsp[(1) - (1)].chars), (yylsp[(1) - (1)]));
+      code_props_plain_init (&plain_code, (yyvsp[0].chars), (yylsp[0]));
       code_props_translate_code (&plain_code);
       gram_scanner_last_string_free ();
       muscle_code_grow (union_seen ? "post_prologue" : "pre_prologue",
-                        plain_code.code, (yylsp[(1) - (1)]));
+                        plain_code.code, (yylsp[0]));
       code_scanner_last_string_free ();
     }
+#line 2043 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 7:
-/* Line 1778 of yacc.c  */
-#line 255 "parse-gram.y"
-    { debug = true; }
+#line 287 "src/parse-gram.y" /* yacc.c:1668  */
+    {
+      muscle_percent_define_ensure ((yyvsp[0].uniqstr), (yylsp[0]), true);
+    }
+#line 2051 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 8:
-/* Line 1778 of yacc.c  */
-#line 257 "parse-gram.y"
+#line 291 "src/parse-gram.y" /* yacc.c:1668  */
     {
-      muscle_percent_define_insert ((yyvsp[(2) - (3)].uniqstr), (yylsp[(2) - (3)]), (yyvsp[(3) - (3)].chars),
+      muscle_percent_define_insert ((yyvsp[-1].uniqstr), (yylsp[-1]), (yyvsp[0].value).kind, (yyvsp[0].value).chars,
                                     MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE);
     }
+#line 2060 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 9:
-/* Line 1778 of yacc.c  */
-#line 261 "parse-gram.y"
+#line 295 "src/parse-gram.y" /* yacc.c:1668  */
     { defines_flag = true; }
+#line 2066 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 10:
-/* Line 1778 of yacc.c  */
-#line 263 "parse-gram.y"
+#line 297 "src/parse-gram.y" /* yacc.c:1668  */
     {
       defines_flag = true;
-      spec_defines_file = xstrdup ((yyvsp[(2) - (2)].chars));
+      spec_defines_file = xstrdup ((yyvsp[0].chars));
     }
+#line 2075 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 11:
-/* Line 1778 of yacc.c  */
-#line 267 "parse-gram.y"
-    { error_verbose = true; }
+#line 302 "src/parse-gram.y" /* yacc.c:1668  */
+    {
+      muscle_percent_define_insert ("parse.error", (yylsp[0]), muscle_keyword,
+                                    "verbose",
+                                    MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE);
+    }
+#line 2085 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 12:
-/* Line 1778 of yacc.c  */
-#line 268 "parse-gram.y"
-    { expected_sr_conflicts = (yyvsp[(2) - (2)].integer); }
+#line 307 "src/parse-gram.y" /* yacc.c:1668  */
+    { expected_sr_conflicts = (yyvsp[0].integer); }
+#line 2091 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 13:
-/* Line 1778 of yacc.c  */
-#line 269 "parse-gram.y"
-    { expected_rr_conflicts = (yyvsp[(2) - (2)].integer); }
+#line 308 "src/parse-gram.y" /* yacc.c:1668  */
+    { expected_rr_conflicts = (yyvsp[0].integer); }
+#line 2097 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 14:
-/* Line 1778 of yacc.c  */
-#line 270 "parse-gram.y"
-    { spec_file_prefix = (yyvsp[(2) - (2)].chars); }
+#line 309 "src/parse-gram.y" /* yacc.c:1668  */
+    { spec_file_prefix = (yyvsp[0].chars); }
+#line 2103 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 15:
-/* Line 1778 of yacc.c  */
-#line 271 "parse-gram.y"
-    { spec_file_prefix = (yyvsp[(3) - (3)].chars); }
-    break;
-
-  case 16:
-/* Line 1778 of yacc.c  */
-#line 273 "parse-gram.y"
+#line 311 "src/parse-gram.y" /* yacc.c:1668  */
     {
       nondeterministic_parser = true;
       glr_parser = true;
     }
+#line 2112 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
-  case 17:
-/* Line 1778 of yacc.c  */
-#line 278 "parse-gram.y"
+  case 16:
+#line 316 "src/parse-gram.y" /* yacc.c:1668  */
     {
       code_props action;
-      code_props_symbol_action_init (&action, (yyvsp[(2) - (2)].code), (yylsp[(2) - (2)]));
+      code_props_symbol_action_init (&action, (yyvsp[0].code), (yylsp[0]));
       code_props_translate_code (&action);
       gram_scanner_last_string_free ();
-      muscle_code_grow ("initial_action", action.code, (yylsp[(2) - (2)]));
+      muscle_code_grow ("initial_action", action.code, (yylsp[0]));
       code_scanner_last_string_free ();
     }
+#line 2125 "src/parse-gram.c" /* yacc.c:1668  */
+    break;
+
+  case 17:
+#line 324 "src/parse-gram.y" /* yacc.c:1668  */
+    { language_argmatch ((yyvsp[0].chars), grammar_prio, (yylsp[-1])); }
+#line 2131 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 18:
-/* Line 1778 of yacc.c  */
-#line 286 "parse-gram.y"
-    { language_argmatch ((yyvsp[(2) - (2)].chars), grammar_prio, (yylsp[(1) - (2)])); }
+#line 325 "src/parse-gram.y" /* yacc.c:1668  */
+    { spec_name_prefix = (yyvsp[0].chars); }
+#line 2137 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 19:
-/* Line 1778 of yacc.c  */
-#line 287 "parse-gram.y"
-    { add_param ("lex_param", (yyvsp[(2) - (2)].code), (yylsp[(2) - (2)])); }
+#line 326 "src/parse-gram.y" /* yacc.c:1668  */
+    { no_lines_flag = true; }
+#line 2143 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 20:
-/* Line 1778 of yacc.c  */
-#line 288 "parse-gram.y"
-    { locations_flag = true; }
+#line 327 "src/parse-gram.y" /* yacc.c:1668  */
+    { nondeterministic_parser = true; }
+#line 2149 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 21:
-/* Line 1778 of yacc.c  */
-#line 289 "parse-gram.y"
-    { spec_name_prefix = (yyvsp[(2) - (2)].chars); }
+#line 328 "src/parse-gram.y" /* yacc.c:1668  */
+    { spec_outfile = (yyvsp[0].chars); }
+#line 2155 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 22:
-/* Line 1778 of yacc.c  */
-#line 290 "parse-gram.y"
-    { spec_name_prefix = (yyvsp[(3) - (3)].chars); }
+#line 329 "src/parse-gram.y" /* yacc.c:1668  */
+    { current_param = (yyvsp[0].param); }
+#line 2161 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 23:
-/* Line 1778 of yacc.c  */
-#line 291 "parse-gram.y"
-    { no_lines_flag = true; }
+#line 329 "src/parse-gram.y" /* yacc.c:1668  */
+    { current_param = param_none; }
+#line 2167 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 24:
-/* Line 1778 of yacc.c  */
-#line 292 "parse-gram.y"
-    { nondeterministic_parser = true; }
+#line 330 "src/parse-gram.y" /* yacc.c:1668  */
+    { version_check (&(yylsp[0]), (yyvsp[0].chars)); }
+#line 2173 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 25:
-/* Line 1778 of yacc.c  */
-#line 293 "parse-gram.y"
-    { spec_outfile = (yyvsp[(2) - (2)].chars); }
-    break;
-
-  case 26:
-/* Line 1778 of yacc.c  */
-#line 294 "parse-gram.y"
-    { spec_outfile = (yyvsp[(3) - (3)].chars); }
-    break;
-
-  case 27:
-/* Line 1778 of yacc.c  */
-#line 295 "parse-gram.y"
-    { add_param ("parse_param", (yyvsp[(2) - (2)].code), (yylsp[(2) - (2)])); }
-    break;
-
-  case 28:
-/* Line 1778 of yacc.c  */
-#line 297 "parse-gram.y"
+#line 332 "src/parse-gram.y" /* yacc.c:1668  */
     {
-      /* %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", (yylsp[(1) - (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", (yylsp[(1) - (1)]), "",
-                                      MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE);
-    }
-    break;
-
-  case 29:
-/* Line 1778 of yacc.c  */
-#line 311 "parse-gram.y"
-    { version_check (&(yylsp[(2) - (2)]), (yyvsp[(2) - (2)].chars)); }
-    break;
-
-  case 30:
-/* Line 1778 of yacc.c  */
-#line 313 "parse-gram.y"
-    {
-      char const *skeleton_user = (yyvsp[(2) - (2)].chars);
-      if (mbschr (skeleton_user, '/'))
+      char const *skeleton_user = (yyvsp[0].chars);
+      if (strchr (skeleton_user, '/'))
         {
           size_t dir_length = strlen (current_file);
           char *skeleton_build;
@@ -2402,497 +2195,542 @@ yyreduce:
           skeleton_user = uniqstr_new (skeleton_build);
           free (skeleton_build);
         }
-      skeleton_arg (skeleton_user, grammar_prio, (yylsp[(1) - (2)]));
+      skeleton_arg (skeleton_user, grammar_prio, (yylsp[-1]));
     }
+#line 2201 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
-  case 31:
-/* Line 1778 of yacc.c  */
-#line 336 "parse-gram.y"
+  case 26:
+#line 355 "src/parse-gram.y" /* yacc.c:1668  */
     { token_table_flag = true; }
+#line 2207 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
-  case 32:
-/* Line 1778 of yacc.c  */
-#line 337 "parse-gram.y"
+  case 27:
+#line 356 "src/parse-gram.y" /* yacc.c:1668  */
     { report_flag |= report_states; }
+#line 2213 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
-  case 33:
-/* Line 1778 of yacc.c  */
-#line 338 "parse-gram.y"
+  case 28:
+#line 357 "src/parse-gram.y" /* yacc.c:1668  */
     { yacc_flag = true; }
+#line 2219 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
-  case 37:
-/* Line 1778 of yacc.c  */
-#line 346 "parse-gram.y"
-    {
-      grammar_start_symbol_set ((yyvsp[(2) - (2)].symbol), (yylsp[(2) - (2)]));
-    }
+  case 30:
+#line 362 "src/parse-gram.y" /* yacc.c:1668  */
+    { add_param (current_param, (yyvsp[0].code), (yylsp[0])); }
+#line 2225 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
-  case 38:
-/* Line 1778 of yacc.c  */
-#line 350 "parse-gram.y"
+  case 31:
+#line 363 "src/parse-gram.y" /* yacc.c:1668  */
+    { add_param (current_param, (yyvsp[0].code), (yylsp[0])); }
+#line 2231 "src/parse-gram.c" /* yacc.c:1668  */
+    break;
+
+  case 34:
+#line 375 "src/parse-gram.y" /* yacc.c:1668  */
     {
-      code_props code;
-      code_props_symbol_action_init (&code, (yyvsp[(2) - (3)].code), (yylsp[(2) - (3)]));
-      code_props_translate_code (&code);
-      {
-        symbol_list *list;
-        for (list = (yyvsp[(3) - (3)].list); list; list = list->next)
-          symbol_list_destructor_set (list, &code);
-        symbol_list_free ((yyvsp[(3) - (3)].list));
-      }
+      grammar_start_symbol_set ((yyvsp[0].symbol), (yylsp[0]));
     }
+#line 2239 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
-  case 39:
-/* Line 1778 of yacc.c  */
-#line 362 "parse-gram.y"
+  case 35:
+#line 379 "src/parse-gram.y" /* yacc.c:1668  */
     {
       code_props code;
-      code_props_symbol_action_init (&code, (yyvsp[(2) - (3)].code), (yylsp[(2) - (3)]));
+      code_props_symbol_action_init (&code, (yyvsp[-1].code), (yylsp[-1]));
       code_props_translate_code (&code);
       {
         symbol_list *list;
-        for (list = (yyvsp[(3) - (3)].list); list; list = list->next)
-          symbol_list_printer_set (list, &code);
-        symbol_list_free ((yyvsp[(3) - (3)].list));
+        for (list = (yyvsp[0].list); list; list = list->next)
+          symbol_list_code_props_set (list, (yyvsp[-2].code_type), &code);
+        symbol_list_free ((yyvsp[0].list));
       }
     }
+#line 2255 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
-  case 40:
-/* Line 1778 of yacc.c  */
-#line 374 "parse-gram.y"
+  case 36:
+#line 391 "src/parse-gram.y" /* yacc.c:1668  */
     {
       default_prec = true;
     }
+#line 2263 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
-  case 41:
-/* Line 1778 of yacc.c  */
-#line 378 "parse-gram.y"
+  case 37:
+#line 395 "src/parse-gram.y" /* yacc.c:1668  */
     {
       default_prec = false;
     }
+#line 2271 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
-  case 42:
-/* Line 1778 of yacc.c  */
-#line 382 "parse-gram.y"
+  case 38:
+#line 399 "src/parse-gram.y" /* yacc.c:1668  */
     {
       /* Do not invoke muscle_percent_code_grow here since it invokes
          muscle_user_name_list_grow.  */
-      muscle_code_grow ("percent_code()", (yyvsp[(2) - (2)].chars), (yylsp[(2) - (2)]));
+      muscle_code_grow ("percent_code()", (yyvsp[0].chars), (yylsp[0]));
       code_scanner_last_string_free ();
     }
+#line 2282 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
-  case 43:
-/* Line 1778 of yacc.c  */
-#line 389 "parse-gram.y"
+  case 39:
+#line 406 "src/parse-gram.y" /* yacc.c:1668  */
     {
-      muscle_percent_code_grow ((yyvsp[(2) - (3)].uniqstr), (yylsp[(2) - (3)]), (yyvsp[(3) - (3)].chars), (yylsp[(3) - (3)]));
+      muscle_percent_code_grow ((yyvsp[-1].uniqstr), (yylsp[-1]), (yyvsp[0].chars), (yylsp[0]));
       code_scanner_last_string_free ();
     }
+#line 2291 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
-  case 44:
-/* Line 1778 of yacc.c  */
-#line 403 "parse-gram.y"
+  case 40:
+#line 416 "src/parse-gram.y" /* yacc.c:1668  */
+    { (yyval.code_type) = destructor; }
+#line 2297 "src/parse-gram.c" /* yacc.c:1668  */
+    break;
+
+  case 41:
+#line 417 "src/parse-gram.y" /* yacc.c:1668  */
+    { (yyval.code_type) = printer; }
+#line 2303 "src/parse-gram.c" /* yacc.c:1668  */
+    break;
+
+  case 42:
+#line 427 "src/parse-gram.y" /* yacc.c:1668  */
     {}
+#line 2309 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
-  case 45:
-/* Line 1778 of yacc.c  */
-#line 404 "parse-gram.y"
-    { muscle_code_grow ("union_name", (yyvsp[(1) - (1)].uniqstr), (yylsp[(1) - (1)])); }
+  case 43:
+#line 428 "src/parse-gram.y" /* yacc.c:1668  */
+    { muscle_code_grow ("union_name", (yyvsp[0].uniqstr), (yylsp[0])); }
+#line 2315 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
-  case 46:
-/* Line 1778 of yacc.c  */
-#line 409 "parse-gram.y"
+  case 44:
+#line 433 "src/parse-gram.y" /* yacc.c:1668  */
     {
       union_seen = true;
-      muscle_code_grow ("stype", (yyvsp[(3) - (3)].chars), (yylsp[(3) - (3)]));
+      muscle_code_grow ("union_members", (yyvsp[0].chars), (yylsp[0]));
       code_scanner_last_string_free ();
     }
+#line 2325 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
-  case 47:
-/* Line 1778 of yacc.c  */
-#line 420 "parse-gram.y"
+  case 45:
+#line 444 "src/parse-gram.y" /* yacc.c:1668  */
     { current_class = nterm_sym; }
+#line 2331 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
-  case 48:
-/* Line 1778 of yacc.c  */
-#line 421 "parse-gram.y"
+  case 46:
+#line 445 "src/parse-gram.y" /* yacc.c:1668  */
     {
       current_class = unknown_sym;
       current_type = NULL;
     }
+#line 2340 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
-  case 49:
-/* Line 1778 of yacc.c  */
-#line 425 "parse-gram.y"
+  case 47:
+#line 449 "src/parse-gram.y" /* yacc.c:1668  */
     { current_class = token_sym; }
+#line 2346 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
-  case 50:
-/* Line 1778 of yacc.c  */
-#line 426 "parse-gram.y"
+  case 48:
+#line 450 "src/parse-gram.y" /* yacc.c:1668  */
     {
       current_class = unknown_sym;
       current_type = NULL;
     }
+#line 2355 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
-  case 51:
-/* Line 1778 of yacc.c  */
-#line 431 "parse-gram.y"
+  case 49:
+#line 455 "src/parse-gram.y" /* yacc.c:1668  */
     {
       symbol_list *list;
       tag_seen = true;
-      for (list = (yyvsp[(3) - (3)].list); list; list = list->next)
-       symbol_type_set (list->content.sym, (yyvsp[(2) - (3)].uniqstr), (yylsp[(2) - (3)]));
-      symbol_list_free ((yyvsp[(3) - (3)].list));
+      for (list = (yyvsp[0].list); list; list = list->next)
+        symbol_type_set (list->content.sym, (yyvsp[-1].uniqstr), (yylsp[-1]));
+      symbol_list_free ((yyvsp[0].list));
     }
+#line 2367 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
-  case 52:
-/* Line 1778 of yacc.c  */
-#line 442 "parse-gram.y"
+  case 50:
+#line 466 "src/parse-gram.y" /* yacc.c:1668  */
     {
       symbol_list *list;
       ++current_prec;
-      for (list = (yyvsp[(3) - (3)].list); list; list = list->next)
-       {
-         symbol_type_set (list->content.sym, current_type, (yylsp[(2) - (3)]));
-         symbol_precedence_set (list->content.sym, current_prec, (yyvsp[(1) - (3)].assoc), (yylsp[(1) - (3)]));
-       }
-      symbol_list_free ((yyvsp[(3) - (3)].list));
+      for (list = (yyvsp[0].list); list; list = list->next)
+        {
+          symbol_type_set (list->content.sym, current_type, (yylsp[-1]));
+          symbol_precedence_set (list->content.sym, current_prec, (yyvsp[-2].assoc), (yylsp[-2]));
+        }
+      symbol_list_free ((yyvsp[0].list));
       current_type = NULL;
     }
+#line 2383 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
-  case 53:
-/* Line 1778 of yacc.c  */
-#line 456 "parse-gram.y"
+  case 51:
+#line 480 "src/parse-gram.y" /* yacc.c:1668  */
     { (yyval.assoc) = left_assoc; }
+#line 2389 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
-  case 54:
-/* Line 1778 of yacc.c  */
-#line 457 "parse-gram.y"
+  case 52:
+#line 481 "src/parse-gram.y" /* yacc.c:1668  */
     { (yyval.assoc) = right_assoc; }
+#line 2395 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
-  case 55:
-/* Line 1778 of yacc.c  */
-#line 458 "parse-gram.y"
+  case 53:
+#line 482 "src/parse-gram.y" /* yacc.c:1668  */
     { (yyval.assoc) = non_assoc; }
+#line 2401 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
-  case 56:
-/* Line 1778 of yacc.c  */
-#line 462 "parse-gram.y"
+  case 54:
+#line 483 "src/parse-gram.y" /* yacc.c:1668  */
+    { (yyval.assoc) = precedence_assoc; }
+#line 2407 "src/parse-gram.c" /* yacc.c:1668  */
+    break;
+
+  case 55:
+#line 487 "src/parse-gram.y" /* yacc.c:1668  */
     { current_type = NULL; }
+#line 2413 "src/parse-gram.c" /* yacc.c:1668  */
+    break;
+
+  case 56:
+#line 488 "src/parse-gram.y" /* yacc.c:1668  */
+    { current_type = (yyvsp[0].uniqstr); tag_seen = true; }
+#line 2419 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 57:
-/* Line 1778 of yacc.c  */
-#line 463 "parse-gram.y"
-    { current_type = (yyvsp[(1) - (1)].uniqstr); tag_seen = true; }
+#line 494 "src/parse-gram.y" /* yacc.c:1668  */
+    { (yyval.list) = symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0])); }
+#line 2425 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 58:
-/* Line 1778 of yacc.c  */
-#line 469 "parse-gram.y"
-    { (yyval.list) = symbol_list_sym_new ((yyvsp[(1) - (1)].symbol), (yylsp[(1) - (1)])); }
+#line 496 "src/parse-gram.y" /* yacc.c:1668  */
+    { (yyval.list) = symbol_list_append ((yyvsp[-1].list), symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0]))); }
+#line 2431 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 59:
-/* Line 1778 of yacc.c  */
-#line 471 "parse-gram.y"
-    { (yyval.list) = symbol_list_prepend ((yyvsp[(1) - (2)].list), symbol_list_sym_new ((yyvsp[(2) - (2)].symbol), (yylsp[(2) - (2)]))); }
+#line 501 "src/parse-gram.y" /* yacc.c:1668  */
+    {
+      (yyval.symbol) = (yyvsp[0].symbol);
+      symbol_class_set ((yyvsp[0].symbol), token_sym, (yylsp[0]), false);
+    }
+#line 2440 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 60:
-/* Line 1778 of yacc.c  */
-#line 475 "parse-gram.y"
-    { (yyval.symbol) = (yyvsp[(1) - (1)].symbol); }
+#line 506 "src/parse-gram.y" /* yacc.c:1668  */
+    {
+      (yyval.symbol) = (yyvsp[-1].symbol);
+      symbol_user_token_number_set ((yyvsp[-1].symbol), (yyvsp[0].integer), (yylsp[0]));
+      symbol_class_set ((yyvsp[-1].symbol), token_sym, (yylsp[-1]), false);
+    }
+#line 2450 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 61:
-/* Line 1778 of yacc.c  */
-#line 476 "parse-gram.y"
-    { (yyval.symbol) = (yyvsp[(1) - (2)].symbol); symbol_user_token_number_set ((yyvsp[(1) - (2)].symbol), (yyvsp[(2) - (2)].integer), (yylsp[(2) - (2)])); }
+#line 516 "src/parse-gram.y" /* yacc.c:1668  */
+    { (yyval.list) = symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0])); }
+#line 2456 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 62:
-/* Line 1778 of yacc.c  */
-#line 482 "parse-gram.y"
-    { (yyval.list) = symbol_list_sym_new ((yyvsp[(1) - (1)].symbol), (yylsp[(1) - (1)])); }
+#line 518 "src/parse-gram.y" /* yacc.c:1668  */
+    { (yyval.list) = symbol_list_append ((yyvsp[-1].list), symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0]))); }
+#line 2462 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 63:
-/* Line 1778 of yacc.c  */
-#line 484 "parse-gram.y"
-    { (yyval.list) = symbol_list_prepend ((yyvsp[(1) - (2)].list), symbol_list_sym_new ((yyvsp[(2) - (2)].symbol), (yylsp[(2) - (2)]))); }
+#line 522 "src/parse-gram.y" /* yacc.c:1668  */
+    { (yyval.list) = (yyvsp[0].list); }
+#line 2468 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 64:
-/* Line 1778 of yacc.c  */
-#line 488 "parse-gram.y"
-    { (yyval.list) = (yyvsp[(1) - (1)].list); }
+#line 523 "src/parse-gram.y" /* yacc.c:1668  */
+    { (yyval.list) = symbol_list_append ((yyvsp[-1].list), (yyvsp[0].list)); }
+#line 2474 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 65:
-/* Line 1778 of yacc.c  */
-#line 489 "parse-gram.y"
-    { (yyval.list) = symbol_list_prepend ((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].list)); }
+#line 527 "src/parse-gram.y" /* yacc.c:1668  */
+    { (yyval.list) = symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0])); }
+#line 2480 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 66:
-/* Line 1778 of yacc.c  */
-#line 493 "parse-gram.y"
-    { (yyval.list) = symbol_list_sym_new ((yyvsp[(1) - (1)].symbol), (yylsp[(1) - (1)])); }
-    break;
-
-  case 67:
-/* Line 1778 of yacc.c  */
-#line 494 "parse-gram.y"
-    { (yyval.list) = symbol_list_type_new ((yyvsp[(1) - (1)].uniqstr), (yylsp[(1) - (1)])); }
+#line 528 "src/parse-gram.y" /* yacc.c:1668  */
+    { (yyval.list) = symbol_list_type_new ((yyvsp[0].uniqstr), (yylsp[0])); }
+#line 2486 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 68:
-/* Line 1778 of yacc.c  */
-#line 495 "parse-gram.y"
-    { (yyval.list) = symbol_list_default_tagged_new ((yylsp[(1) - (1)])); }
+#line 533 "src/parse-gram.y" /* yacc.c:1668  */
+    { (yyval.uniqstr) = uniqstr_new ("*"); }
+#line 2492 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 69:
-/* Line 1778 of yacc.c  */
-#line 496 "parse-gram.y"
-    { (yyval.list) = symbol_list_default_tagless_new ((yylsp[(1) - (1)])); }
+#line 534 "src/parse-gram.y" /* yacc.c:1668  */
+    { (yyval.uniqstr) = uniqstr_new (""); }
+#line 2498 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 70:
-/* Line 1778 of yacc.c  */
-#line 502 "parse-gram.y"
+#line 540 "src/parse-gram.y" /* yacc.c:1668  */
     {
-       current_type = (yyvsp[(1) - (1)].uniqstr);
-       tag_seen = true;
-     }
+      current_type = (yyvsp[0].uniqstr);
+      tag_seen = true;
+    }
+#line 2507 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 71:
-/* Line 1778 of yacc.c  */
-#line 507 "parse-gram.y"
+#line 545 "src/parse-gram.y" /* yacc.c:1668  */
     {
-       symbol_class_set ((yyvsp[(1) - (1)].symbol), current_class, (yylsp[(1) - (1)]), true);
-       symbol_type_set ((yyvsp[(1) - (1)].symbol), current_type, (yylsp[(1) - (1)]));
-     }
+      symbol_class_set ((yyvsp[0].symbol), current_class, (yylsp[0]), true);
+      symbol_type_set ((yyvsp[0].symbol), current_type, (yylsp[0]));
+    }
+#line 2516 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 72:
-/* Line 1778 of yacc.c  */
-#line 512 "parse-gram.y"
+#line 550 "src/parse-gram.y" /* yacc.c:1668  */
     {
-      symbol_class_set ((yyvsp[(1) - (2)].symbol), current_class, (yylsp[(1) - (2)]), true);
-      symbol_type_set ((yyvsp[(1) - (2)].symbol), current_type, (yylsp[(1) - (2)]));
-      symbol_user_token_number_set ((yyvsp[(1) - (2)].symbol), (yyvsp[(2) - (2)].integer), (yylsp[(2) - (2)]));
+      symbol_class_set ((yyvsp[-1].symbol), current_class, (yylsp[-1]), true);
+      symbol_type_set ((yyvsp[-1].symbol), current_type, (yylsp[-1]));
+      symbol_user_token_number_set ((yyvsp[-1].symbol), (yyvsp[0].integer), (yylsp[0]));
     }
+#line 2526 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 73:
-/* Line 1778 of yacc.c  */
-#line 518 "parse-gram.y"
+#line 556 "src/parse-gram.y" /* yacc.c:1668  */
     {
-      symbol_class_set ((yyvsp[(1) - (2)].symbol), current_class, (yylsp[(1) - (2)]), true);
-      symbol_type_set ((yyvsp[(1) - (2)].symbol), current_type, (yylsp[(1) - (2)]));
-      symbol_make_alias ((yyvsp[(1) - (2)].symbol), (yyvsp[(2) - (2)].symbol), (yyloc));
+      symbol_class_set ((yyvsp[-1].symbol), current_class, (yylsp[-1]), true);
+      symbol_type_set ((yyvsp[-1].symbol), current_type, (yylsp[-1]));
+      symbol_make_alias ((yyvsp[-1].symbol), (yyvsp[0].symbol), (yyloc));
     }
+#line 2536 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 74:
-/* Line 1778 of yacc.c  */
-#line 524 "parse-gram.y"
+#line 562 "src/parse-gram.y" /* yacc.c:1668  */
     {
-      symbol_class_set ((yyvsp[(1) - (3)].symbol), current_class, (yylsp[(1) - (3)]), true);
-      symbol_type_set ((yyvsp[(1) - (3)].symbol), current_type, (yylsp[(1) - (3)]));
-      symbol_user_token_number_set ((yyvsp[(1) - (3)].symbol), (yyvsp[(2) - (3)].integer), (yylsp[(2) - (3)]));
-      symbol_make_alias ((yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol), (yyloc));
+      symbol_class_set ((yyvsp[-2].symbol), current_class, (yylsp[-2]), true);
+      symbol_type_set ((yyvsp[-2].symbol), current_type, (yylsp[-2]));
+      symbol_user_token_number_set ((yyvsp[-2].symbol), (yyvsp[-1].integer), (yylsp[-1]));
+      symbol_make_alias ((yyvsp[-2].symbol), (yyvsp[0].symbol), (yyloc));
     }
+#line 2547 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 81:
-/* Line 1778 of yacc.c  */
-#line 554 "parse-gram.y"
+#line 592 "src/parse-gram.y" /* yacc.c:1668  */
     {
       yyerrok;
     }
+#line 2555 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 82:
-/* Line 1778 of yacc.c  */
-#line 560 "parse-gram.y"
-    { current_lhs ((yyvsp[(1) - (2)].symbol), (yylsp[(1) - (2)]), (yyvsp[(2) - (2)].named_ref)); }
+#line 598 "src/parse-gram.y" /* yacc.c:1668  */
+    { current_lhs ((yyvsp[-1].symbol), (yylsp[-1]), (yyvsp[0].named_ref)); }
+#line 2561 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 83:
-/* Line 1778 of yacc.c  */
-#line 561 "parse-gram.y"
+#line 599 "src/parse-gram.y" /* yacc.c:1668  */
     {
     /* Free the current lhs. */
-    current_lhs (0, (yylsp[(1) - (4)]), 0);
+    current_lhs (0, (yylsp[-3]), 0);
   }
+#line 2570 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 84:
-/* Line 1778 of yacc.c  */
-#line 568 "parse-gram.y"
-    { grammar_current_rule_end ((yylsp[(1) - (1)])); }
+#line 606 "src/parse-gram.y" /* yacc.c:1668  */
+    { grammar_current_rule_end ((yylsp[0])); }
+#line 2576 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 85:
-/* Line 1778 of yacc.c  */
-#line 569 "parse-gram.y"
-    { grammar_current_rule_end ((yylsp[(3) - (3)])); }
+#line 607 "src/parse-gram.y" /* yacc.c:1668  */
+    { grammar_current_rule_end ((yylsp[0])); }
+#line 2582 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 87:
-/* Line 1778 of yacc.c  */
-#line 575 "parse-gram.y"
+#line 614 "src/parse-gram.y" /* yacc.c:1668  */
     { grammar_current_rule_begin (current_lhs_symbol, current_lhs_location,
-                                 current_lhs_named_ref); }
+                                  current_lhs_named_ref); }
+#line 2589 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 88:
-/* Line 1778 of yacc.c  */
-#line 578 "parse-gram.y"
-    { grammar_current_rule_symbol_append ((yyvsp[(2) - (3)].symbol), (yylsp[(2) - (3)]), (yyvsp[(3) - (3)].named_ref)); }
+#line 617 "src/parse-gram.y" /* yacc.c:1668  */
+    { grammar_current_rule_symbol_append ((yyvsp[-1].symbol), (yylsp[-1]), (yyvsp[0].named_ref)); }
+#line 2595 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 89:
-/* Line 1778 of yacc.c  */
-#line 580 "parse-gram.y"
-    { grammar_current_rule_action_append ((yyvsp[(2) - (3)].code), (yylsp[(2) - (3)]), (yyvsp[(3) - (3)].named_ref)); }
+#line 619 "src/parse-gram.y" /* yacc.c:1668  */
+    { grammar_current_rule_action_append ((yyvsp[-1].code), (yylsp[-1]), (yyvsp[0].named_ref), false); }
+#line 2601 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 90:
-/* Line 1778 of yacc.c  */
-#line 582 "parse-gram.y"
-    { grammar_current_rule_prec_set ((yyvsp[(3) - (3)].symbol), (yylsp[(3) - (3)])); }
+#line 621 "src/parse-gram.y" /* yacc.c:1668  */
+    { grammar_current_rule_action_append ((yyvsp[0].code), (yylsp[0]), NULL, true); }
+#line 2607 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 91:
-/* Line 1778 of yacc.c  */
-#line 584 "parse-gram.y"
-    { grammar_current_rule_dprec_set ((yyvsp[(3) - (3)].integer), (yylsp[(3) - (3)])); }
+#line 623 "src/parse-gram.y" /* yacc.c:1668  */
+    { grammar_current_rule_empty_set ((yylsp[0])); }
+#line 2613 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 92:
-/* Line 1778 of yacc.c  */
-#line 586 "parse-gram.y"
-    { grammar_current_rule_merge_set ((yyvsp[(3) - (3)].uniqstr), (yylsp[(3) - (3)])); }
+#line 625 "src/parse-gram.y" /* yacc.c:1668  */
+    { grammar_current_rule_prec_set ((yyvsp[0].symbol), (yylsp[0])); }
+#line 2619 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 93:
-/* Line 1778 of yacc.c  */
-#line 590 "parse-gram.y"
-    { (yyval.named_ref) = 0; }
+#line 627 "src/parse-gram.y" /* yacc.c:1668  */
+    { grammar_current_rule_dprec_set ((yyvsp[0].integer), (yylsp[0])); }
+#line 2625 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 94:
-/* Line 1778 of yacc.c  */
-#line 592 "parse-gram.y"
-    { (yyval.named_ref) = named_ref_new((yyvsp[(1) - (1)].uniqstr), (yylsp[(1) - (1)])); }
+#line 629 "src/parse-gram.y" /* yacc.c:1668  */
+    { grammar_current_rule_merge_set ((yyvsp[0].uniqstr), (yylsp[0])); }
+#line 2631 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
-  case 96:
-/* Line 1778 of yacc.c  */
-#line 604 "parse-gram.y"
-    { (yyval.uniqstr) = uniqstr_new ((yyvsp[(1) - (1)].chars)); }
+  case 95:
+#line 633 "src/parse-gram.y" /* yacc.c:1668  */
+    { (yyval.named_ref) = 0; }
+#line 2637 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
-  case 97:
-/* Line 1778 of yacc.c  */
-#line 609 "parse-gram.y"
-    { (yyval.chars) = ""; }
+  case 96:
+#line 634 "src/parse-gram.y" /* yacc.c:1668  */
+    { (yyval.named_ref) = named_ref_new((yyvsp[0].uniqstr), (yylsp[0])); }
+#line 2643 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 98:
-/* Line 1778 of yacc.c  */
-#line 610 "parse-gram.y"
-    { (yyval.chars) = (yyvsp[(1) - (1)].uniqstr); }
+#line 645 "src/parse-gram.y" /* yacc.c:1668  */
+    { (yyval.uniqstr) = uniqstr_new ((yyvsp[0].chars)); }
+#line 2649 "src/parse-gram.c" /* yacc.c:1668  */
+    break;
+
+  case 99:
+#line 670 "src/parse-gram.y" /* yacc.c:1668  */
+    { (yyval.value).kind = muscle_keyword; (yyval.value).chars = ""; }
+#line 2655 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
   case 100:
-/* Line 1778 of yacc.c  */
-#line 621 "parse-gram.y"
+#line 671 "src/parse-gram.y" /* yacc.c:1668  */
+    { (yyval.value).kind = muscle_keyword; (yyval.value).chars = (yyvsp[0].uniqstr); }
+#line 2661 "src/parse-gram.c" /* yacc.c:1668  */
+    break;
+
+  case 101:
+#line 672 "src/parse-gram.y" /* yacc.c:1668  */
+    { (yyval.value).kind = muscle_string;  (yyval.value).chars = (yyvsp[0].chars); }
+#line 2667 "src/parse-gram.c" /* yacc.c:1668  */
+    break;
+
+  case 102:
+#line 673 "src/parse-gram.y" /* yacc.c:1668  */
+    { (yyval.value).kind = muscle_code;    (yyval.value).chars = (yyvsp[0].chars); }
+#line 2673 "src/parse-gram.c" /* yacc.c:1668  */
+    break;
+
+  case 103:
+#line 683 "src/parse-gram.y" /* yacc.c:1668  */
     {
       code_props plain_code;
-      (yyvsp[(1) - (1)].code)[strlen ((yyvsp[(1) - (1)].code)) - 1] = '\n';
-      code_props_plain_init (&plain_code, (yyvsp[(1) - (1)].code)+1, (yylsp[(1) - (1)]));
+      (yyvsp[0].code)[strlen ((yyvsp[0].code)) - 1] = '\0';
+      code_props_plain_init (&plain_code, (yyvsp[0].code)+1, (yylsp[0]));
       code_props_translate_code (&plain_code);
       gram_scanner_last_string_free ();
       (yyval.chars) = plain_code.code;
     }
+#line 2686 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
-  case 101:
-/* Line 1778 of yacc.c  */
-#line 641 "parse-gram.y"
-    { (yyval.symbol) = symbol_from_uniqstr ((yyvsp[(1) - (1)].uniqstr), (yylsp[(1) - (1)])); }
+  case 104:
+#line 703 "src/parse-gram.y" /* yacc.c:1668  */
+    { (yyval.symbol) = symbol_from_uniqstr ((yyvsp[0].uniqstr), (yylsp[0])); }
+#line 2692 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
-  case 102:
-/* Line 1778 of yacc.c  */
-#line 643 "parse-gram.y"
+  case 105:
+#line 705 "src/parse-gram.y" /* yacc.c:1668  */
     {
-      (yyval.symbol) = symbol_get (char_name ((yyvsp[(1) - (1)].character)), (yylsp[(1) - (1)]));
-      symbol_class_set ((yyval.symbol), token_sym, (yylsp[(1) - (1)]), false);
-      symbol_user_token_number_set ((yyval.symbol), (yyvsp[(1) - (1)].character), (yylsp[(1) - (1)]));
+      (yyval.symbol) = symbol_get (char_name ((yyvsp[0].character)), (yylsp[0]));
+      symbol_class_set ((yyval.symbol), token_sym, (yylsp[0]), false);
+      symbol_user_token_number_set ((yyval.symbol), (yyvsp[0].character), (yylsp[0]));
     }
+#line 2702 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
-  case 103:
-/* Line 1778 of yacc.c  */
-#line 651 "parse-gram.y"
-    { (yyval.symbol) = symbol_from_uniqstr ((yyvsp[(1) - (1)].uniqstr), (yylsp[(1) - (1)])); }
+  case 106:
+#line 713 "src/parse-gram.y" /* yacc.c:1668  */
+    { (yyval.symbol) = symbol_from_uniqstr ((yyvsp[0].uniqstr), (yylsp[0])); }
+#line 2708 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
-  case 106:
-/* Line 1778 of yacc.c  */
-#line 663 "parse-gram.y"
+  case 109:
+#line 725 "src/parse-gram.y" /* yacc.c:1668  */
     {
-      (yyval.symbol) = symbol_get (quotearg_style (c_quoting_style, (yyvsp[(1) - (1)].chars)), (yylsp[(1) - (1)]));
-      symbol_class_set ((yyval.symbol), token_sym, (yylsp[(1) - (1)]), false);
+      (yyval.symbol) = symbol_get (quotearg_style (c_quoting_style, (yyvsp[0].chars)), (yylsp[0]));
+      symbol_class_set ((yyval.symbol), token_sym, (yylsp[0]), false);
     }
+#line 2717 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
-  case 108:
-/* Line 1778 of yacc.c  */
-#line 672 "parse-gram.y"
+  case 111:
+#line 734 "src/parse-gram.y" /* yacc.c:1668  */
     {
       code_props plain_code;
-      code_props_plain_init (&plain_code, (yyvsp[(2) - (2)].chars), (yylsp[(2) - (2)]));
+      code_props_plain_init (&plain_code, (yyvsp[0].chars), (yylsp[0]));
       code_props_translate_code (&plain_code);
       gram_scanner_last_string_free ();
-      muscle_code_grow ("epilogue", plain_code.code, (yylsp[(2) - (2)]));
+      muscle_code_grow ("epilogue", plain_code.code, (yylsp[0]));
       code_scanner_last_string_free ();
     }
+#line 2730 "src/parse-gram.c" /* yacc.c:1668  */
     break;
 
 
-/* Line 1778 of yacc.c  */
-#line 2896 "parse-gram.c"
+#line 2734 "src/parse-gram.c" /* yacc.c:1668  */
         default: break;
       }
     if (yychar_backup != yychar)
@@ -2918,7 +2756,7 @@ yyreduce:
   *++yyvsp = yyval;
   *++yylsp = yyloc;
 
-  /* Now `shift' the result of the reduction.  Determine what state
+  /* Now 'shift' the result of the reduction.  Determine what state
      that goes to, based on the state we popped back to and the rule
      number reduced by.  */
 
@@ -2933,9 +2771,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.  */
@@ -2946,7 +2784,7 @@ yyerrlab:
     {
       ++yynerrs;
 #if ! YYERROR_VERBOSE
-      yyerror (YY_("syntax error"));
+      yyerror (&yylloc, YY_("syntax error"));
 #else
 # define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
                                         yyesa, &yyes, &yyes_capacity, \
@@ -2976,7 +2814,7 @@ yyerrlab:
                 yymsgp = yymsg;
               }
           }
-        yyerror (yymsgp);
+        yyerror (&yylloc, yymsgp);
         if (yysyntax_error_status == 2)
           goto yyexhaustedlab;
       }
@@ -2989,20 +2827,20 @@ yyerrlab:
   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, &yylloc);
-         yychar = YYEMPTY;
-       }
+        {
+          yydestruct ("Error: discarding",
+                      yytoken, &yylval, &yylloc);
+          yychar = YYEMPTY;
+        }
     }
 
   /* Else will try to reuse lookahead token after shifting the error
@@ -3022,7 +2860,7 @@ yyerrorlab:
      goto yyerrorlab;
 
   yyerror_range[1] = yylsp[1-yylen];
-  /* Do not reclaim the symbols of the rule which action triggered
+  /* Do not reclaim the symbols of the rule whose action triggered
      this YYERROR.  */
   YYPOPSTACK (yylen);
   yylen = 0;
@@ -3035,29 +2873,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;
 
       yyerror_range[1] = *yylsp;
       yydestruct ("Error: popping",
-                 yystos[yystate], yyvsp, yylsp);
+                  yystos[yystate], yyvsp, yylsp);
       YYPOPSTACK (1);
       yystate = *yyssp;
       YY_STACK_PRINT (yyss, yyssp);
@@ -3103,7 +2941,7 @@ yyabortlab:
 | yyexhaustedlab -- memory exhaustion comes here.  |
 `-------------------------------------------------*/
 yyexhaustedlab:
-  yyerror (YY_("memory exhausted"));
+  yyerror (&yylloc, YY_("memory exhausted"));
   yyresult = 2;
   /* Fall through.  */
 #endif
@@ -3117,14 +2955,14 @@ yyreturn:
       yydestruct ("Cleanup: discarding lookahead",
                   yytoken, &yylval, &yylloc);
     }
-  /* Do not reclaim the symbols of the rule which action triggered
+  /* Do not reclaim the symbols of the rule whose action triggered
      this YYABORT or YYACCEPT.  */
   YYPOPSTACK (yylen);
   YY_STACK_PRINT (yyss, yyssp);
   while (yyssp != yyss)
     {
       yydestruct ("Cleanup: popping",
-                 yystos[*yyssp], yyvsp, yylsp);
+                  yystos[*yyssp], yyvsp, yylsp);
       YYPOPSTACK (1);
     }
 #ifndef yyoverflow
@@ -3137,14 +2975,9 @@ yyreturn:
   if (yymsg != yymsgbuf)
     YYSTACK_FREE (yymsg);
 #endif
-  /* Make sure YYID is used.  */
-  return YYID (yyresult);
+  return yyresult;
 }
-
-
-/* Line 2041 of yacc.c  */
-#line 682 "parse-gram.y"
-
+#line 744 "src/parse-gram.y" /* yacc.c:1928  */
 
 
 /* Return the location of the left-hand side of a rule whose
@@ -3169,51 +3002,53 @@ 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.  */
-  --p;
-  while (c_isspace ((unsigned char) *p))
+  {
+    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.  */
     --p;
-  p[1] = '\0';
-  ++decl;
-  while (c_isspace ((unsigned char) *decl))
+  while (c_isspace ((unsigned char) *p))
+      --p;
+    p[1] = '\0';
     ++decl;
+  while (c_isspace ((unsigned char) *decl))
+      ++decl;
+  }
 
   if (! name_start)
-    complain_at (loc, _("missing identifier in parameter declaration"));
+    complain (&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);
     }
 
@@ -3226,8 +3061,8 @@ version_check (location const *loc, char const *version)
 {
   if (strverscmp (version, PACKAGE_VERSION) > 0)
     {
-      complain_at (*loc, "require bison %s, but have %s",
-                   version, PACKAGE_VERSION);
+      complain (loc, complaint, "require bison %s, but have %s",
+                version, PACKAGE_VERSION);
       exit (EX_MISMATCH);
     }
 }
@@ -3235,7 +3070,7 @@ version_check (location const *loc, char const *version)
 static void
 gram_error (location const *loc, char const *msg)
 {
-  complain_at (*loc, "%s", msg);
+  complain (loc, complaint, "%s", msg);
 }
 
 char const *
index c709098fb9c4a5ce2f05b387b5610303d8b51840..b64cfa4fcfc18ab68af6793c17a7881ce6365124 100644 (file)
@@ -1,19 +1,19 @@
-/* A Bison parser, made by GNU Bison 2.6.5.63-3ada.  */
+/* A Bison parser, made by GNU Bison 2.7.1127-02879-dirty.  */
 
 /* Bison interface for Yacc-like parsers in C
-   
-      Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc.
-   
+
+   Copyright (C) 1984, 1989-1990, 2000-2013 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/>.  */
 
    special exception, which will cause the skeleton and the resulting
    Bison output files to be licensed under the GNU General Public
    License without this special exception.
-   
+
    This special exception was added by the Free Software Foundation in
    version 2.2 of Bison.  */
 
-#ifndef YY_GRAM__________SRC_PARSE_GRAM_H_INCLUDED
-# define YY_GRAM__________SRC_PARSE_GRAM_H_INCLUDED
-/* Enabling traces.  */
+#ifndef YY_GRAM_SRC_PARSE_GRAM_H_INCLUDED
+# define YY_GRAM_SRC_PARSE_GRAM_H_INCLUDED
+/* Debug traces.  */
 #ifndef GRAM_DEBUG
 # if defined YYDEBUG
-#  if YYDEBUG
+#if YYDEBUG
 #   define GRAM_DEBUG 1
 #  else
 #   define GRAM_DEBUG 0
 #if GRAM_DEBUG
 extern int gram_debug;
 #endif
+/* "%code requires" blocks.  */
+#line 218 "src/parse-gram.y" /* yacc.c:1931  */
 
-/* Tokens.  */
+  typedef enum
+  {
+    param_none   = 0,
+    param_lex    = 1 << 0,
+    param_parse  = 1 << 1,
+    param_both   = param_lex | param_parse
+  } param_type;
+
+#line 649 "src/parse-gram.y" /* yacc.c:1931  */
+#include "muscle-tab.h"
+
+#line 65 "src/parse-gram.h" /* yacc.c:1931  */
+
+/* Token type.  */
 #ifndef GRAM_TOKENTYPE
 # define GRAM_TOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum gram_tokentype {
-     GRAM_EOF = 0,
-     STRING = 258,
-     INT = 259,
-     PERCENT_TOKEN = 260,
-     PERCENT_NTERM = 261,
-     PERCENT_TYPE = 262,
-     PERCENT_DESTRUCTOR = 263,
-     PERCENT_PRINTER = 264,
-     PERCENT_LEFT = 265,
-     PERCENT_RIGHT = 266,
-     PERCENT_NONASSOC = 267,
-     PERCENT_PREC = 268,
-     PERCENT_DPREC = 269,
-     PERCENT_MERGE = 270,
-     PERCENT_CODE = 271,
-     PERCENT_DEBUG = 272,
-     PERCENT_DEFAULT_PREC = 273,
-     PERCENT_DEFINE = 274,
-     PERCENT_DEFINES = 275,
-     PERCENT_ERROR_VERBOSE = 276,
-     PERCENT_EXPECT = 277,
-     PERCENT_EXPECT_RR = 278,
-     PERCENT_FILE_PREFIX = 279,
-     PERCENT_GLR_PARSER = 280,
-     PERCENT_INITIAL_ACTION = 281,
-     PERCENT_LANGUAGE = 282,
-     PERCENT_LEX_PARAM = 283,
-     PERCENT_LOCATIONS = 284,
-     PERCENT_NAME_PREFIX = 285,
-     PERCENT_NO_DEFAULT_PREC = 286,
-     PERCENT_NO_LINES = 287,
-     PERCENT_NONDETERMINISTIC_PARSER = 288,
-     PERCENT_OUTPUT = 289,
-     PERCENT_PARSE_PARAM = 290,
-     PERCENT_PURE_PARSER = 291,
-     PERCENT_REQUIRE = 292,
-     PERCENT_SKELETON = 293,
-     PERCENT_START = 294,
-     PERCENT_TOKEN_TABLE = 295,
-     PERCENT_VERBOSE = 296,
-     PERCENT_YACC = 297,
-     BRACED_CODE = 298,
-     BRACKETED_ID = 299,
-     CHAR = 300,
-     EPILOGUE = 301,
-     EQUAL = 302,
-     ID = 303,
-     ID_COLON = 304,
-     PERCENT_PERCENT = 305,
-     PIPE = 306,
-     PROLOGUE = 307,
-     SEMICOLON = 308,
-     TYPE = 309,
-     TYPE_TAG_ANY = 310,
-     TYPE_TAG_NONE = 311,
-     PERCENT_UNION = 312
-   };
+  enum gram_tokentype
+  {
+    GRAM_EOF = 0,
+    STRING = 258,
+    PERCENT_TOKEN = 259,
+    PERCENT_NTERM = 260,
+    PERCENT_TYPE = 261,
+    PERCENT_DESTRUCTOR = 262,
+    PERCENT_PRINTER = 263,
+    PERCENT_LEFT = 264,
+    PERCENT_RIGHT = 265,
+    PERCENT_NONASSOC = 266,
+    PERCENT_PRECEDENCE = 267,
+    PERCENT_PREC = 268,
+    PERCENT_DPREC = 269,
+    PERCENT_MERGE = 270,
+    PERCENT_CODE = 271,
+    PERCENT_DEFAULT_PREC = 272,
+    PERCENT_DEFINE = 273,
+    PERCENT_DEFINES = 274,
+    PERCENT_ERROR_VERBOSE = 275,
+    PERCENT_EXPECT = 276,
+    PERCENT_EXPECT_RR = 277,
+    PERCENT_FLAG = 278,
+    PERCENT_FILE_PREFIX = 279,
+    PERCENT_GLR_PARSER = 280,
+    PERCENT_INITIAL_ACTION = 281,
+    PERCENT_LANGUAGE = 282,
+    PERCENT_NAME_PREFIX = 283,
+    PERCENT_NO_DEFAULT_PREC = 284,
+    PERCENT_NO_LINES = 285,
+    PERCENT_NONDETERMINISTIC_PARSER = 286,
+    PERCENT_OUTPUT = 287,
+    PERCENT_REQUIRE = 288,
+    PERCENT_SKELETON = 289,
+    PERCENT_START = 290,
+    PERCENT_TOKEN_TABLE = 291,
+    PERCENT_VERBOSE = 292,
+    PERCENT_YACC = 293,
+    BRACED_CODE = 294,
+    BRACED_PREDICATE = 295,
+    BRACKETED_ID = 296,
+    CHAR = 297,
+    EPILOGUE = 298,
+    EQUAL = 299,
+    ID = 300,
+    ID_COLON = 301,
+    PERCENT_PERCENT = 302,
+    PIPE = 303,
+    PROLOGUE = 304,
+    SEMICOLON = 305,
+    TAG = 306,
+    TAG_ANY = 307,
+    TAG_NONE = 308,
+    INT = 309,
+    PERCENT_PARAM = 310,
+    PERCENT_UNION = 311,
+    PERCENT_EMPTY = 312
+  };
 #endif
-/* Tokens.  */
-#define GRAM_EOF 0
-#define STRING 258
-#define INT 259
-#define PERCENT_TOKEN 260
-#define PERCENT_NTERM 261
-#define PERCENT_TYPE 262
-#define PERCENT_DESTRUCTOR 263
-#define PERCENT_PRINTER 264
-#define PERCENT_LEFT 265
-#define PERCENT_RIGHT 266
-#define PERCENT_NONASSOC 267
-#define PERCENT_PREC 268
-#define PERCENT_DPREC 269
-#define PERCENT_MERGE 270
-#define PERCENT_CODE 271
-#define PERCENT_DEBUG 272
-#define PERCENT_DEFAULT_PREC 273
-#define PERCENT_DEFINE 274
-#define PERCENT_DEFINES 275
-#define PERCENT_ERROR_VERBOSE 276
-#define PERCENT_EXPECT 277
-#define PERCENT_EXPECT_RR 278
-#define PERCENT_FILE_PREFIX 279
-#define PERCENT_GLR_PARSER 280
-#define PERCENT_INITIAL_ACTION 281
-#define PERCENT_LANGUAGE 282
-#define PERCENT_LEX_PARAM 283
-#define PERCENT_LOCATIONS 284
-#define PERCENT_NAME_PREFIX 285
-#define PERCENT_NO_DEFAULT_PREC 286
-#define PERCENT_NO_LINES 287
-#define PERCENT_NONDETERMINISTIC_PARSER 288
-#define PERCENT_OUTPUT 289
-#define PERCENT_PARSE_PARAM 290
-#define PERCENT_PURE_PARSER 291
-#define PERCENT_REQUIRE 292
-#define PERCENT_SKELETON 293
-#define PERCENT_START 294
-#define PERCENT_TOKEN_TABLE 295
-#define PERCENT_VERBOSE 296
-#define PERCENT_YACC 297
-#define BRACED_CODE 298
-#define BRACKETED_ID 299
-#define CHAR 300
-#define EPILOGUE 301
-#define EQUAL 302
-#define ID 303
-#define ID_COLON 304
-#define PERCENT_PERCENT 305
-#define PIPE 306
-#define PROLOGUE 307
-#define SEMICOLON 308
-#define TYPE 309
-#define TYPE_TAG_ANY 310
-#define TYPE_TAG_NONE 311
-#define PERCENT_UNION 312
-
-
 
+/* Value type.  */
 #if ! defined GRAM_STYPE && ! defined GRAM_STYPE_IS_DECLARED
-typedef union GRAM_STYPE
+typedef union GRAM_STYPE GRAM_STYPE;
+union GRAM_STYPE
 {
-/* Line 2042 of yacc.c  */
-#line 115 "parse-gram.y"
+#line 170 "src/parse-gram.y" /* yacc.c:1931  */
+unsigned char character;
+#line 177 "src/parse-gram.y" /* yacc.c:1931  */
 
-  symbol *symbol;
-  symbol_list *list;
-  int integer;
-  char const *chars;
   char *code;
-  assoc assoc;
-  uniqstr uniqstr;
-  unsigned char character;
-  named_ref *named_ref;
+  char const *chars;
+
+#line 188 "src/parse-gram.y" /* yacc.c:1931  */
+uniqstr uniqstr;
+#line 196 "src/parse-gram.y" /* yacc.c:1931  */
+int integer;
+#line 200 "src/parse-gram.y" /* yacc.c:1931  */
+symbol *symbol;
+#line 205 "src/parse-gram.y" /* yacc.c:1931  */
+assoc assoc;
+#line 208 "src/parse-gram.y" /* yacc.c:1931  */
+symbol_list *list;
+#line 211 "src/parse-gram.y" /* yacc.c:1931  */
+named_ref *named_ref;
+#line 238 "src/parse-gram.y" /* yacc.c:1931  */
+param_type param;
+#line 413 "src/parse-gram.y" /* yacc.c:1931  */
+code_props_type code_type;
+#line 651 "src/parse-gram.y" /* yacc.c:1931  */
 
+  struct
+  {
+    char const *chars;
+    muscle_kind kind;
+  } value;
 
-/* Line 2042 of yacc.c  */
-#line 194 "parse-gram.h"
-} GRAM_STYPE;
+
+#line 168 "src/parse-gram.h" /* yacc.c:1931  */
+};
 # define GRAM_STYPE_IS_TRIVIAL 1
-# define gram_stype GRAM_STYPE /* obsolescent; will be withdrawn */
 # define GRAM_STYPE_IS_DECLARED 1
 #endif
 
+/* Location type.  */
 #if ! defined GRAM_LTYPE && ! defined GRAM_LTYPE_IS_DECLARED
-typedef struct GRAM_LTYPE
+typedef struct GRAM_LTYPE GRAM_LTYPE;
+struct GRAM_LTYPE
 {
   int first_line;
   int first_column;
   int last_line;
   int last_column;
-} GRAM_LTYPE;
-# define gram_ltype GRAM_LTYPE /* obsolescent; will be withdrawn */
+};
 # define GRAM_LTYPE_IS_DECLARED 1
 # define GRAM_LTYPE_IS_TRIVIAL 1
 #endif
 
 
-#ifdef YYPARSE_PARAM
-#if defined __STDC__ || defined __cplusplus
-int gram_parse (void *YYPARSE_PARAM);
-#else
-int gram_parse ();
-#endif
-#else /* ! YYPARSE_PARAM */
-#if defined __STDC__ || defined __cplusplus
+
 int gram_parse (void);
-#else
-int gram_parse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
 
-#endif /* !YY_GRAM__________SRC_PARSE_GRAM_H_INCLUDED  */
+#endif /* !YY_GRAM_SRC_PARSE_GRAM_H_INCLUDED  */
index bbd7fba2aefabfcf3254ddf13f060e640264323f..ebcd31b3a87f001b047a45e6410e5625a2f0f042 100644 (file)
 #include "files.h"
 #include "getargs.h"
 #include "gram.h"
-#include "muscle-tab.h"
 #include "named-ref.h"
 #include "quotearg.h"
 #include "reader.h"
 #include "symlist.h"
+#include "symtab.h"
 #include "scan-gram.h"
 #include "scan-code.h"
 #include "xmemdup0.h"
 static YYLTYPE lloc_default (YYLTYPE const *, int);
 
 #define YY_LOCATION_PRINT(File, Loc) \
-         location_print (File, Loc)
+          location_print (Loc, File)
 
 static void version_check (location const *loc, char const *version);
 
-/* Request detailed syntax error messages, and pass them to GRAM_ERROR.
-   FIXME: depends on the undocumented availability of YYLLOC.  */
-#undef  yyerror
-#define yyerror(Msg) \
-       gram_error (&yylloc, Msg)
 static void gram_error (location const *, char const *);
 
+/* A string that describes a char (e.g., 'a' -> "'a'").  */
 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
 %define api.prefix "gram_"
-%define api.pure
+%define api.pure full
+%define locations
+%define parse.error verbose
 %define parse.lac full
+%define parse.trace
 %defines
-%error-verbose
 %expect 0
-%locations
 %verbose
 
 %initial-action
@@ -111,23 +100,9 @@ current_lhs(symbol *sym, location loc, named_ref *ref)
   boundary_set (&@$.end, current_file, 1, 1);
 }
 
-%union
-{
-  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 GRAM_EOF 0 "end of file"
 %token STRING     "string"
-%token INT        "integer"
 
 %token PERCENT_TOKEN       "%token"
 %token PERCENT_NTERM       "%nterm"
@@ -139,40 +114,36 @@ current_lhs(symbol *sym, location loc, named_ref *ref)
 %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"
@@ -181,6 +152,7 @@ current_lhs(symbol *sym, location loc, named_ref *ref)
 ;
 
 %token BRACED_CODE     "{...}"
+%token BRACED_PREDICATE "%?{...}"
 %token BRACKETED_ID    "[identifier]"
 %token CHAR            "char"
 %token EPILOGUE        "epilogue"
@@ -191,39 +163,98 @@ current_lhs(symbol *sym, location loc, named_ref *ref)
 %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        "<>"
 
+%union {unsigned char character;}
 %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 <integer> INT
-%printer { fprintf (stderr, "%d", $$); } <integer>
-
+%union
+{
+  char *code;
+  char const *chars;
+};
+%type <chars> STRING "%{...%}" EPILOGUE braceless
+%type <code> "{...}" "%?{...}"
+%printer { fputs (quotearg_style (c_quoting_style, $$), yyo); }
+         STRING
+%printer { fprintf (yyo, "{\n%s\n}", $$); }
+         braceless "{...}" "%{...%}" EPILOGUE
+
+%union {uniqstr uniqstr;}
+%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
+
+%union {int integer;};
+%token <integer> INT "integer"
+%printer { fprintf (yyo, "%d", $$); } <integer>
+
+%union {symbol *symbol;}
 %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
 
+%union {assoc assoc;};
 %type <assoc> precedence_declarator
+
+%union {symbol_list *list;}
 %type <list>  symbols.1 symbols.prec generic_symlist generic_symlist_item
+
+%union {named_ref *named_ref;}
 %type <named_ref> named_ref.opt
 
+/*---------.
+| %param.  |
+`---------*/
+%code requires
+{
+  typedef enum
+  {
+    param_none   = 0,
+    param_lex    = 1 << 0,
+    param_parse  = 1 << 1,
+    param_both   = param_lex | param_parse
+  } param_type;
+};
+%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, yyo); break
+      CASE (lex,   lex-param);
+      CASE (parse, parse-param);
+      CASE (both,  param);
+#undef CASE
+      case param_none: aver (false); break;
+    }
+} <param>;
+
+
+                     /*==========\
+                     | Grammar.  |
+                     \==========*/
 %%
 
 input:
@@ -231,12 +262,12 @@ input:
 ;
 
 
-       /*------------------------------------.
-       | Declarations: before the first %%.  |
-       `------------------------------------*/
+        /*------------------------------------.
+        | Declarations: before the first %%.  |
+        `------------------------------------*/
 
 prologue_declarations:
-  /* Nothing */
+  %empty
 | prologue_declarations prologue_declaration
 ;
 
@@ -252,10 +283,13 @@ prologue_declaration:
                         plain_code.code, @1);
       code_scanner_last_string_free ();
     }
-| "%debug"                         { debug = true; }
-| "%define" variable content.opt
+| "%<flag>"
     {
-      muscle_percent_define_insert ($2, @2, $3,
+      muscle_percent_define_ensure ($1, @1, true);
+    }
+| "%define" variable value
+    {
+      muscle_percent_define_insert ($2, @2, $3.kind, $3.chars,
                                     MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE);
     }
 | "%defines"                       { defines_flag = true; }
@@ -264,11 +298,15 @@ prologue_declaration:
       defines_flag = true;
       spec_defines_file = xstrdup ($2);
     }
-| "%error-verbose"                 { error_verbose = true; }
+| "%error-verbose"
+    {
+      muscle_percent_define_insert ("parse.error", @1, muscle_keyword,
+                                    "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"
     {
       nondeterministic_parser = true;
@@ -283,36 +321,17 @@ prologue_declaration:
       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;
@@ -339,6 +358,16 @@ prologue_declaration:
 | /*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
@@ -346,7 +375,7 @@ grammar_declaration:
     {
       grammar_start_symbol_set ($2, @2);
     }
-| "%destructor" "{...}" generic_symlist
+| code_props_type "{...}" generic_symlist
     {
       code_props code;
       code_props_symbol_action_init (&code, $2, @2);
@@ -354,19 +383,7 @@ grammar_declaration:
       {
         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 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);
       }
     }
@@ -392,23 +409,30 @@ grammar_declaration:
     }
 ;
 
+%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";
 
 union_name:
-  /* Nothing. */ {}
-| ID             { muscle_code_grow ("union_name", $1, @1); }
+  %empty {}
+| ID     { muscle_code_grow ("union_name", $1, @1); }
 ;
 
 grammar_declaration:
   "%union" union_name braceless
     {
       union_seen = true;
-      muscle_code_grow ("stype", $3, @3);
+      muscle_code_grow ("union_members", $3, @3);
       code_scanner_last_string_free ();
     }
 ;
@@ -427,40 +451,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:
-  /* Nothing. */ { current_type = NULL; }
-| TYPE           { current_type = $1; tag_seen = true; }
+tag.opt:
+  %empty { current_type = NULL; }
+| TAG    { current_type = $1; tag_seen = true; }
 ;
 
 /* Just like symbols.1 but accept INT for the sake of POSIX.  */
@@ -468,46 +493,59 @@ symbols.prec:
   symbol.prec
     { $$ = symbol_list_sym_new ($1, @1); }
 | symbols.prec symbol.prec
-    { $$ = symbol_list_prepend ($1, symbol_list_sym_new ($2, @2)); }
+    { $$ = symbol_list_append ($1, symbol_list_sym_new ($2, @2)); }
 ;
 
 symbol.prec:
-    symbol { $$ = $1; }
-  | symbol INT { $$ = $1; symbol_user_token_number_set ($1, $2, @2); }
-  ;
+  symbol
+    {
+      $$ = $1;
+      symbol_class_set ($1, token_sym, @1, false);
+    }
+| symbol INT
+    {
+      $$ = $1;
+      symbol_user_token_number_set ($1, $2, @2);
+      symbol_class_set ($1, token_sym, @1, false);
+    }
+;
 
 /* One or more symbols to be %typed. */
 symbols.1:
   symbol
     { $$ = symbol_list_sym_new ($1, @1); }
 | symbols.1 symbol
-    { $$ = symbol_list_prepend ($1, symbol_list_sym_new ($2, @2)); }
+    { $$ = symbol_list_append ($1, symbol_list_sym_new ($2, @2)); }
 ;
 
 generic_symlist:
   generic_symlist_item { $$ = $1; }
-| generic_symlist generic_symlist_item { $$ = symbol_list_prepend ($1, $2); }
+| generic_symlist generic_symlist_item { $$ = symbol_list_append ($1, $2); }
 ;
 
 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
-     {
-       current_type = $1;
-       tag_seen = true;
-     }
+  TAG
+    {
+      current_type = $1;
+      tag_seen = true;
+    }
 | id
-     {
-       symbol_class_set ($1, current_class, @1, true);
-       symbol_type_set ($1, current_type, @1);
-     }
+    {
+      symbol_class_set ($1, current_class, @1, true);
+      symbol_type_set ($1, current_type, @1);
+    }
 | id INT
     {
       symbol_class_set ($1, current_class, @1, true);
@@ -536,9 +574,9 @@ symbol_defs.1:
 ;
 
 
-       /*------------------------------------------.
-       | The grammar section: between the two %%.  |
-       `------------------------------------------*/
+        /*------------------------------------------.
+        | The grammar section: between the two %%.  |
+        `------------------------------------------*/
 
 grammar:
   rules_or_grammar_declaration
@@ -570,57 +608,81 @@ rhses.1:
 | rhses.1 ";"
 ;
 
+%token PERCENT_EMPTY "%empty";
 rhs:
-  /* Nothing.  */
+  %empty
     { 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 "%empty"
+    { grammar_current_rule_empty_set (@2); }
 | 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); }
 ;
 
 named_ref.opt:
-  /* Nothing. */ { $$ = 0; }
-|
-  BRACKETED_ID   { $$ = named_ref_new($1, @1); }
+  %empty         { $$ = 0; }
+| BRACKETED_ID   { $$ = named_ref_new($1, @1); }
 ;
 
-
-/*----------------------------*
- | variable and content.opt.  |
- *---------------------------*/
+/*---------------------.
+| variable and value.  |
+`---------------------*/
 
 /* The STRING form of variable is deprecated and is not M4-friendly.
-   For example, M4 fails for `%define "[" "value"'.  */
+   For example, M4 fails for '%define "[" "value"'.  */
 variable:
   ID
 | STRING { $$ = uniqstr_new ($1); }
 ;
 
 /* Some content or empty by default. */
-content.opt:
-  /* Nothing. */   { $$ = ""; }
-| ID { $$ = $1; }
-| STRING
+%code requires {#include "muscle-tab.h"};
+%union
+{
+  struct
+  {
+    char const *chars;
+    muscle_kind kind;
+  } value;
+};
+%type <value> value;
+%printer
+{
+  switch ($$.kind)
+    {
+    case muscle_code:    fprintf (yyo,  "{%s}",  $$.chars); break;
+    case muscle_keyword: fprintf (yyo,   "%s",   $$.chars); break;
+    case muscle_string:  fprintf (yyo, "\"%s\"", $$.chars); break;
+    }
+} <value>;
+
+value:
+  %empty    { $$.kind = muscle_keyword; $$.chars = ""; }
+| ID        { $$.kind = muscle_keyword; $$.chars = $1; }
+| STRING    { $$.kind = muscle_string;  $$.chars = $1; }
+| braceless { $$.kind = muscle_code;    $$.chars = $1; }
 ;
 
 
-/*-------------*
- | braceless.  |
- *-------------*/
+/*------------.
+| braceless.  |
+`------------*/
 
 braceless:
   "{...}"
     {
       code_props plain_code;
-      $1[strlen ($1) - 1] = '\n';
+      $1[strlen ($1) - 1] = '\0';
       code_props_plain_init (&plain_code, $1+1, @1);
       code_props_translate_code (&plain_code);
       gram_scanner_last_string_free ();
@@ -629,9 +691,9 @@ braceless:
 ;
 
 
-/*---------------*
- | Identifiers.  |
- *---------------*/
+/*--------------.
+| Identifiers.  |
+`--------------*/
 
 /* Identifiers are returned as uniqstr values by the scanner.
    Depending on their use, we may need to make them genuine symbols.  */
@@ -667,7 +729,7 @@ string_as_id:
 ;
 
 epilogue.opt:
-  /* Nothing.  */
+  %empty
 | "%%" EPILOGUE
     {
       code_props plain_code;
@@ -681,7 +743,6 @@ epilogue.opt:
 
 %%
 
-
 /* Return the location of the left-hand side of a rule whose
    right-hand side is RHS[1] ... RHS[N].  Ignore empty nonterminals in
    the right-hand side, and return an empty location equal to the end
@@ -704,51 +765,53 @@ 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.  */
-  --p;
-  while (c_isspace ((unsigned char) *p))
+  {
+    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.  */
     --p;
-  p[1] = '\0';
-  ++decl;
-  while (c_isspace ((unsigned char) *decl))
+  while (c_isspace ((unsigned char) *p))
+      --p;
+    p[1] = '\0';
     ++decl;
+  while (c_isspace ((unsigned char) *decl))
+      ++decl;
+  }
 
   if (! name_start)
-    complain_at (loc, _("missing identifier in parameter declaration"));
+    complain (&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);
     }
 
@@ -761,8 +824,8 @@ version_check (location const *loc, char const *version)
 {
   if (strverscmp (version, PACKAGE_VERSION) > 0)
     {
-      complain_at (*loc, "require bison %s, but have %s",
-                   version, PACKAGE_VERSION);
+      complain (loc, complaint, "require bison %s, but have %s",
+                version, PACKAGE_VERSION);
       exit (EX_MISMATCH);
     }
 }
@@ -770,7 +833,7 @@ version_check (location const *loc, char const *version)
 static void
 gram_error (location const *loc, char const *msg)
 {
-  complain_at (*loc, "%s", msg);
+  complain (loc, complaint, "%s", msg);
 }
 
 char const *
index bdec56fca898e47f2495808460e2b409513b4355..a3ef15117d773647f9305305aa6a10aef27042a1 100644 (file)
@@ -81,36 +81,36 @@ print_core (FILE *out, int level, state *s)
       sp1 = sp = ritem + sitems[i];
 
       while (*sp >= 0)
-       sp++;
+        sp++;
 
       r = item_number_as_rule_number (*sp);
       sp = rules[r].rhs;
 
       /* Display the lookahead tokens?  */
       if (item_number_is_rule_number (*sp1))
-       {
-         reductions *reds = s->reductions;
-         int red = state_reduction_find (s, &rules[r]);
-         /* Print item with lookaheads if there are. */
-         if (reds->lookahead_tokens && red != -1)
-           {
-             xml_printf (out, level + 1,
-                         "<item rule-number=\"%d\" point=\"%d\">",
-                         rules[r].number, sp1 - sp);
-             state_rule_lookahead_tokens_print_xml (s, &rules[r],
-                                                    out, level + 2);
-             xml_puts (out, level + 1, "</item>");
-             printed = true;
-           }
-       }
+        {
+          reductions *reds = s->reductions;
+          int red = state_reduction_find (s, &rules[r]);
+          /* Print item with lookaheads if there are. */
+          if (reds->lookahead_tokens && red != -1)
+            {
+              xml_printf (out, level + 1,
+                          "<item rule-number=\"%d\" point=\"%d\">",
+                          rules[r].number, sp1 - sp);
+              state_rule_lookahead_tokens_print_xml (s, &rules[r],
+                                                     out, level + 2);
+              xml_puts (out, level + 1, "</item>");
+              printed = true;
+            }
+        }
 
       if (!printed)
-       {
-         xml_printf (out, level + 1,
-                     "<item rule-number=\"%d\" point=\"%d\"/>",
-                     rules[r].number,
-                     sp1 - sp);
-       }
+        {
+          xml_printf (out, level + 1,
+                      "<item rule-number=\"%d\" point=\"%d\"/>",
+                      rules[r].number,
+                      sp1 - sp);
+        }
     }
   xml_puts (out, level, "</itemset>");
 }
@@ -131,7 +131,7 @@ print_transitions (state *s, FILE *out, int level)
   for (i = 0; i < trans->num; i++)
     if (!TRANSITION_IS_DISABLED (trans, i))
       {
-       n++;
+        n++;
       }
 
   /* Nothing to report. */
@@ -145,28 +145,28 @@ print_transitions (state *s, FILE *out, int level)
 
   for (i = 0; i < trans->num; i++)
     if (!TRANSITION_IS_DISABLED (trans, i)
-       && TRANSITION_IS_SHIFT (trans, i))
+        && TRANSITION_IS_SHIFT (trans, i))
       {
-       symbol *sym = symbols[TRANSITION_SYMBOL (trans, i)];
-       char const *tag = sym->tag;
-       state *s1 = trans->states[i];
+        symbol *sym = symbols[TRANSITION_SYMBOL (trans, i)];
+        char const *tag = sym->tag;
+        state *s1 = trans->states[i];
 
-       xml_printf (out, level + 1,
-                   "<transition type=\"shift\" symbol=\"%s\" state=\"%d\"/>",
-                   xml_escape (tag), s1->number);
+        xml_printf (out, level + 1,
+                    "<transition type=\"shift\" symbol=\"%s\" state=\"%d\"/>",
+                    xml_escape (tag), s1->number);
       }
 
   for (i = 0; i < trans->num; i++)
     if (!TRANSITION_IS_DISABLED (trans, i)
-       && !TRANSITION_IS_SHIFT (trans, i))
+        && !TRANSITION_IS_SHIFT (trans, i))
       {
-       symbol *sym = symbols[TRANSITION_SYMBOL (trans, i)];
-       char const *tag = sym->tag;
-       state *s1 = trans->states[i];
+        symbol *sym = symbols[TRANSITION_SYMBOL (trans, i)];
+        char const *tag = sym->tag;
+        state *s1 = trans->states[i];
 
-       xml_printf (out, level + 1,
-                   "<transition type=\"goto\" symbol=\"%s\" state=\"%d\"/>",
-                   xml_escape (tag), s1->number);
+        xml_printf (out, level + 1,
+                    "<transition type=\"goto\" symbol=\"%s\" state=\"%d\"/>",
+                    xml_escape (tag), s1->number);
       }
 
   xml_puts (out, level, "</transitions>");
@@ -199,36 +199,36 @@ print_errs (FILE *out, int level, state *s)
   for (i = 0; i < errp->num; ++i)
     if (errp->symbols[i])
       {
-       char const *tag = errp->symbols[i]->tag;
-       xml_printf (out, level + 1,
-                   "<error symbol=\"%s\">nonassociative</error>",
-                   xml_escape (tag));
+        char const *tag = errp->symbols[i]->tag;
+        xml_printf (out, level + 1,
+                    "<error symbol=\"%s\">nonassociative</error>",
+                    xml_escape (tag));
       }
   xml_puts (out, level, "</errors>");
 }
 
 
 /*-------------------------------------------------------------------------.
-| Report a reduction of RULE on LOOKAHEAD_TOKEN (which can be `default').  |
+| Report a reduction of RULE on LOOKAHEAD_TOKEN (which can be 'default').  |
 | If not ENABLED, the rule is masked by a shift or a reduce (S/R and       |
 | R/R conflicts).                                                          |
 `-------------------------------------------------------------------------*/
 
 static void
 print_reduction (FILE *out, int level, char const *lookahead_token,
-                rule *r, bool enabled)
+                 rule *r, bool enabled)
 {
   if (r->number)
     xml_printf (out, level,
-               "<reduction symbol=\"%s\" rule=\"%d\" enabled=\"%s\"/>",
-               xml_escape (lookahead_token),
-               r->number,
-               enabled ? "true" : "false");
+                "<reduction symbol=\"%s\" rule=\"%d\" enabled=\"%s\"/>",
+                xml_escape (lookahead_token),
+                r->number,
+                enabled ? "true" : "false");
   else
     xml_printf (out, level,
-               "<reduction symbol=\"%s\" rule=\"accept\" enabled=\"%s\"/>",
-               xml_escape (lookahead_token),
-               enabled ? "true" : "false");
+                "<reduction symbol=\"%s\" rule=\"accept\" enabled=\"%s\"/>",
+                xml_escape (lookahead_token),
+                enabled ? "true" : "false");
 }
 
 
@@ -267,22 +267,22 @@ print_reductions (FILE *out, int level, state *s)
   if (reds->lookahead_tokens)
     for (i = 0; i < ntokens; i++)
       {
-       bool count = bitset_test (no_reduce_set, i);
-
-       for (j = 0; j < reds->num; ++j)
-         if (bitset_test (reds->lookahead_tokens[j], i))
-           {
-             if (! count)
-               {
-                 if (reds->rules[j] != default_reduction)
-                   report = true;
-                 count = true;
-               }
-             else
-               {
-                 report = true;
-               }
-           }
+        bool count = bitset_test (no_reduce_set, i);
+
+        for (j = 0; j < reds->num; ++j)
+          if (bitset_test (reds->lookahead_tokens[j], i))
+            {
+              if (! count)
+                {
+                  if (reds->rules[j] != default_reduction)
+                    report = true;
+                  count = true;
+                }
+              else
+                {
+                  report = true;
+                }
+            }
       }
 
   /* Nothing to report. */
@@ -297,36 +297,36 @@ print_reductions (FILE *out, int level, state *s)
   if (reds->lookahead_tokens)
     for (i = 0; i < ntokens; i++)
       {
-       bool defaulted = false;
-       bool count = bitset_test (no_reduce_set, i);
-
-       for (j = 0; j < reds->num; ++j)
-         if (bitset_test (reds->lookahead_tokens[j], i))
-           {
-             if (! count)
-               {
-                 if (reds->rules[j] != default_reduction)
-                   print_reduction (out, level + 1, symbols[i]->tag,
-                                    reds->rules[j], true);
-                 else
-                   defaulted = true;
-                 count = true;
-               }
-             else
-               {
-                 if (defaulted)
-                   print_reduction (out, level + 1, symbols[i]->tag,
-                                    default_reduction, true);
-                 defaulted = false;
-                 print_reduction (out, level + 1, symbols[i]->tag,
-                                  reds->rules[j], false);
-               }
-           }
+        bool defaulted = false;
+        bool count = bitset_test (no_reduce_set, i);
+
+        for (j = 0; j < reds->num; ++j)
+          if (bitset_test (reds->lookahead_tokens[j], i))
+            {
+              if (! count)
+                {
+                  if (reds->rules[j] != default_reduction)
+                    print_reduction (out, level + 1, symbols[i]->tag,
+                                     reds->rules[j], true);
+                  else
+                    defaulted = true;
+                  count = true;
+                }
+              else
+                {
+                  if (defaulted)
+                    print_reduction (out, level + 1, symbols[i]->tag,
+                                     default_reduction, true);
+                  defaulted = false;
+                  print_reduction (out, level + 1, symbols[i]->tag,
+                                   reds->rules[j], false);
+                }
+            }
       }
 
   if (default_reduction)
     print_reduction (out, level + 1,
-                    "$default", default_reduction, true);
+                     "$default", default_reduction, true);
 
   xml_puts (out, level, "</reductions>");
 }
@@ -389,7 +389,7 @@ print_grammar (FILE *out, int level)
   for (i = 0; i < max_user_token_number + 1; i++)
     if (token_translations[i] != undeftoken->number)
       {
-       char const *tag = symbols[token_translations[i]]->tag;
+        char const *tag = symbols[token_translations[i]]->tag;
         int precedence = symbols[token_translations[i]]->prec;
         assoc associativity = symbols[token_translations[i]]->assoc;
         xml_indent (out, level + 2);
@@ -413,9 +413,9 @@ print_grammar (FILE *out, int level)
     {
       char const *tag = symbols[i]->tag;
       xml_printf (out, level + 2,
-                 "<nonterminal symbol-number=\"%d\" name=\"%s\""
+                  "<nonterminal symbol-number=\"%d\" name=\"%s\""
                   " usefulness=\"%s\"/>",
-                 i, xml_escape (tag),
+                  i, xml_escape (tag),
                   reduce_nonterminal_useless_in_grammar (i)
                     ? "useless-in-grammar" : "useful");
     }
@@ -511,7 +511,7 @@ print_xml (void)
 
   fputc ('\n', out);
   xml_printf (out, level + 1, "<filename>%s</filename>",
-             xml_escape (grammar_file));
+              xml_escape (grammar_file));
 
   /* print grammar */
   print_grammar (out, level + 1);
index 8a51517c9632893720995740e92d5a698467bb32..824bb4ae825798420e26efb5d16ffc361c7fe3ab 100644 (file)
@@ -96,7 +96,7 @@ print_core (FILE *out, state *s)
       sp1 = sp = ritem + sitems[i];
 
       while (*sp >= 0)
-       sp++;
+        sp++;
 
       r = item_number_as_rule_number (*sp);
 
@@ -104,15 +104,15 @@ print_core (FILE *out, state *s)
       previous_lhs = rules[r].lhs;
 
       for (sp = rules[r].rhs; sp < sp1; sp++)
-       fprintf (out, " %s", symbols[*sp]->tag);
+        fprintf (out, " %s", symbols[*sp]->tag);
       fputs (" .", out);
       for (/* Nothing */; *sp >= 0; ++sp)
-       fprintf (out, " %s", symbols[*sp]->tag);
+        fprintf (out, " %s", symbols[*sp]->tag);
 
       /* Display the lookahead tokens?  */
       if (report_flag & report_lookahead_tokens
           && item_number_is_rule_number (*sp1))
-       state_rule_lookahead_tokens_print (s, &rules[r], out);
+        state_rule_lookahead_tokens_print (s, &rules[r], out);
 
       fputc ('\n', out);
     }
@@ -134,10 +134,10 @@ print_transitions (state *s, FILE *out, bool display_transitions_p)
   /* Compute the width of the lookahead token column.  */
   for (i = 0; i < trans->num; i++)
     if (!TRANSITION_IS_DISABLED (trans, i)
-       && TRANSITION_IS_SHIFT (trans, i) == display_transitions_p)
+        && TRANSITION_IS_SHIFT (trans, i) == display_transitions_p)
       {
-       symbol *sym = symbols[TRANSITION_SYMBOL (trans, i)];
-       max_length (&width, sym->tag);
+        symbol *sym = symbols[TRANSITION_SYMBOL (trans, i)];
+        max_length (&width, sym->tag);
       }
 
   /* Nothing to report. */
@@ -150,20 +150,20 @@ print_transitions (state *s, FILE *out, bool display_transitions_p)
   /* Report lookahead tokens and shifts.  */
   for (i = 0; i < trans->num; i++)
     if (!TRANSITION_IS_DISABLED (trans, i)
-       && TRANSITION_IS_SHIFT (trans, i) == display_transitions_p)
+        && TRANSITION_IS_SHIFT (trans, i) == display_transitions_p)
       {
-       symbol *sym = symbols[TRANSITION_SYMBOL (trans, i)];
-       const char *tag = sym->tag;
-       state *s1 = trans->states[i];
-       int j;
-
-       fprintf (out, "    %s", tag);
-       for (j = width - strlen (tag); j > 0; --j)
-         fputc (' ', out);
-       if (display_transitions_p)
-         fprintf (out, _("shift, and go to state %d\n"), s1->number);
-       else
-         fprintf (out, _("go to state %d\n"), s1->number);
+        symbol *sym = symbols[TRANSITION_SYMBOL (trans, i)];
+        const char *tag = sym->tag;
+        state *s1 = trans->states[i];
+        int j;
+
+        fprintf (out, "    %s", tag);
+        for (j = width - strlen (tag); j > 0; --j)
+          fputc (' ', out);
+        if (display_transitions_p)
+          fprintf (out, _("shift, and go to state %d\n"), s1->number);
+        else
+          fprintf (out, _("go to state %d\n"), s1->number);
       }
 }
 
@@ -195,26 +195,26 @@ print_errs (FILE *out, state *s)
   for (i = 0; i < errp->num; ++i)
     if (errp->symbols[i])
       {
-       const char *tag = errp->symbols[i]->tag;
-       int j;
-       fprintf (out, "    %s", tag);
-       for (j = width - strlen (tag); j > 0; --j)
-         fputc (' ', out);
-       fputs (_("error (nonassociative)\n"), out);
+        const char *tag = errp->symbols[i]->tag;
+        int j;
+        fprintf (out, "    %s", tag);
+        for (j = width - strlen (tag); j > 0; --j)
+          fputc (' ', out);
+        fputs (_("error (nonassociative)\n"), out);
       }
 }
 
 
 /*-------------------------------------------------------------------------.
-| Report a reduction of RULE on LOOKAHEAD_TOKEN (which can be `default').  |
+| Report a reduction of RULE on LOOKAHEAD_TOKEN (which can be 'default').  |
 | If not ENABLED, the rule is masked by a shift or a reduce (S/R and       |
 | R/R conflicts).                                                          |
 `-------------------------------------------------------------------------*/
 
 static void
 print_reduction (FILE *out, size_t width,
-                const char *lookahead_token,
-                rule *r, bool enabled)
+                 const char *lookahead_token,
+                 rule *r, bool enabled)
 {
   int j;
   fprintf (out, "    %s", lookahead_token);
@@ -266,22 +266,22 @@ print_reductions (FILE *out, state *s)
   if (reds->lookahead_tokens)
     for (i = 0; i < ntokens; i++)
       {
-       bool count = bitset_test (no_reduce_set, i);
-
-       for (j = 0; j < reds->num; ++j)
-         if (bitset_test (reds->lookahead_tokens[j], i))
-           {
-             if (! count)
-               {
-                 if (reds->rules[j] != default_reduction)
-                   max_length (&width, symbols[i]->tag);
-                 count = true;
-               }
-             else
-               {
-                 max_length (&width, symbols[i]->tag);
-               }
-           }
+        bool count = bitset_test (no_reduce_set, i);
+
+        for (j = 0; j < reds->num; ++j)
+          if (bitset_test (reds->lookahead_tokens[j], i))
+            {
+              if (! count)
+                {
+                  if (reds->rules[j] != default_reduction)
+                    max_length (&width, symbols[i]->tag);
+                  count = true;
+                }
+              else
+                {
+                  max_length (&width, symbols[i]->tag);
+                }
+            }
       }
 
   /* Nothing to report. */
@@ -295,49 +295,49 @@ print_reductions (FILE *out, state *s)
   if (reds->lookahead_tokens)
     for (i = 0; i < ntokens; i++)
       {
-       bool defaulted = false;
-       bool count = bitset_test (no_reduce_set, i);
+        bool defaulted = false;
+        bool count = bitset_test (no_reduce_set, i);
         if (count)
           default_reduction_only = false;
 
-       for (j = 0; j < reds->num; ++j)
-         if (bitset_test (reds->lookahead_tokens[j], i))
-           {
-             if (! count)
-               {
-                 if (reds->rules[j] != default_reduction)
+        for (j = 0; j < reds->num; ++j)
+          if (bitset_test (reds->lookahead_tokens[j], i))
+            {
+              if (! count)
+                {
+                  if (reds->rules[j] != default_reduction)
                     {
                       default_reduction_only = false;
                       print_reduction (out, width,
                                        symbols[i]->tag,
                                        reds->rules[j], true);
                     }
-                 else
-                   defaulted = true;
-                 count = true;
-               }
-             else
-               {
+                  else
+                    defaulted = true;
+                  count = true;
+                }
+              else
+                {
                   default_reduction_only = false;
-                 if (defaulted)
-                   print_reduction (out, width,
-                                    symbols[i]->tag,
-                                    default_reduction, true);
-                 defaulted = false;
-                 print_reduction (out, width,
-                                  symbols[i]->tag,
-                                  reds->rules[j], false);
-               }
-           }
+                  if (defaulted)
+                    print_reduction (out, width,
+                                     symbols[i]->tag,
+                                     default_reduction, true);
+                  defaulted = false;
+                  print_reduction (out, width,
+                                   symbols[i]->tag,
+                                   reds->rules[j], false);
+                }
+            }
       }
 
   if (default_reduction)
     {
       char *default_reductions =
-        muscle_percent_define_get ("lr.default-reductions");
+        muscle_percent_define_get ("lr.default-reduction");
       print_reduction (out, width, _("$default"), default_reduction, true);
-      aver (0 == strcmp (default_reductions, "most")
-            || (0 == strcmp (default_reductions, "consistent")
+      aver (STREQ (default_reductions, "most")
+            || (STREQ (default_reductions, "consistent")
                 && default_reduction_only)
             || (reds->num == 1 && reds->rules[0]->number == 0));
       free (default_reductions);
@@ -385,15 +385,15 @@ print_state (FILE *out, state *s)
 | Print information on the whole grammar.  |
 `-----------------------------------------*/
 
-#define END_TEST(End)                          \
-do {                                           \
-  if (column + strlen(buffer) > (End))         \
-                                             \
-      fprintf (out, "%s\n   ", buffer);                \
-      column = 3;                              \
-      buffer[0] = 0;                           \
-                                             \
-} while (0)
+#define END_TEST(End)                           \
+  do {                                          \
+    if (column + strlen (buffer) > (End))       \
+      {                                         \
+        fprintf (out, "%s\n   ", buffer);       \
+        column = 3;                             \
+        buffer[0] = 0;                          \
+      }                                         \
+  } while (0)
 
 
 static void
@@ -410,25 +410,25 @@ print_grammar (FILE *out)
   for (i = 0; i < max_user_token_number + 1; i++)
     if (token_translations[i] != undeftoken->number)
       {
-       const char *tag = symbols[token_translations[i]]->tag;
-       rule_number r;
-       item_number *rhsp;
-
-       buffer[0] = 0;
-       column = strlen (tag);
-       fputs (tag, out);
-       END_TEST (65);
-       sprintf (buffer, " (%d)", i);
-
-       for (r = 0; r < nrules; r++)
-         for (rhsp = rules[r].rhs; *rhsp >= 0; rhsp++)
-           if (item_number_as_symbol_number (*rhsp) == token_translations[i])
-             {
-               END_TEST (65);
-               sprintf (buffer + strlen (buffer), " %d", r);
-               break;
-             }
-       fprintf (out, "%s\n", buffer);
+        const char *tag = symbols[token_translations[i]]->tag;
+        rule_number r;
+        item_number *rhsp;
+
+        buffer[0] = 0;
+        column = strlen (tag);
+        fputs (tag, out);
+        END_TEST (65);
+        sprintf (buffer, " (%d)", i);
+
+        for (r = 0; r < nrules; r++)
+          for (rhsp = rules[r].rhs; *rhsp >= 0; rhsp++)
+            if (item_number_as_symbol_number (*rhsp) == token_translations[i])
+              {
+                END_TEST (65);
+                sprintf (buffer + strlen (buffer), " %d", r);
+                break;
+              }
+        fprintf (out, "%s\n", buffer);
       }
   fputs ("\n\n", out);
 
@@ -441,17 +441,17 @@ print_grammar (FILE *out)
       const char *tag = symbols[i]->tag;
 
       for (r = 0; r < nrules; r++)
-       {
-         item_number *rhsp;
-         if (rules[r].lhs->number == i)
-           left_count++;
-         for (rhsp = rules[r].rhs; *rhsp >= 0; rhsp++)
-           if (item_number_as_symbol_number (*rhsp) == i)
-             {
-               right_count++;
-               break;
-             }
-       }
+        {
+          item_number *rhsp;
+          if (rules[r].lhs->number == i)
+            left_count++;
+          for (rhsp = rules[r].rhs; *rhsp >= 0; rhsp++)
+            if (item_number_as_symbol_number (*rhsp) == i)
+              {
+                right_count++;
+                break;
+              }
+        }
 
       buffer[0] = 0;
       fputs (tag, out);
@@ -460,38 +460,38 @@ print_grammar (FILE *out)
       END_TEST (0);
 
       if (left_count > 0)
-       {
-         END_TEST (65);
-         sprintf (buffer + strlen (buffer), _(" on left:"));
-
-         for (r = 0; r < nrules; r++)
-           {
-             if (rules[r].lhs->number == i)
-               {
-                 END_TEST (65);
-                 sprintf (buffer + strlen (buffer), " %d", r);
-               }
-           }
-       }
+        {
+          END_TEST (65);
+          sprintf (buffer + strlen (buffer), _(" on left:"));
+
+          for (r = 0; r < nrules; r++)
+            {
+              if (rules[r].lhs->number == i)
+                {
+                  END_TEST (65);
+                  sprintf (buffer + strlen (buffer), " %d", r);
+                }
+            }
+        }
 
       if (right_count > 0)
-       {
-         if (left_count > 0)
-           sprintf (buffer + strlen (buffer), ",");
-         END_TEST (65);
-         sprintf (buffer + strlen (buffer), _(" on right:"));
-         for (r = 0; r < nrules; r++)
-           {
-             item_number *rhsp;
-             for (rhsp = rules[r].rhs; *rhsp >= 0; rhsp++)
-               if (item_number_as_symbol_number (*rhsp) == i)
-                 {
-                   END_TEST (65);
-                   sprintf (buffer + strlen (buffer), " %d", r);
-                   break;
-                 }
-           }
-       }
+        {
+          if (left_count > 0)
+            sprintf (buffer + strlen (buffer), ",");
+          END_TEST (65);
+          sprintf (buffer + strlen (buffer), _(" on right:"));
+          for (r = 0; r < nrules; r++)
+            {
+              item_number *rhsp;
+              for (rhsp = rules[r].rhs; *rhsp >= 0; rhsp++)
+                if (item_number_as_symbol_number (*rhsp) == i)
+                  {
+                    END_TEST (65);
+                    sprintf (buffer + strlen (buffer), " %d", r);
+                    break;
+                  }
+            }
+        }
       fprintf (out, "%s\n", buffer);
     }
 }
@@ -507,14 +507,14 @@ print_results (void)
 
   reduce_output (out);
   grammar_rules_partial_print (out,
-                              _("Rules useless in parser due to conflicts"),
+                               _("Rules useless in parser due to conflicts"),
                                  rule_useless_in_parser_p);
   conflicts_output (out);
 
   print_grammar (out);
 
   /* If the whole state item sets, not only the kernels, are wanted,
-     `closure' will be run, which needs memory allocation/deallocation.   */
+     'closure' will be run, which needs memory allocation/deallocation.   */
   if (report_flag & report_itemsets)
     new_closure (nritems);
   /* Storage for print_reductions.  */
index 4769e4c4d7939405fb07443be9c96ba99fbd0220..7e429dbd107999e9ce5ff38c73cfdad635f07548 100644 (file)
 /* Print the lhs of a rule in such a manner that there is no vertical
    repetition, like in *.output files. */
 
-static void
-print_lhs (struct obstack *oout, rule *previous_rule, rule *r)
-{
-  if (previous_rule && STREQ (previous_rule->lhs->tag, r->lhs->tag))
-    {
-      int i;
-      for (i = 0; i < strlen (r->lhs->tag); ++i)
-        obstack_1grow (oout, ' ');
-      obstack_1grow (oout, '|');
-    }
-  else
-    {
-      obstack_sgrow (oout, escape (r->lhs->tag));
-      obstack_1grow (oout, ':');
-    }
-}
-
 static void
 print_core (struct obstack *oout, state *s)
 {
-  item_number *sitems = s->items;
-  rule *previous_rule = NULL;
+  item_number const *sitems = s->items;
+  symbol *previous_lhs = NULL;
   size_t i;
   size_t snritems = s->nitems;
 
-  /* Output all the items of a state, not only its kernel.  */
+  /* Output all the items of a state, not just its kernel.  */
   if (report_flag & report_itemsets)
     {
       closure (sitems, snritems);
@@ -79,25 +62,27 @@ print_core (struct obstack *oout, state *s)
   obstack_sgrow (oout, "\\n\\l");
   for (i = 0; i < snritems; i++)
     {
-      item_number *sp;
-      item_number *sp1;
-      rule_number r;
+      item_number const *sp1 = ritem + sitems[i];
+      item_number const *sp = sp1;
+      rule *r;
 
-      sp1 = sp = ritem + sitems[i];
-
-      while (*sp >= 0)
+      while (0 <= *sp)
         sp++;
 
-      r = item_number_as_rule_number (*sp);
+      r = &rules[item_number_as_rule_number (*sp)];
 
-      obstack_printf (oout, "%3d ", r);
-      print_lhs (oout, previous_rule, &rules[r]);
-      previous_rule = &rules[r];
+      obstack_printf (oout, "%3d ", r->number);
+      if (previous_lhs && UNIQSTR_EQ (previous_lhs->tag, r->lhs->tag))
+        obstack_printf (oout, "%*s| ",
+                        (int) strlen (previous_lhs->tag), "");
+      else
+        obstack_printf (oout, "%s: ", escape (r->lhs->tag));
+      previous_lhs = r->lhs;
 
-      for (sp = rules[r].rhs; sp < sp1; sp++)
-        obstack_printf (oout, " %s", escape (symbols[*sp]->tag));
+      for (sp = r->rhs; sp < sp1; sp++)
+        obstack_printf (oout, "%s ", escape (symbols[*sp]->tag));
 
-      obstack_sgrow (oout, " .");
+      obstack_1grow (oout, '.');
 
       for (/* Nothing */; *sp >= 0; ++sp)
         obstack_printf (oout, " %s", escape (symbols[*sp]->tag));
@@ -108,7 +93,7 @@ print_core (struct obstack *oout, state *s)
         {
           /* Find the reduction we are handling.  */
           reductions *reds = s->reductions;
-          int redno = state_reduction_find (s, &rules[r]);
+          int redno = state_reduction_find (s, r);
 
           /* Print them if there are.  */
           if (reds->lookahead_tokens && redno != -1)
@@ -148,21 +133,21 @@ print_actions (state const *s, FILE *fgraph)
   for (i = 0; i < trans->num; i++)
     if (!TRANSITION_IS_DISABLED (trans, i))
       {
-       state *s1 = trans->states[i];
-       symbol_number sym = s1->accessing_symbol;
-
-       /* Shifts are solid, gotos are dashed, and error is dotted.  */
-       char const *style =
-         (TRANSITION_IS_ERROR (trans, i) ? "dotted"
-          : TRANSITION_IS_SHIFT (trans, i) ? "solid"
-          : "dashed");
-
-       if (TRANSITION_IS_ERROR (trans, i)
-           && strcmp (symbols[sym]->tag, "error") != 0)
-         abort ();
-       output_edge (s->number, s1->number,
-                    TRANSITION_IS_ERROR (trans, i) ? NULL : symbols[sym]->tag,
-                    style, fgraph);
+        state *s1 = trans->states[i];
+        symbol_number sym = s1->accessing_symbol;
+
+        /* Shifts are solid, gotos are dashed, and error is dotted.  */
+        char const *style =
+          (TRANSITION_IS_ERROR (trans, i) ? "dotted"
+           : TRANSITION_IS_SHIFT (trans, i) ? "solid"
+           : "dashed");
+
+        if (TRANSITION_IS_ERROR (trans, i)
+            && STRNEQ (symbols[sym]->tag, "error"))
+          abort ();
+        output_edge (s->number, s1->number,
+                     TRANSITION_IS_ERROR (trans, i) ? NULL : symbols[sym]->tag,
+                     style, fgraph);
       }
   /* Display reductions. */
   output_red (s, s->reductions, fgraph);
@@ -182,8 +167,7 @@ print_state (state *s, FILE *fgraph)
   /* A node's label contains its items.  */
   obstack_init (&node_obstack);
   print_core (&node_obstack, s);
-  obstack_1grow (&node_obstack, '\0');
-  output_node (s->number, obstack_finish (&node_obstack), fgraph);
+  output_node (s->number, obstack_finish0 (&node_obstack), fgraph);
   obstack_free (&node_obstack, 0);
 
   /* Output the edges.  */
index 47a25405642e6b7cb0b525d118bc6af3143e723b..dbf4e95ea5799b800826b1c6d3121a09bae3261d 100644 (file)
@@ -59,7 +59,7 @@ void
 grammar_start_symbol_set (symbol *sym, location loc)
 {
   if (start_flag)
-    complain_at (loc, _("multiple %s declarations"), "%start");
+    complain (&loc, complaint, _("multiple %s declarations"), "%start");
   else
     {
       start_flag = true;
@@ -94,7 +94,7 @@ get_merge_function (uniqstr name)
       syms->next = xmalloc (sizeof syms->next[0]);
       syms->next->name = uniqstr_new (name);
       /* After all symbol type declarations have been parsed, packgram invokes
-        record_merge_function_type to set the type.  */
+         record_merge_function_type to set the type.  */
       syms->next->type = NULL;
       syms->next->next = NULL;
       merge_functions = head.next;
@@ -129,21 +129,22 @@ record_merge_function_type (int merger, uniqstr type, location declaration_loc)
   if (merge_function->type != NULL && !UNIQSTR_EQ (merge_function->type, type))
     {
       unsigned indent = 0;
-      complain_at_indent (declaration_loc, &indent,
-                          _("result type clash on merge function %s: "
-                            "<%s> != <%s>"),
-                          quote (merge_function->name), type,
-                          merge_function->type);
+      complain_indent (&declaration_loc, complaint, &indent,
+                       _("result type clash on merge function %s: "
+                         "<%s> != <%s>"),
+                       quote (merge_function->name), type,
+                       merge_function->type);
       indent += SUB_INDENT;
-      complain_at_indent (merge_function->type_declaration_location, &indent,
-                          _("previous declaration"));
-   }
+      complain_indent (&merge_function->type_declaration_location, complaint,
+                       &indent,
+                       _("previous declaration"));
+    }
   merge_function->type = uniqstr_new (type);
   merge_function->type_declaration_location = declaration_loc;
 }
 
 /*--------------------------------------.
-| Free all merge-function definitions. |
+| Free all merge-function definitions.  |
 `--------------------------------------*/
 
 void
@@ -201,9 +202,9 @@ assign_named_ref (symbol_list *p, named_ref *name)
 
   if (name->id == sym->tag)
     {
-      warn_at (name->loc,
-              _("duplicated symbol name for %s ignored"),
-              quote (sym->tag));
+      complain (&name->loc, Wother,
+                _("duplicated symbol name for %s ignored"),
+                quote (sym->tag));
       named_ref_free (name);
     }
   else
@@ -224,7 +225,7 @@ static symbol_list *previous_rule_end = NULL;
 
 void
 grammar_current_rule_begin (symbol *lhs, location loc,
-                           named_ref *lhs_name)
+                            named_ref *lhs_name)
 {
   symbol_list* p;
 
@@ -246,7 +247,8 @@ grammar_current_rule_begin (symbol *lhs, location loc,
       ++nvars;
     }
   else if (lhs->class == token_sym)
-    complain_at (loc, _("rule given for %s, which is a token"), lhs->tag);
+    complain (&loc, complaint, _("rule given for %s, which is a token"),
+              lhs->tag);
 }
 
 
@@ -261,13 +263,13 @@ grammar_current_rule_begin (symbol *lhs, location loc,
 static bool
 symbol_should_be_used (symbol_list const *s, bool *midrule_warning)
 {
-  if (symbol_destructor_get (s->content.sym)->code)
+  if (symbol_code_props_get (s->content.sym, destructor)->code)
     return true;
   if ((s->midrule && s->midrule->action_props.is_value_used)
       || (s->midrule_parent_rule
-          && symbol_list_n_get (s->midrule_parent_rule,
-                                s->midrule_parent_rhs_index)
-               ->action_props.is_value_used))
+          && (symbol_list_n_get (s->midrule_parent_rule,
+                                 s->midrule_parent_rhs_index)
+              ->action_props.is_value_used)))
     {
       *midrule_warning = true;
       return true;
@@ -295,19 +297,19 @@ grammar_rule_check (const symbol_list *r)
       symbol *first_rhs = r->next->content.sym;
       /* If $$ is being set in default way, report if any type mismatch.  */
       if (first_rhs)
-       {
-         char const *lhs_type = r->content.sym->type_name;
-         const char *rhs_type =
-           first_rhs->type_name ? first_rhs->type_name : "";
-         if (!UNIQSTR_EQ (lhs_type, rhs_type))
-           warn_at (r->location,
-                    _("type clash on default action: <%s> != <%s>"),
-                    lhs_type, rhs_type);
-       }
+        {
+          char const *lhs_type = r->content.sym->type_name;
+          const char *rhs_type =
+            first_rhs->type_name ? first_rhs->type_name : "";
+          if (!UNIQSTR_EQ (lhs_type, rhs_type))
+            complain (&r->location, Wother,
+                      _("type clash on default action: <%s> != <%s>"),
+                      lhs_type, rhs_type);
+        }
       /* Warn if there is no default for $$ but we need one.  */
       else
-       warn_at (r->location,
-                _("empty rule for typed nonterminal, and no action"));
+        complain (&r->location, Wother,
+                  _("empty rule for typed nonterminal, and no action"));
     }
 
   /* Check that symbol values that should be used are in fact used.  */
@@ -319,27 +321,38 @@ grammar_rule_check (const symbol_list *r)
         bool midrule_warning = false;
         if (!l->action_props.is_value_used
             && symbol_should_be_used (l, &midrule_warning)
-            /* The default action, $$ = $1, `uses' both.  */
+            /* The default action, $$ = $1, 'uses' both.  */
             && (r->action_props.code || (n != 0 && n != 1)))
           {
-            void (*warn_at_ptr)(location, char const*, ...) =
-              midrule_warning ? midrule_value_at : warn_at;
+            warnings warn_flag = midrule_warning ? Wmidrule_values : Wother;
             if (n)
-              warn_at_ptr (l->location, _("unused value: $%d"), n);
+              complain (&l->location, warn_flag, _("unused value: $%d"), n);
             else
-              warn_at_ptr (l->location, _("unset value: $$"));
+              complain (&l->location, warn_flag, _("unset value: $$"));
           }
       }
   }
 
+  /* Check that %empty => empty rule.  */
+  if (r->percent_empty_loc.start.file
+      && r->next && r->next->content.sym)
+    complain (&r->percent_empty_loc, complaint,
+              _("%%empty on non-empty rule"));
+
+  /* Check that empty rule => %empty.  */
+  if (!(r->next && r->next->content.sym)
+      && !r->midrule_parent_rule
+      && !r->percent_empty_loc.start.file)
+    complain (&r->location, Wempty_rule, _("empty rule without %%empty"));
+
   /* See comments in grammar_current_rule_prec_set for how POSIX
      mandates this complaint.  It's only for identifiers, so skip
      it for char literals and strings, which are always tokens.  */
   if (r->ruleprec
       && r->ruleprec->tag[0] != '\'' && r->ruleprec->tag[0] != '"'
-      && !r->ruleprec->declared && !r->ruleprec->prec)
-    warn_at (r->location, _("token for %%prec is not defined: %s"),
-             r->ruleprec->tag);
+      && r->ruleprec->status != declared && !r->ruleprec->prec)
+    complain (&r->location, Wother,
+              _("token for %%prec is not defined: %s"), r->ruleprec->tag);
 }
 
 
@@ -388,7 +401,8 @@ grammar_midrule_action (void)
   code_props_rule_action_init (&midrule->action_props,
                                current_rule->action_props.code,
                                current_rule->action_props.location,
-                               midrule, 0);
+                               midrule, 0,
+                               current_rule->action_props.is_predicate);
   code_props_none_init (&current_rule->action_props);
 
   if (previous_rule_end)
@@ -428,8 +442,26 @@ grammar_current_rule_prec_set (symbol *precsym, location loc)
      token.  */
   symbol_class_set (precsym, token_sym, loc, false);
   if (current_rule->ruleprec)
-    complain_at (loc, _("only one %s allowed per rule"), "%prec");
-  current_rule->ruleprec = precsym;
+    duplicate_directive ("%prec",
+                         current_rule->ruleprec->location, loc);
+  else
+    current_rule->ruleprec = precsym;
+}
+
+/* Set %empty for the current rule. */
+
+void
+grammar_current_rule_empty_set (location loc)
+{
+  /* If %empty is used and -Wno-empty-rule is not, then enable
+     -Wempty-rule.  */
+  if (warning_is_unset (Wempty_rule))
+    warning_argmatch ("empty-rule", 0, 0);
+  if (current_rule->percent_empty_loc.start.file)
+    duplicate_directive ("%empty",
+                         current_rule->percent_empty_loc, loc);
+  else
+    current_rule->percent_empty_loc = loc;
 }
 
 /* Attach dynamic precedence DPREC to the current rule. */
@@ -438,12 +470,19 @@ void
 grammar_current_rule_dprec_set (int dprec, location loc)
 {
   if (! glr_parser)
-    warn_at (loc, _("%s affects only GLR parsers"), "%dprec");
+    complain (&loc, Wother, _("%s affects only GLR parsers"),
+              "%dprec");
   if (dprec <= 0)
-    complain_at (loc, _("%s must be followed by positive number"), "%dprec");
+    complain (&loc, complaint, _("%s must be followed by positive number"),
+              "%dprec");
   else if (current_rule->dprec != 0)
-    complain_at (loc, _("only one %s allowed per rule"), "%dprec");
-  current_rule->dprec = dprec;
+    duplicate_directive ("%dprec",
+                         current_rule->dprec_location, loc);
+  else
+    {
+      current_rule->dprec = dprec;
+      current_rule->dprec_location = loc;
+    }
 }
 
 /* Attach a merge function NAME with argument type TYPE to current
@@ -453,11 +492,16 @@ void
 grammar_current_rule_merge_set (uniqstr name, location loc)
 {
   if (! glr_parser)
-    warn_at (loc, _("%s affects only GLR parsers"), "%merge");
+    complain (&loc, Wother, _("%s affects only GLR parsers"),
+              "%merge");
   if (current_rule->merger != 0)
-    complain_at (loc, _("only one %s allowed per rule"), "%merge");
-  current_rule->merger = get_merge_function (name);
-  current_rule->merger_declaration_location = loc;
+    duplicate_directive ("%merge",
+                         current_rule->merger_declaration_location, loc);
+  else
+    {
+      current_rule->merger = get_merge_function (name);
+      current_rule->merger_declaration_location = loc;
+    }
 }
 
 /* Attach SYM to the current rule.  If needed, move the previous
@@ -465,7 +509,7 @@ grammar_current_rule_merge_set (uniqstr name, location loc)
 
 void
 grammar_current_rule_symbol_append (symbol *sym, location loc,
-                                   named_ref *name)
+                                    named_ref *name)
 {
   symbol_list *p;
   if (current_rule->action_props.code)
@@ -473,20 +517,22 @@ grammar_current_rule_symbol_append (symbol *sym, location loc,
   p = grammar_symbol_append (sym, loc);
   if (name)
     assign_named_ref(p, name);
+  if (sym->status == undeclared || sym->status == used)
+    sym->status = needed;
 }
 
 /* Attach an ACTION to the current rule.  */
 
 void
 grammar_current_rule_action_append (const char *action, location loc,
-                                   named_ref *name)
+                                    named_ref *name, bool is_predicate)
 {
   if (current_rule->action_props.code)
     grammar_midrule_action ();
   /* After all symbol declarations have been parsed, packgram invokes
      code_props_translate_code.  */
   code_props_rule_action_init (&current_rule->action_props, action, loc,
-                               current_rule, name);
+                               current_rule, name, is_predicate);
 }
 
 \f
@@ -500,7 +546,7 @@ packgram (void)
 {
   unsigned int itemno = 0;
   rule_number ruleno = 0;
-  symbol_list *p = grammar;
+  symbol_list *p;
 
   ritem = xnmalloc (nritems + 1, sizeof *ritem);
 
@@ -509,12 +555,11 @@ packgram (void)
 
   rules = xnmalloc (nrules, sizeof *rules);
 
-  while (p)
+  for (p = grammar; p; p = p->next)
     {
-      int rule_length = 0;
       symbol *ruleprec = p->ruleprec;
       record_merge_function_type (p->merger, p->content.sym->type_name,
-                                 p->merger_declaration_location);
+                                  p->merger_declaration_location);
       rules[ruleno].user_number = ruleno;
       rules[ruleno].number = ruleno;
       rules[ruleno].lhs = p->content.sym;
@@ -527,57 +572,58 @@ packgram (void)
       rules[ruleno].useful = true;
       rules[ruleno].action = p->action_props.code;
       rules[ruleno].action_location = p->action_props.location;
+      rules[ruleno].is_predicate = p->action_props.is_predicate;
 
-      /* If the midrule's $$ is set or its $n is used, remove the `$' from the
-        symbol name so that it's a user-defined symbol so that the default
-        %destructor and %printer apply.  */
+      /* If the midrule's $$ is set or its $n is used, remove the '$' from the
+         symbol name so that it's a user-defined symbol so that the default
+         %destructor and %printer apply.  */
       if (p->midrule_parent_rule
           && (p->action_props.is_value_used
-             || symbol_list_n_get (p->midrule_parent_rule,
-                                   p->midrule_parent_rhs_index)
-                   ->action_props.is_value_used))
-       p->content.sym->tag += 1;
+              || (symbol_list_n_get (p->midrule_parent_rule,
+                                     p->midrule_parent_rhs_index)
+                  ->action_props.is_value_used)))
+        p->content.sym->tag += 1;
 
       /* Don't check the generated rule 0.  It has no action, so some rhs
-        symbols may appear unused, but the parsing algorithm ensures that
-        %destructor's are invoked appropriately.  */
+         symbols may appear unused, but the parsing algorithm ensures that
+         %destructor's are invoked appropriately.  */
       if (p != grammar)
-       grammar_rule_check (p);
-
-      for (p = p->next; p && p->content.sym; p = p->next)
-       {
-         ++rule_length;
-
-         /* Don't allow rule_length == INT_MAX, since that might
-            cause confusion with strtol if INT_MAX == LONG_MAX.  */
-         if (rule_length == INT_MAX)
-             fatal_at (rules[ruleno].location, _("rule is too long"));
-
-         /* item_number = symbol_number.
-            But the former needs to contain more: negative rule numbers. */
-         ritem[itemno++] =
-            symbol_number_as_item_number (p->content.sym->number);
-         /* A rule gets by default the precedence and associativity
-            of its last token.  */
-         if (p->content.sym->class == token_sym && default_prec)
-           rules[ruleno].prec = p->content.sym;
-       }
+        grammar_rule_check (p);
+
+      {
+        size_t rule_length = 0;
+        for (p = p->next; p->content.sym; p = p->next)
+          {
+            ++rule_length;
+
+            /* Don't allow rule_length == INT_MAX, since that might
+               cause confusion with strtol if INT_MAX == LONG_MAX.  */
+            if (rule_length == INT_MAX)
+              complain (&rules[ruleno].location, fatal, _("rule is too long"));
+
+            /* item_number = symbol_number.
+               But the former needs to contain more: negative rule numbers. */
+            ritem[itemno++] =
+              symbol_number_as_item_number (p->content.sym->number);
+            /* A rule gets by default the precedence and associativity
+               of its last token.  */
+            if (p->content.sym->class == token_sym && default_prec)
+              rules[ruleno].prec = p->content.sym;
+          }
+      }
 
       /* If this rule has a %prec,
          the specified symbol's precedence replaces the default.  */
       if (ruleprec)
-       {
-         rules[ruleno].precsym = ruleprec;
-         rules[ruleno].prec = ruleprec;
-       }
+        {
+          rules[ruleno].precsym = ruleprec;
+          rules[ruleno].prec = ruleprec;
+        }
       /* An item ends by the rule number (negated).  */
       ritem[itemno++] = rule_number_as_item_number (ruleno);
       aver (itemno < ITEM_NUMBER_MAX);
       ++ruleno;
       aver (ruleno < RULE_NUMBER_MAX);
-
-      if (p)
-       p = p->next;
     }
 
   aver (itemno == nritems);
@@ -623,7 +669,7 @@ reader (void)
   gram_parse ();
   prepare_percent_define_front_end_variables ();
 
-  if (! complaint_issued)
+  if (complaint_status  < status_complaint)
     check_and_convert_grammar ();
 
   xfclose (gram_in);
@@ -633,17 +679,17 @@ static void
 prepare_percent_define_front_end_variables (void)
 {
   /* Set %define front-end variable defaults.  */
-  muscle_percent_define_default ("lr.keep-unreachable-states", "false");
+  muscle_percent_define_default ("lr.keep-unreachable-state", "false");
   {
     char *lr_type;
     /* IELR would be a better default, but LALR is historically the
        default.  */
     muscle_percent_define_default ("lr.type", "lalr");
     lr_type = muscle_percent_define_get ("lr.type");
-    if (0 != strcmp (lr_type, "canonical-lr"))
-      muscle_percent_define_default ("lr.default-reductions", "most");
+    if (STRNEQ (lr_type, "canonical-lr"))
+      muscle_percent_define_default ("lr.default-reduction", "most");
     else
-      muscle_percent_define_default ("lr.default-reductions", "accepting");
+      muscle_percent_define_default ("lr.default-reduction", "accepting");
     free (lr_type);
   }
 
@@ -651,7 +697,7 @@ prepare_percent_define_front_end_variables (void)
   {
     static char const * const values[] = {
       "lr.type", "lalr", "ielr", "canonical-lr", NULL,
-      "lr.default-reductions", "most", "consistent", "accepting", NULL,
+      "lr.default-reduction", "most", "consistent", "accepting", NULL,
       NULL
     };
     muscle_percent_define_check_values (values);
@@ -661,7 +707,7 @@ prepare_percent_define_front_end_variables (void)
 
 /*-------------------------------------------------------------.
 | Check the grammar that has just been read, and convert it to |
-| internal form.                                              |
+| internal form.                                               |
 `-------------------------------------------------------------*/
 
 static void
@@ -669,7 +715,7 @@ check_and_convert_grammar (void)
 {
   /* Grammar has been read.  Do some checking.  */
   if (nrules == 0)
-    fatal (_("no rules in the input grammar"));
+    complain (NULL, fatal, _("no rules in the input grammar"));
 
   /* If the user did not define her ENDTOKEN, do it now. */
   if (!endtoken)
@@ -705,7 +751,7 @@ check_and_convert_grammar (void)
   /* Insert the initial rule, whose line is that of the first rule
      (not that of the start symbol):
 
-     accept: %start EOF.  */
+     $accept: %start $end.  */
   {
     symbol_list *p = symbol_list_sym_new (accept, empty_location);
     p->location = grammar->location;
@@ -718,7 +764,8 @@ check_and_convert_grammar (void)
     grammar = p;
   }
 
-  aver (nsyms <= SYMBOL_NUMBER_MAXIMUM && nsyms == ntokens + nvars);
+  aver (nsyms <= SYMBOL_NUMBER_MAXIMUM);
+  aver (nsyms == ntokens + nvars);
 
   /* Assign the symbols their symbol numbers.  Write #defines for the
      token symbols into FDEFINES if requested.  */
@@ -729,11 +776,11 @@ check_and_convert_grammar (void)
      action type checking.
 
      Before invoking grammar_rule_check (in packgram below) on any rule, make
-     sure all actions have already been scanned in order to set `used' flags.
+     sure all actions have already been scanned in order to set 'used' flags.
      Otherwise, checking that a midrule's $$ should be set will not always work
      properly because the check must forward-reference the midrule's parent
-     rule.  For the same reason, all the `used' flags must be set before
-     checking whether to remove `$' from any midrule symbol name (also in
+     rule.  For the same reason, all the 'used' flags must be set before
+     checking whether to remove '$' from any midrule symbol name (also in
      packgram).  */
   {
     symbol_list *sym;
index bc4ac55ef16f8a8113b191089de6fae23252e232..ba6ffe6edca76c8a91d2a4a81c5ee9e03cbd034e 100644 (file)
@@ -44,16 +44,18 @@ char const *token_name (int type);
 /* From reader.c. */
 void grammar_start_symbol_set (symbol *sym, location loc);
 void grammar_current_rule_begin (symbol *lhs, location loc,
-                                named_ref *lhs_named_ref);
+                                 named_ref *lhs_named_ref);
 void grammar_current_rule_end (location loc);
 void grammar_midrule_action (void);
+/* Apply %empty to the current rule.  */
+void grammar_current_rule_empty_set (location loc);
 void grammar_current_rule_prec_set (symbol *precsym, location loc);
 void grammar_current_rule_dprec_set (int dprec, location loc);
 void grammar_current_rule_merge_set (uniqstr name, location loc);
 void grammar_current_rule_symbol_append (symbol *sym, location loc,
-                                        named_ref *nref);
+                                         named_ref *nref);
 void grammar_current_rule_action_append (const char *action, location loc,
-                                        named_ref *nref);
+                                         named_ref *nref, bool);
 void reader (void);
 void free_merger_functions (void);
 
index 2a29e73cb4461652c9b6e814687c6a99dced1b0d..eea11b1e20345158c318f2403b2a33f039ce20a1 100644 (file)
@@ -49,7 +49,7 @@ static bitset P;
 static bitset V;
 
 /* Set of symbols used to define rule precedence (so they are
-   `useless', but no warning should be issued).  */
+   'useless', but no warning should be issued).  */
 static bitset V1;
 
 static rule_number nuseful_productions;
@@ -114,14 +114,14 @@ useless_nonterminals (void)
     {
       bitset_copy (Np, N);
       for (r = 0; r < nrules; r++)
-       if (!bitset_test (P, r)
-           && useful_production (r, N))
-         {
-           bitset_set (Np, rules[r].lhs->number - ntokens);
-           bitset_set (P, r);
-         }
+        if (!bitset_test (P, r)
+            && useful_production (r, N))
+          {
+            bitset_set (Np, rules[r].lhs->number - ntokens);
+            bitset_set (P, r);
+          }
       if (bitset_equal_p (N, Np))
-       break;
+        break;
       Ns = Np;
       Np = N;
       N = Ns;
@@ -168,37 +168,37 @@ inaccessable_symbols (void)
       bitset_set (V, accept->number);
 
       while (1)
-       {
-         rule_number r;
-         bitset_copy (Vp, V);
-         for (r = 0; r < nrules; r++)
-           {
-             if (!bitset_test (Pp, r)
-                 && bitset_test (P, r)
-                 && bitset_test (V, rules[r].lhs->number))
-               {
-                 item_number *rhsp;
-                 for (rhsp = rules[r].rhs; *rhsp >= 0; rhsp++)
-                   if (ISTOKEN (*rhsp) || bitset_test (N, *rhsp - ntokens))
-                     bitset_set (Vp, *rhsp);
-                 bitset_set (Pp, r);
-               }
-           }
-         if (bitset_equal_p (V, Vp))
-           break;
-         Vs = Vp;
-         Vp = V;
-         V = Vs;
-       }
+        {
+          rule_number r;
+          bitset_copy (Vp, V);
+          for (r = 0; r < nrules; r++)
+            {
+              if (!bitset_test (Pp, r)
+                  && bitset_test (P, r)
+                  && bitset_test (V, rules[r].lhs->number))
+                {
+                  item_number *rhsp;
+                  for (rhsp = rules[r].rhs; *rhsp >= 0; rhsp++)
+                    if (ISTOKEN (*rhsp) || bitset_test (N, *rhsp - ntokens))
+                      bitset_set (Vp, *rhsp);
+                  bitset_set (Pp, r);
+                }
+            }
+          if (bitset_equal_p (V, Vp))
+            break;
+          Vs = Vp;
+          Vp = V;
+          V = Vs;
+        }
     }
 
   bitset_free (V);
   V = Vp;
 
   /* Tokens 0, 1, and 2 are internal to Bison.  Consider them useful. */
-  bitset_set (V, endtoken->number);            /* end-of-input token */
-  bitset_set (V, errtoken->number);            /* error token */
-  bitset_set (V, undeftoken->number);          /* some undefined token */
+  bitset_set (V, endtoken->number);             /* end-of-input token */
+  bitset_set (V, errtoken->number);             /* error token */
+  bitset_set (V, undeftoken->number);           /* some undefined token */
 
   bitset_free (P);
   P = Pp;
@@ -211,7 +211,7 @@ inaccessable_symbols (void)
     symbol_number i;
     for (i = ntokens; i < nsyms; i++)
       if (bitset_test (V, i))
-       nuseful_nonterminals++;
+        nuseful_nonterminals++;
   }
   nuseless_nonterminals = nvars - nuseful_nonterminals;
 
@@ -220,7 +220,7 @@ inaccessable_symbols (void)
     rule_number r;
     for (r = 0; r < nrules; ++r)
       if (rules[r].precsym != 0)
-       bitset_set (V1, rules[r].precsym->number);
+        bitset_set (V1, rules[r].precsym->number);
   }
 }
 
@@ -256,11 +256,11 @@ reduce_grammar_tables (void)
     /* Renumber the rules markers in RITEMS.  */
     for (r = 0; r < nrules; ++r)
       {
-       item_number *rhsp = rules[r].rhs;
-       for (/* Nothing. */; *rhsp >= 0; ++rhsp)
-         /* Nothing. */;
-       *rhsp = rule_number_as_item_number (r);
-       rules[r].number = r;
+        item_number *rhsp = rules[r].rhs;
+        for (/* Nothing. */; *rhsp >= 0; ++rhsp)
+          /* Nothing. */;
+        *rhsp = rule_number_as_item_number (r);
+        rules[r].number = r;
       }
     nrules -= nuseless_productions;
   }
@@ -271,8 +271,8 @@ reduce_grammar_tables (void)
     int length;
     for (r = nrules; r < nrules + nuseless_productions; ++r)
       {
-       length = rule_rhs_length (&rules[r]);
-       nritems -= length + 1;
+        length = rule_rhs_length (&rules[r]);
+        nritems -= length + 1;
       }
   }
 }
@@ -285,22 +285,23 @@ reduce_grammar_tables (void)
 static void
 nonterminals_reduce (void)
 {
-  symbol_number i, n;
-
   /* Map the nonterminals to their new index: useful first, useless
      afterwards.  Kept for later report.  */
 
   symbol_number *nontermmap = xnmalloc (nvars, sizeof *nontermmap);
-  n = ntokens;
+  symbol_number n = ntokens;
+  symbol_number i;
   for (i = ntokens; i < nsyms; i++)
     if (bitset_test (V, i))
       nontermmap[i - ntokens] = n++;
   for (i = ntokens; i < nsyms; i++)
     if (!bitset_test (V, i))
       {
-       nontermmap[i - ntokens] = n++;
-       warn_at (symbols[i]->location, _("nonterminal useless in grammar: %s"),
-                symbols[i]->tag);
+        nontermmap[i - ntokens] = n++;
+        if (symbols[i]->status != used)
+          complain (&symbols[i]->location, Wother,
+                    _("nonterminal useless in grammar: %s"),
+                    symbols[i]->tag);
       }
 
 
@@ -321,11 +322,11 @@ nonterminals_reduce (void)
     rule_number r;
     for (r = 0; r < nrules; ++r)
       {
-       item_number *rhsp;
-       for (rhsp = rules[r].rhs; *rhsp >= 0; ++rhsp)
-         if (ISVAR (*rhsp))
-           *rhsp =  symbol_number_as_item_number (nontermmap[*rhsp
-                                                             - ntokens]);
+        item_number *rhsp;
+        for (rhsp = rules[r].rhs; *rhsp >= 0; ++rhsp)
+          if (ISVAR (*rhsp))
+            *rhsp =  symbol_number_as_item_number (nontermmap[*rhsp
+                                                              - ntokens]);
       }
     accept->number = nontermmap[accept->number - ntokens];
   }
@@ -349,7 +350,7 @@ reduce_output (FILE *out)
       int i;
       fprintf (out, "%s\n\n", _("Nonterminals useless in grammar"));
       for (i = 0; i < nuseless_nonterminals; ++i)
-       fprintf (out, "   %s\n", symbols[nsyms + i]->tag);
+        fprintf (out, "   %s\n", symbols[nsyms + i]->tag);
       fputs ("\n\n", out);
     }
 
@@ -358,19 +359,19 @@ reduce_output (FILE *out)
     int i;
     for (i = 0; i < ntokens; i++)
       if (reduce_token_unused_in_grammar (i))
-       {
-         if (!b)
-           fprintf (out, "%s\n\n", _("Terminals unused in grammar"));
-         b = true;
-         fprintf (out, "   %s\n", symbols[i]->tag);
-       }
+        {
+          if (!b)
+            fprintf (out, "%s\n\n", _("Terminals unused in grammar"));
+          b = true;
+          fprintf (out, "   %s\n", symbols[i]->tag);
+        }
     if (b)
       fputs ("\n\n", out);
   }
 
   if (nuseless_productions > 0)
     grammar_rules_partial_print (out, _("Rules useless in grammar"),
-                                rule_useless_in_grammar_p);
+                                 rule_useless_in_grammar_p);
 }
 \f
 
@@ -382,15 +383,15 @@ static void
 reduce_print (void)
 {
   if (nuseless_nonterminals > 0)
-    warn (ngettext ("%d nonterminal useless in grammar",
-                    "%d nonterminals useless in grammar",
-                    nuseless_nonterminals),
-          nuseless_nonterminals);
+    complain (NULL, Wother, ngettext ("%d nonterminal useless in grammar",
+                                      "%d nonterminals useless in grammar",
+                                      nuseless_nonterminals),
+              nuseless_nonterminals);
   if (nuseless_productions > 0)
-    warn (ngettext ("%d rule useless in grammar",
-                    "%d rules useless in grammar",
-                    nuseless_productions),
-          nuseless_productions);
+    complain (NULL, Wother, ngettext ("%d rule useless in grammar",
+                                      "%d rules useless in grammar",
+                                      nuseless_productions),
+              nuseless_productions);
 }
 \f
 void
@@ -415,9 +416,9 @@ reduce_grammar (void)
   reduce_print ();
 
   if (!bitset_test (N, accept->number - ntokens))
-    fatal_at (startsymbol_location,
-             _("start symbol %s does not derive any sentence"),
-             startsymbol->tag);
+    complain (&startsymbol_location, fatal,
+              _("start symbol %s does not derive any sentence"),
+              startsymbol->tag);
 
   /* First reduce the nonterminals, as they renumber themselves in the
      whole grammar.  If you change the order, nonterms would be
@@ -431,9 +432,9 @@ reduce_grammar (void)
     {
       grammar_dump (stderr, "Reduced Grammar");
 
-      fprintf (stderr, "reduced %s defines %d terminals, %d nonterminals\
-, and %d productions.\n",
-              grammar_file, ntokens, nvars, nrules);
+      fprintf (stderr, "reduced %s defines %d terminals, %d nonterminals"
+               ", and %d productions.\n",
+               grammar_file, ntokens, nvars, nrules);
     }
 }
 
index 133c8498eda5a3f27b9ed5f991373c5294cc81da..5746eca70492691c07aa27b09a4b83fb2b247cc3 100644 (file)
@@ -36,8 +36,8 @@ relation_print (relation r, relation_node size, FILE *out)
     {
       fprintf (out, "%3lu: ", (unsigned long int) i);
       if (r[i])
-       for (j = 0; r[i][j] != END_NODE; ++j)
-         fprintf (out, "%3lu ", (unsigned long int) r[i][j]);
+        for (j = 0; r[i][j] != END_NODE; ++j)
+          fprintf (out, "%3lu ", (unsigned long int) r[i][j]);
       fputc ('\n', out);
     }
   fputc ('\n', out);
@@ -70,25 +70,25 @@ traverse (relation_node i)
   if (R[i])
     for (j = 0; R[i][j] != END_NODE; ++j)
       {
-       if (INDEX[R[i][j]] == 0)
-         traverse (R[i][j]);
+        if (INDEX[R[i][j]] == 0)
+          traverse (R[i][j]);
 
-       if (INDEX[i] > INDEX[R[i][j]])
-         INDEX[i] = INDEX[R[i][j]];
+        if (INDEX[i] > INDEX[R[i][j]])
+          INDEX[i] = INDEX[R[i][j]];
 
-       bitset_or (F[i], F[i], F[R[i][j]]);
+        bitset_or (F[i], F[i], F[R[i][j]]);
       }
 
   if (INDEX[i] == height)
     for (;;)
       {
-       j = VERTICES[top--];
-       INDEX[j] = infinity;
+        j = VERTICES[top--];
+        INDEX[j] = infinity;
 
-       if (i == j)
-         break;
+        if (i == j)
+          break;
 
-       bitset_copy (F[j], F[i]);
+        bitset_copy (F[j], F[i]);
       }
 }
 
@@ -144,17 +144,17 @@ relation_transpose (relation *R_arg, relation_node n)
   for (i = 0; i < n; i++)
     if (r[i])
       for (j = 0; r[i][j] != END_NODE; ++j)
-       ++nedges[r[i][j]];
+        ++nedges[r[i][j]];
 
   /* Allocate. */
   for (i = 0; i < n; i++)
     {
       relation_node *sp = NULL;
       if (nedges[i] > 0)
-       {
-         sp = xnmalloc (nedges[i] + 1, sizeof *sp);
-         sp[nedges[i]] = END_NODE;
-       }
+        {
+          sp = xnmalloc (nedges[i] + 1, sizeof *sp);
+          sp[nedges[i]] = END_NODE;
+        }
       new_R[i] = sp;
       end_R[i] = sp;
     }
@@ -163,7 +163,7 @@ relation_transpose (relation *R_arg, relation_node n)
   for (i = 0; i < n; i++)
     if (r[i])
       for (j = 0; r[i][j] != END_NODE; ++j)
-       *end_R[r[i][j]]++ = i;
+        *end_R[r[i][j]]++ = i;
 
   free (nedges);
   free (end_R);
index 7f0d3f4b48b635e85471f704241f1b98d0c5bef2..b44e1a7f9856190d7536d798bf983ee9248f6518 100644 (file)
@@ -26,7 +26,7 @@
    If GRAPH is a relation, then GRAPH[Node] is a list of adjacent
    nodes, ended with END_NODE.  */
 
-#define END_NODE ((relation_node) -1)
+# define END_NODE ((relation_node) -1)
 
 typedef size_t relation_node;
 typedef relation_node *relation_nodes;
index 4a018f854e42b7dd8b7e6a5c91c230062dd3ffa3..7d37b766b54701d1c63b21cfad7c1e963680c907 100644 (file)
@@ -1,3 +1,3 @@
 #include <config.h>
 #include "system.h"
-#include "scan-code.c"
+#include "src/scan-code.c"
index 2a231b84af1e3986832f9352d421e67d60dd60ac..d5a15c1a1ca2e2007f315a12960b5e23d7f31705 100644 (file)
@@ -66,6 +66,17 @@ typedef struct code_props {
    */
   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;
 
@@ -82,11 +93,20 @@ typedef struct code_props {
 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
@@ -137,7 +157,7 @@ void code_props_symbol_action_init (code_props *self, char const *code,
  */
 void code_props_rule_action_init (code_props *self, char const *code,
                                   location code_loc, struct symbol_list *rule,
-                                  named_ref *name);
+                                  named_ref *name, bool is_predicate);
 
 /**
  * \pre
index f1329e0b8c73b892d5cbc95b53778f830b10fe55..cced97bfeaac135080bd320f351395854390f09d 100644 (file)
 #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>
@@ -50,7 +51,7 @@ 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. */
@@ -77,49 +78,30 @@ 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>]+
+   NUL and newline, as this simplifies our implementation.  We allow
+   "->" as a means to dereference a pointer.  */
+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}"]"|"$"
 
 %%
 
 %{
-  /* Nesting level of the current code in braces.  */
-  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 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
-     for this because, at the end of strings and comments, we still need
-     to know whether we're in a directive.  */
-  bool in_cpp = false;
-
   /* This scanner is special: it is invoked only once, henceforth
      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;
 %}
 
@@ -139,8 +121,8 @@ ref      -?[0-9]+|{id}|"["{id}"]"|"$"
 
 <SC_LINE_COMMENT>
 {
-  "\n"          STRING_GROW; BEGIN sc_context;
-  {splice}      STRING_GROW;
+  "\n"           STRING_GROW; BEGIN sc_context;
+  {splice}       STRING_GROW;
 }
 
 
@@ -150,48 +132,30 @@ ref      -?[0-9]+|{id}|"["{id}"]"|"$"
 
 <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>
 {
-  "'" {
-    STRING_GROW;
-    BEGIN SC_CHARACTER;
-    need_semicolon = true;
-  }
-  "\"" {
-    STRING_GROW;
-    BEGIN SC_STRING;
-    need_semicolon = true;
-  }
-  "/"{splice}"*" {
-    STRING_GROW;
-    BEGIN SC_COMMENT;
-  }
-  "/"{splice}"/" {
-    STRING_GROW;
-    BEGIN SC_LINE_COMMENT;
-  }
+  "'"              STRING_GROW; BEGIN SC_CHARACTER;
+  "\""             STRING_GROW; BEGIN SC_STRING;
+  "/"{splice}"*"   STRING_GROW; BEGIN SC_COMMENT;
+  "/"{splice}"/"   STRING_GROW; BEGIN SC_LINE_COMMENT;
+
   [$@]  {
-    warn_at (*loc, _("stray '%s'"), yytext);
+    complain (loc, Wother, _("stray '%s'"), yytext);
     obstack_escape (&obstack_for_string, yytext);
-    need_semicolon = true;
-  }
-  [\[\]]  {
-    obstack_escape (&obstack_for_string, yytext);
-    need_semicolon = true;
   }
 }
 
@@ -202,64 +166,13 @@ ref      -?[0-9]+|{id}|"["{id}"]"|"$"
     handle_action_dollar (self->rule, yytext, *loc);
     if (ref_tail_fields)
       obstack_sgrow (&obstack_for_string, ref_tail_fields);
-    need_semicolon = true;
   }
   "@"{ref} {
     ref_tail_fields = NULL;
     handle_action_at (self->rule, yytext, *loc);
     if (ref_tail_fields)
       obstack_sgrow (&obstack_for_string, ref_tail_fields);
-    need_semicolon = true;
-  }
-
-  ";"  STRING_GROW;                 need_semicolon = false;
-  "{"  STRING_GROW; ++braces_level; need_semicolon = false;
-  "}"  {
-    bool outer_brace = --braces_level == 0;
-
-    /* As an undocumented Bison extension, append ';' before the last
-       brace in braced code, so that the user code can omit trailing
-       ';'.  But do not append ';' if emulating Yacc, since Yacc does
-       not append one.  This is deprecated since release 2.4.1.  */
-    if (outer_brace && !yacc_flag && language_prio == default_prio
-        && skeleton_prio == default_prio && need_semicolon && ! in_cpp)
-      {
-        unsigned int indent = 0;
-        warn_at_indent (*loc, &indent,
-                       _("a ';' might be needed at the end of action code"));
-        indent += SUB_INDENT;
-        warn_at_indent (*loc, &indent,
-                       _("future versions of Bison will not add the ';'"));
-        obstack_1grow (&obstack_for_string, ';');
-      }
-
-    STRING_GROW;
-    need_semicolon = false;
-  }
-
-  /* Preprocessing directives should only be recognized at the beginning
-     of lines, allowing whitespace including comments, but in C/C++,
-     '#' can only be the start of preprocessor directives or within
-     '#define' directives anyway, so don't bother with begin of line.  */
-  "#"       STRING_GROW; in_cpp = true;
-
-  {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;
 }
 
 <SC_SYMBOL_ACTION>
@@ -274,7 +187,7 @@ ref      -?[0-9]+|{id}|"["{id}"]"|"$"
   }
   "@$" {
     obstack_sgrow (&obstack_for_string, "]b4_at_dollar[");
-    locations_flag = true;
+    muscle_percent_define_ensure("locations", the_location, true);
   }
 }
 
@@ -287,7 +200,7 @@ ref      -?[0-9]+|{id}|"["{id}"]"|"$"
   /* By default, grow the string obstack with the input.  */
   .|\n        STRING_GROW;
 
 /* End of processing. */
+ /* End of processing. */
   <<EOF>>     STRING_FINISH; return last_string;
 }
 
@@ -349,9 +262,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];
 }
@@ -381,7 +294,7 @@ find_prefix_end (const char *prefix, char *begin, char *end)
 
 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;
 
@@ -403,7 +316,7 @@ variant_add (uniqstr id, location id_loc, unsigned symbol_index,
 }
 
 static const char *
-get_at_spec (unsigned symbol_index)
+get_at_spec(unsigned symbol_index)
 {
   static char at_buf[20];
   if (symbol_index == 0)
@@ -414,77 +327,72 @@ get_at_spec (unsigned symbol_index)
 }
 
 static void
-show_sub_messages (const char* cp, bool explicit_bracketing,
-                   int midrule_rhs_index, char dollar_or_at,
-                   bool is_warning, unsigned indent)
+show_sub_message (warnings warning,
+                  const char* cp, bool explicit_bracketing,
+                  int midrule_rhs_index, char dollar_or_at,
+                  unsigned indent, const variant *var)
 {
-  unsigned i;
+  const char *at_spec = get_at_spec (var->symbol_index);
 
-  for (i = 0; i < variant_count; ++i)
+  if (var->err == 0)
+    complain_indent (&var->loc, warning, &indent,
+                     _("refers to: %c%s at %s"), dollar_or_at,
+                     var->id, at_spec);
+  else
     {
-      const variant *var = &variant_table[i];
-      const char *at_spec = get_at_spec (var->symbol_index);
+      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;
 
-      if (var->err == 0)
+      /* Create the explanation message. */
+      obstack_init (&msg_buf);
+
+      obstack_printf (&msg_buf, _("possibly meant: %c"), dollar_or_at);
+      if (contains_dot_or_dash (id))
+        obstack_printf (&msg_buf, "[%s]", id);
+      else
+        obstack_sgrow (&msg_buf, id);
+      obstack_sgrow (&msg_buf, tail);
+
+      if (var->err & VARIANT_HIDDEN)
         {
-          if (is_warning)
-            warn_at_indent (var->loc, &indent, _("refers to: %c%s at %s"),
-                            dollar_or_at, var->id, at_spec);
+          obstack_printf (&msg_buf, _(", hiding %c"), dollar_or_at);
+          if (contains_dot_or_dash (var->id))
+            obstack_printf (&msg_buf, "[%s]", var->id);
           else
-            complain_at_indent (var->loc, &indent, _("refers to: %c%s at %s"),
-                                dollar_or_at, var->id, at_spec);
+            obstack_sgrow (&msg_buf, var->id);
+          obstack_sgrow (&msg_buf, tail);
         }
-      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_printf (&msg_buf, _("possibly meant: %c"), dollar_or_at);
-         if (contains_dot_or_dash (id))
-           obstack_printf (&msg_buf, "[%s]", id);
-         else
-           obstack_sgrow (&msg_buf, id);
-         obstack_sgrow (&msg_buf, tail);
-
-         if (var->err & VARIANT_HIDDEN)
-           {
-             obstack_printf (&msg_buf, _(", hiding %c"), dollar_or_at);
-             if (contains_dot_or_dash (var->id))
-               obstack_printf (&msg_buf, "[%s]", var->id);
-             else
-               obstack_sgrow (&msg_buf, var->id);
-             obstack_sgrow (&msg_buf, tail);
-           }
-
-         obstack_printf (&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_printf (&msg_buf, format, midrule_rhs_index);
-            }
 
-         obstack_1grow (&msg_buf, '\0');
-          if (is_warning)
-            warn_at_indent (id_loc, &indent, "%s",
-                            (char *) obstack_finish (&msg_buf));
-          else
-            complain_at_indent (id_loc, &indent, "%s",
-                                (char *) obstack_finish (&msg_buf));
-         obstack_free (&msg_buf, 0);
-       }
+      obstack_printf (&msg_buf, _(" at %s"), at_spec);
+
+      if (var->err & VARIANT_NOT_VISIBLE_FROM_MIDRULE)
+        obstack_printf (&msg_buf,
+                        _(", cannot be accessed from mid-rule action at $%d"),
+                        midrule_rhs_index);
+
+      complain_indent (&id_loc, warning, &indent, "%s",
+                        obstack_finish0 (&msg_buf));
+      obstack_free (&msg_buf, 0);
     }
 }
 
+static void
+show_sub_messages (warnings warning,
+                   const char* cp, bool explicit_bracketing,
+                   int midrule_rhs_index, char dollar_or_at,
+                   unsigned indent)
+{
+  unsigned i;
+
+  for (i = 0; i < variant_count; ++i)
+    show_sub_message (warning | silent,
+                      cp, explicit_bracketing,
+                      midrule_rhs_index, dollar_or_at,
+                      indent, &variant_table[i]);
+}
+
 /* Returned from "parse_ref" when the reference
    is inappropriate. */
 #define INVALID_REF (INT_MIN)
@@ -498,8 +406,8 @@ show_sub_messages (const char* cp, bool explicit_bracketing,
    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;
@@ -515,13 +423,13 @@ parse_ref (char *cp, symbol_list *rule, int rule_length,
     {
       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"),
-                       quote (text));
-         return INVALID_REF;
-       }
+        {
+          complain (&text_loc, complaint, _("integer out of range: %s"),
+                    quote (text));
+          return INVALID_REF;
+        }
     }
 
   if ('[' == *cp)
@@ -529,7 +437,7 @@ parse_ref (char *cp, symbol_list *rule, int rule_length,
       /* Ignore the brackets. */
       char *p;
       for (p = ++cp; *p != ']'; ++p)
-       continue;
+        continue;
       cp_end = p;
 
       explicit_bracketing = true;
@@ -539,13 +447,13 @@ parse_ref (char *cp, symbol_list *rule, int rule_length,
       /* 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;
@@ -558,17 +466,17 @@ parse_ref (char *cp, symbol_list *rule, int rule_length,
     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);
       }
   }
@@ -581,7 +489,7 @@ parse_ref (char *cp, symbol_list *rule, int rule_length,
 
       /* 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. */
@@ -607,37 +515,33 @@ parse_ref (char *cp, symbol_list *rule, int rule_length,
           cp_end - cp : ref_tail_fields - cp;
         unsigned indent = 0;
 
-        complain_at_indent (text_loc, &indent, _("invalid reference: %s"),
-                            quote (text));
+        complain_indent (&text_loc, complaint, &indent,
+                         _("invalid reference: %s"), quote (text));
         indent += SUB_INDENT;
         if (len == 0)
           {
             location sym_loc = text_loc;
             sym_loc.start.column += 1;
             sym_loc.end = sym_loc.start;
-            const char *format =
-              _("syntax error after '%c', expecting integer, letter,"
-                " '_', '[', or '$'");
-            complain_at_indent (sym_loc, &indent, format, dollar_or_at);
+            complain_indent (&sym_loc, complaint, &indent,
+                             _("syntax error after '%c', expecting integer, "
+                               "letter, '_', '[', or '$'"),
+                             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,
-                                midrule_rhs_index, len, cp);
-          }
+          complain_indent (&rule->location, complaint, &indent,
+                           _("symbol not found in production before $%d: "
+                             "%.*s"),
+                           midrule_rhs_index, len, cp);
         else
-          {
-            const char *format =
-              _("symbol not found in production: %.*s");
-            complain_at_indent (rule->location, &indent, format,
-                                len, cp);
-          }
+          complain_indent (&rule->location, complaint, &indent,
+                           _("symbol not found in production: %.*s"),
+                           len, cp);
 
         if (variant_count > 0)
-          show_sub_messages (cp, explicit_bracketing, midrule_rhs_index,
-                             dollar_or_at, false, indent);
+          show_sub_messages (complaint,
+                             cp, explicit_bracketing, midrule_rhs_index,
+                             dollar_or_at, indent);
         return INVALID_REF;
       }
     case 1:
@@ -645,10 +549,11 @@ parse_ref (char *cp, symbol_list *rule, int rule_length,
         unsigned indent = 0;
         if (variant_count > 1)
           {
-            warn_at_indent (text_loc, &indent, _("misleading reference: %s"),
-                            quote (text));
-            show_sub_messages (cp, explicit_bracketing, midrule_rhs_index,
-                               dollar_or_at, true, indent + SUB_INDENT);
+            complain_indent (&text_loc, Wother, &indent,
+                             _("misleading reference: %s"), quote (text));
+            show_sub_messages (Wother,
+                               cp, explicit_bracketing, midrule_rhs_index,
+                               dollar_or_at, indent + SUB_INDENT);
           }
         {
           unsigned symbol_index =
@@ -660,10 +565,11 @@ parse_ref (char *cp, symbol_list *rule, int rule_length,
     default:
       {
         unsigned indent = 0;
-        complain_at_indent (text_loc, &indent, _("ambiguous reference: %s"),
-                            quote (text));
-        show_sub_messages (cp, explicit_bracketing, midrule_rhs_index,
-                           dollar_or_at, false, indent + SUB_INDENT);
+        complain_indent (&text_loc, complaint, &indent,
+                         _("ambiguous reference: %s"), quote (text));
+        show_sub_messages (complaint,
+                           cp, explicit_bracketing, midrule_rhs_index,
+                           dollar_or_at, indent + SUB_INDENT);
         return INVALID_REF;
       }
     }
@@ -690,14 +596,16 @@ fetch_type_name (char *cp, char const **type_name,
   if (*cp == '<')
     {
       *type_name = ++cp;
-      while (*cp != '>')
-       ++cp;
+      /* Series of non-'>' or "->".  */
+      while (*cp != '>' || cp[-1] == '-')
+        ++cp;
 
       /* The '>' symbol will be later replaced by '\0'. Original
-        'text' is needed for error messages. */
+         'text' is needed for error messages. */
       ++cp;
       if (untyped_var_seen)
-       complain_at (dollar_loc, _("explicit type given in untyped grammar"));
+        complain (&dollar_loc, complaint,
+                  _("explicit type given in untyped grammar"));
       tag_seen = true;
     }
   return cp;
@@ -735,7 +643,7 @@ handle_action_dollar (symbol_list *rule, char *text, location dollar_loc)
   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, '$');
 
   /* End type_name. */
   if (type_name)
@@ -748,21 +656,22 @@ handle_action_dollar (symbol_list *rule, char *text, location dollar_loc)
 
     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 (&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"),
-                             quote (rule->content.sym->tag));
+                complain (&dollar_loc, complaint,
+                          _("$$ of %s has no declared type"),
+                          quote (rule->content.sym->tag));
             }
           else
             untyped_var_seen = true;
@@ -776,26 +685,27 @@ handle_action_dollar (symbol_list *rule, char *text, location dollar_loc)
 
     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 (&dollar_loc, complaint,
+                      _("$%s of %s has no declared type"), cp,
+                      quote (effective_rule->content.sym->tag));
           else
             untyped_var_seen = true;
         }
 
       obstack_printf (&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;
     }
 }
@@ -825,10 +735,10 @@ handle_action_at (symbol_list *rule, char *text, location at_loc)
       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:
@@ -840,7 +750,7 @@ handle_action_at (symbol_list *rule, char *text, location at_loc)
 
     default:
       obstack_printf (&obstack_for_string, "]b4_rhs_location(%d, %d)[",
-                     effective_rule_length, n);
+                      effective_rule_length, n);
       break;
     }
 }
@@ -883,43 +793,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
index 6bacac62ff9de95ab2f988fa1f0065ea69a9dae1..2b4fc67b484ad730814d63074a20c41c4cce8942 100644 (file)
@@ -1,3 +1,3 @@
 #include <config.h>
 #include "system.h"
-#include "scan-gram.c"
+#include "src/scan-gram.c"
index d78676e27d90b5dee1e647909b6c21a2e713340e..cf8b220d3a329479a700a8f912cf96b684882685 100644 (file)
@@ -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/>.  */
 
-%option debug nodefault noinput nounput noyywrap never-interactive
+%option debug nodefault noinput noyywrap never-interactive
 %option prefix="gram_" outfile="lex.yy.c"
 
 %{
 #define gram_wrap() 1
 
 #define FLEX_PREFIX(Id) gram_ ## Id
-#include "flex-scanner.h"
+#include <src/flex-scanner.h>
 
-#include "complain.h"
-#include "files.h"
-#include "gram.h"
-#include "quotearg.h"
-#include "reader.h"
-#include "uniqstr.h"
+#include <src/complain.h>
+#include <src/files.h>
+#include <src/getargs.h>
+#include <src/gram.h>
+#include <quotearg.h>
+#include <src/reader.h>
+#include <src/uniqstr.h>
 
 #include <c-ctype.h>
 #include <mbswidth.h>
 #include <quote.h>
 
-#include "scan-gram.h"
+#include <src/scan-gram.h>
 
 #define YY_DECL GRAM_LEX_DECL
 
-#define YY_USER_INIT                                   \
-   code_start = scanner_cursor = loc->start;           \
+#define YY_USER_INIT                                    \
+   code_start = scanner_cursor = loc->start;            \
 
 /* Location of scanner cursor.  */
 static boundary scanner_cursor;
@@ -55,12 +56,33 @@ static boundary scanner_cursor;
 static size_t no_cr_read (FILE *, char *, size_t);
 #define YY_INPUT(buf, result, size) ((result) = no_cr_read (yyin, buf, size))
 
+#define RETURN_PERCENT_PARAM(Value)                     \
+  RETURN_VALUE(PERCENT_PARAM, param, param_ ## Value)
+
+#define RETURN_PERCENT_FLAG(Value)                              \
+  RETURN_VALUE(PERCENT_FLAG, uniqstr, uniqstr_new (Value))
+
+#define RETURN_VALUE(Token, Field, Value)       \
+  do {                                          \
+    val->Field = Value;                         \
+    return Token;                               \
+  } while (0)
+
 #define ROLLBACK_CURRENT_TOKEN                                  \
   do {                                                          \
-    scanner_cursor.column -= mbsnwidth (yytext, yyleng, 0);    \
+    scanner_cursor.column -= mbsnwidth (yytext, yyleng, 0);     \
     yyless (0);                                                 \
   } while (0)
 
+#define DEPRECATED(Msg)                                         \
+  do {                                                          \
+    size_t i;                                                   \
+    deprecated_directive (loc, yytext, Msg);                    \
+    scanner_cursor.column -= mbsnwidth (Msg, strlen (Msg), 0);  \
+    for (i = strlen (Msg); i != 0; --i)                         \
+      unput (Msg[i - 1]);                                       \
+  } while (0)
+
 /* A string representing the most recently saved token.  */
 static char *last_string;
 
@@ -91,11 +113,19 @@ static void unexpected_newline (boundary, char const *);
     to capture the sequence 'identifier :'. */
 %x SC_AFTER_IDENTIFIER
 
- /* Three types of user code:
+ /* 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, as this simplifies our implementation.  We match
+    angle brackets in nested pairs: several languages use them for
+    generics/template types.  */
+%x SC_TAG
+
+ /* Four types of user code:
     - prologue (code between '%{' '%}' in the first section, before %%);
     - actions, printers, union, etc, (between braced in the middle section);
-    - epilogue (everything after the second %%). */
-%x SC_PROLOGUE SC_BRACED_CODE SC_EPILOGUE
+    - epilogue (everything after the second %%).
+    - predicate (code between '%?{' and '{' in middle section); */
+%x SC_PROLOGUE SC_BRACED_CODE SC_EPILOGUE SC_PREDICATE
  /* C and C++ comments in code. */
 %x SC_COMMENT SC_LINE_COMMENT
  /* Strings and characters in code. */
@@ -103,24 +133,24 @@ static void unexpected_newline (boundary, char const *);
  /* Bracketed identifiers support. */
 %x SC_BRACKETED_ID SC_RETURN_BRACKETED_ID
 
-letter    [.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_]
+letter    [.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_]
 notletter [^.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_]{-}[%\{]
-id       {letter}({letter}|[-0-9])*
-int      [0-9]+
-
-/* 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>]+
+id        {letter}({letter}|[-0-9])*
+int       [0-9]+
 
 /* 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)*
+
+/* An equal sign, with optional leading whitespaces. This is used in some
+   deprecated constructs. */
+eqopt    ([[:space:]]*=)?
 
 %%
 %{
-  /* Nesting level of the current code in braces.  */
-  int braces_level PACIFY_CC (= 0);
+  /* Nesting level.  Either for nested braces, or nested angle brackets
+     (but not mixed).  */
+  int nesting PACIFY_CC (= 0);
 
   /* Parent context state, when applicable.  */
   int context_state PACIFY_CC (= 0);
@@ -146,7 +176,9 @@ splice       (\\[ \f\t\v]*\n)*
 <INITIAL,SC_AFTER_IDENTIFIER,SC_BRACKETED_ID,SC_RETURN_BRACKETED_ID>
 {
   /* Comments and white space.  */
-  ","          warn_at (*loc, _("stray ',' treated as white space"));
+  "," {
+     complain (loc, Wother, _("stray ',' treated as white space"));
+  }
   [ \f\n\t\v]  |
   "//".*       continue;
   "/*" {
@@ -168,7 +200,7 @@ splice       (\\[ \f\t\v]*\n)*
   `----------------------------*/
 
   /* For directives that are also command line options, the regex must be
-       "%..."
+        "%..."
      after "[-_]"s are removed, and the directive must match the --long
      option name, with a single string argument.  Otherwise, add exceptions
      to ../build-aux/cross-options.pl.  */
@@ -177,56 +209,70 @@ splice     (\\[ \f\t\v]*\n)*
 {
   "%binary"                         return PERCENT_NONASSOC;
   "%code"                           return PERCENT_CODE;
-  "%debug"                          return PERCENT_DEBUG;
-  "%default"[-_]"prec"              return PERCENT_DEFAULT_PREC;
+  "%debug"                          RETURN_PERCENT_FLAG("parse.trace");
+  "%default-prec"                   return PERCENT_DEFAULT_PREC;
   "%define"                         return PERCENT_DEFINE;
   "%defines"                        return PERCENT_DEFINES;
   "%destructor"                     return PERCENT_DESTRUCTOR;
   "%dprec"                          return PERCENT_DPREC;
-  "%error"[-_]"verbose"             return PERCENT_ERROR_VERBOSE;
+  "%empty"                          return PERCENT_EMPTY;
+  "%error-verbose"                  return PERCENT_ERROR_VERBOSE;
   "%expect"                         return PERCENT_EXPECT;
-  "%expect"[-_]"rr"                 return PERCENT_EXPECT_RR;
+  "%expect-rr"                      return PERCENT_EXPECT_RR;
   "%file-prefix"                    return PERCENT_FILE_PREFIX;
-  "%fixed"[-_]"output"[-_]"files"   return PERCENT_YACC;
+  "%fixed-output-files"             return PERCENT_YACC;
   "%initial-action"                 return PERCENT_INITIAL_ACTION;
   "%glr-parser"                     return PERCENT_GLR_PARSER;
   "%language"                       return PERCENT_LANGUAGE;
   "%left"                           return PERCENT_LEFT;
-  "%lex-param"                      return PERCENT_LEX_PARAM;
-  "%locations"                      return PERCENT_LOCATIONS;
+  "%lex-param"                      RETURN_PERCENT_PARAM(lex);
+  "%locations"                      RETURN_PERCENT_FLAG("locations");
   "%merge"                          return PERCENT_MERGE;
-  "%name"[-_]"prefix"               return PERCENT_NAME_PREFIX;
-  "%no"[-_]"default"[-_]"prec"      return PERCENT_NO_DEFAULT_PREC;
-  "%no"[-_]"lines"                  return PERCENT_NO_LINES;
+  "%name-prefix"                    return PERCENT_NAME_PREFIX;
+  "%no-default-prec"                return PERCENT_NO_DEFAULT_PREC;
+  "%no-lines"                       return PERCENT_NO_LINES;
   "%nonassoc"                       return PERCENT_NONASSOC;
   "%nondeterministic-parser"        return PERCENT_NONDETERMINISTIC_PARSER;
   "%nterm"                          return PERCENT_NTERM;
   "%output"                         return PERCENT_OUTPUT;
-  "%parse-param"                    return PERCENT_PARSE_PARAM;
+  "%param"                          RETURN_PERCENT_PARAM(both);
+  "%parse-param"                    RETURN_PERCENT_PARAM(parse);
   "%prec"                           return PERCENT_PREC;
+  "%precedence"                     return PERCENT_PRECEDENCE;
   "%printer"                        return PERCENT_PRINTER;
-  "%pure"[-_]"parser"               return PERCENT_PURE_PARSER;
+  "%pure-parser"                    RETURN_PERCENT_FLAG("api.pure");
   "%require"                        return PERCENT_REQUIRE;
   "%right"                          return PERCENT_RIGHT;
   "%skeleton"                       return PERCENT_SKELETON;
   "%start"                          return PERCENT_START;
   "%term"                           return PERCENT_TOKEN;
   "%token"                          return PERCENT_TOKEN;
-  "%token"[-_]"table"               return PERCENT_TOKEN_TABLE;
+  "%token-table"                    return PERCENT_TOKEN_TABLE;
   "%type"                           return PERCENT_TYPE;
   "%union"                          return PERCENT_UNION;
   "%verbose"                        return PERCENT_VERBOSE;
   "%yacc"                           return PERCENT_YACC;
 
+  /* deprecated */
+  "%default"[-_]"prec"              DEPRECATED("%default-prec");
+  "%error"[-_]"verbose"             DEPRECATED("%define parse.error verbose");
+  "%expect"[-_]"rr"                 DEPRECATED("%expect-rr");
+  "%file-prefix"{eqopt}             DEPRECATED("%file-prefix");
+  "%fixed"[-_]"output"[-_]"files"   DEPRECATED("%fixed-output-files");
+  "%name"[-_]"prefix"{eqopt}        DEPRECATED("%name-prefix");
+  "%no"[-_]"default"[-_]"prec"      DEPRECATED("%no-default-prec");
+  "%no"[-_]"lines"                  DEPRECATED("%no-lines");
+  "%output"{eqopt}                  DEPRECATED("%output");
+  "%pure"[-_]"parser"               DEPRECATED("%pure-parser");
+  "%token"[-_]"table"               DEPRECATED("%token-table");
+
   "%"{id}|"%"{notletter}([[:graph:]])+ {
-    complain_at (*loc, _("invalid directive: %s"), quote (yytext));
+    complain (loc, complaint, _("invalid directive: %s"), quote (yytext));
   }
 
   "="                     return EQUAL;
   "|"                     return PIPE;
   ";"                     return SEMICOLON;
-  "<*>"                   return TYPE_TAG_ANY;
-  "<>"                    return TYPE_TAG_NONE;
 
   {id} {
     val->uniqstr = uniqstr_new (yytext);
@@ -247,14 +293,14 @@ splice     (\\[ \f\t\v]*\n)*
   /* Identifiers may not start with a digit.  Yet, don't silently
      accept "1FOO" as "1 FOO".  */
   {int}{id} {
-    complain_at (*loc, _("invalid identifier: %s"), quote (yytext));
+    complain (loc, complaint, _("invalid identifier: %s"), quote (yytext));
   }
 
   /* Characters.  */
-  "'"        token_start = loc->start; BEGIN SC_ESCAPED_CHARACTER;
+  "'"         token_start = loc->start; BEGIN SC_ESCAPED_CHARACTER;
 
   /* Strings. */
-  "\""       token_start = loc->start; BEGIN SC_ESCAPED_STRING;
+  "\""        token_start = loc->start; BEGIN SC_ESCAPED_STRING;
 
   /* Prologue. */
   "%{"        code_start = loc->start; BEGIN SC_PROLOGUE;
@@ -262,18 +308,25 @@ splice     (\\[ \f\t\v]*\n)*
   /* Code in between braces.  */
   "{" {
     STRING_GROW;
-    braces_level = 0;
+    nesting = 0;
     code_start = loc->start;
     BEGIN SC_BRACED_CODE;
   }
 
+  /* Semantic predicate. */
+  "%?"[ \f\n\t\v]*"{" {
+    nesting = 0;
+    code_start = loc->start;
+    BEGIN SC_PREDICATE;
+  }
+
   /* A type. */
-  "<"{tag}">" {
-    obstack_grow (&obstack_for_string, yytext + 1, yyleng - 2);
-    STRING_FINISH;
-    val->uniqstr = uniqstr_new (last_string);
-    STRING_FREE;
-    return TYPE;
+  "<*>"       return TAG_ANY;
+  "<>"        return TAG_NONE;
+  "<"         {
+    nesting = 0;
+    token_start = loc->start;
+    BEGIN SC_TAG;
   }
 
   "%%" {
@@ -291,9 +344,9 @@ splice       (\\[ \f\t\v]*\n)*
   }
 
   [^\[%A-Za-z0-9_<>{}\"\'*;|=/, \f\n\t\v]+|. {
-    complain_at (*loc, "%s: %s",
-                 ngettext ("invalid character", "invalid characters", yyleng),
-                 quote_mem (yytext, yyleng));
+    complain (loc, complaint, "%s: %s",
+              ngettext ("invalid character", "invalid characters", yyleng),
+              quote_mem (yytext, yyleng));
   }
 
   <<EOF>> {
@@ -303,6 +356,17 @@ splice      (\\[ \f\t\v]*\n)*
 }
 
 
+  /*--------------------------------------------------------------.
+  | Supporting \0 complexifies our implementation for no expected |
+  | added value.                                                  |
+  `--------------------------------------------------------------*/
+
+<SC_ESCAPED_CHARACTER,SC_ESCAPED_STRING,SC_TAG>
+{
+  \0        complain (loc, complaint, _("invalid null character"));
+}
+
+
   /*-----------------------------------------------------------------.
   | Scanning after an identifier, checking whether a colon is next.  |
   `-----------------------------------------------------------------*/
@@ -312,16 +376,16 @@ splice     (\\[ \f\t\v]*\n)*
   "[" {
     if (bracketed_id_str)
       {
-       ROLLBACK_CURRENT_TOKEN;
-       BEGIN SC_RETURN_BRACKETED_ID;
-       *loc = id_loc;
-       return ID;
+        ROLLBACK_CURRENT_TOKEN;
+        BEGIN SC_RETURN_BRACKETED_ID;
+        *loc = id_loc;
+        return ID;
       }
     else
       {
-       bracketed_id_start = loc->start;
-       bracketed_id_context_state = YY_START;
-       BEGIN SC_BRACKETED_ID;
+        bracketed_id_start = loc->start;
+        bracketed_id_context_state = YY_START;
+        BEGIN SC_BRACKETED_ID;
       }
   }
   ":" {
@@ -351,36 +415,37 @@ splice     (\\[ \f\t\v]*\n)*
   {id} {
     if (bracketed_id_str)
       {
-       complain_at (*loc, _("unexpected identifier in bracketed name: %s"),
-                    quote (yytext));
+        complain (loc, complaint,
+                  _("unexpected identifier in bracketed name: %s"),
+                  quote (yytext));
       }
     else
       {
-       bracketed_id_str = uniqstr_new (yytext);
-       bracketed_id_loc = *loc;
+        bracketed_id_str = uniqstr_new (yytext);
+        bracketed_id_loc = *loc;
       }
   }
   "]" {
     BEGIN bracketed_id_context_state;
     if (bracketed_id_str)
       {
-       if (INITIAL == bracketed_id_context_state)
-         {
-           val->uniqstr = bracketed_id_str;
-           bracketed_id_str = 0;
-           *loc = bracketed_id_loc;
-           return BRACKETED_ID;
-         }
+        if (INITIAL == bracketed_id_context_state)
+          {
+            val->uniqstr = bracketed_id_str;
+            bracketed_id_str = 0;
+            *loc = bracketed_id_loc;
+            return BRACKETED_ID;
+          }
       }
     else
-      complain_at (*loc, _("an identifier expected"));
+      complain (loc, complaint, _("an identifier expected"));
   }
 
   [^\].A-Za-z0-9_/ \f\n\t\v]+|. {
-    complain_at (*loc, "%s: %s",
-                 ngettext ("invalid character in bracketed name",
-                           "invalid characters in bracketed name", yyleng),
-                 quote_mem (yytext, yyleng));
+    complain (loc, complaint, "%s: %s",
+              ngettext ("invalid character in bracketed name",
+                        "invalid characters in bracketed name", yyleng),
+              quote_mem (yytext, yyleng));
   }
 
   <<EOF>> {
@@ -409,7 +474,7 @@ splice       (\\[ \f\t\v]*\n)*
 <SC_YACC_COMMENT>
 {
   "*/"     BEGIN context_state;
-  .|\n    continue;
+  .|\n     continue;
   <<EOF>>  unexpected_eof (token_start, "*/"); BEGIN context_state;
 }
 
@@ -421,7 +486,7 @@ splice       (\\[ \f\t\v]*\n)*
 <SC_COMMENT>
 {
   "*"{splice}"/"  STRING_GROW; BEGIN context_state;
-  <<EOF>>        unexpected_eof (token_start, "*/"); BEGIN context_state;
+  <<EOF>>         unexpected_eof (token_start, "*/"); BEGIN context_state;
 }
 
 
@@ -431,9 +496,9 @@ splice       (\\[ \f\t\v]*\n)*
 
 <SC_LINE_COMMENT>
 {
-  "\n"          STRING_GROW; BEGIN context_state;
-  {splice}      STRING_GROW;
-  <<EOF>>       BEGIN context_state;
+  "\n"           STRING_GROW; BEGIN context_state;
+  {splice}       STRING_GROW;
+  <<EOF>>        BEGIN context_state;
 }
 
 
@@ -444,80 +509,74 @@ splice     (\\[ \f\t\v]*\n)*
 
 <SC_ESCAPED_STRING>
 {
-  "\""|"\n" {
-    if (yytext[0] == '\n')
-      unexpected_newline (token_start, "\"");
-    STRING_FINISH;
-    loc->start = token_start;
-    val->chars = last_string;
-    BEGIN INITIAL;
-    return STRING;
-  }
-  <<EOF>> {
-    unexpected_eof (token_start, "\"");
+  "\"" {
     STRING_FINISH;
     loc->start = token_start;
     val->chars = last_string;
     BEGIN INITIAL;
     return STRING;
   }
+  <<EOF>>   unexpected_eof (token_start, "\"");
+  "\n"      unexpected_newline (token_start, "\"");
 }
 
   /*----------------------------------------------------------.
   | Scanning a Bison character literal, decoding its escapes. |
-  | The initial quote is already eaten.                              |
+  | The initial quote is already eaten.                       |
   `----------------------------------------------------------*/
 
 <SC_ESCAPED_CHARACTER>
 {
-  "'"|"\n" {
-    STRING_FINISH;
-    loc->start = token_start;
-    val->character = last_string[0];
-    {
-      /* FIXME: Eventually, make these errors.  */
-      if (last_string[0] == '\0')
-        {
-          warn_at (*loc, _("empty character literal"));
-          /* '\0' seems dangerous even if we are about to complain.  */
-          val->character = '\'';
-        }
-      else if (last_string[1] != '\0')
-        warn_at (*loc, _("extra characters in character literal"));
-    }
-    if (yytext[0] == '\n')
-      unexpected_newline (token_start, "'");
-    STRING_FREE;
-    BEGIN INITIAL;
-    return CHAR;
-  }
-  <<EOF>> {
+  "'" {
     STRING_FINISH;
     loc->start = token_start;
     val->character = last_string[0];
+
+    /* FIXME: Eventually, make these errors.  */
+    if (last_string[0] == '\0')
     {
-      /* FIXME: Eventually, make these errors.  */
-      if (last_string[0] == '\0')
-        {
-          warn_at (*loc, _("empty character literal"));
-          /* '\0' seems dangerous even if we are about to complain.  */
-          val->character = '\'';
-        }
-      else if (last_string[1] != '\0')
-        warn_at (*loc, _("extra characters in character literal"));
+      complain (loc, Wother, _("empty character literal"));
+      /* '\0' seems dangerous even if we are about to complain.  */
+      val->character = '\'';
     }
-    unexpected_eof (token_start, "'");
+    else if (last_string[1] != '\0')
+      complain (loc, Wother,
+                _("extra characters in character literal"));
     STRING_FREE;
     BEGIN INITIAL;
     return CHAR;
   }
+  "\n"      unexpected_newline (token_start, "'");
+  <<EOF>>   unexpected_eof (token_start, "'");
 }
 
-<SC_ESCAPED_CHARACTER,SC_ESCAPED_STRING>
+
+
+  /*--------------------------------------------------------------.
+  | Scanning a tag.  The initial angle bracket is already eaten.  |
+  `--------------------------------------------------------------*/
+
+<SC_TAG>
 {
-  \0       complain_at (*loc, _("invalid null character"));
-}
+  ">" {
+    --nesting;
+    if (nesting < 0)
+      {
+        STRING_FINISH;
+        loc->start = token_start;
+        val->uniqstr = uniqstr_new (last_string);
+        STRING_FREE;
+        BEGIN INITIAL;
+        return TAG;
+      }
+    STRING_GROW;
+  }
+
+  ([^<>]|->)+ STRING_GROW;
+  "<"+   STRING_GROW; nesting += yyleng;
 
+  <<EOF>>   unexpected_eof (token_start, ">");
+}
 
   /*----------------------------.
   | Decode escaped characters.  |
@@ -528,7 +587,7 @@ splice       (\\[ \f\t\v]*\n)*
   \\[0-7]{1,3} {
     unsigned long int c = strtoul (yytext + 1, NULL, 8);
     if (!c || UCHAR_MAX < c)
-      complain_at (*loc, _("invalid number after \\-escape: %s"),
+      complain (loc, complaint, _("invalid number after \\-escape: %s"),
                    yytext+1);
     else
       obstack_1grow (&obstack_for_string, c);
@@ -538,19 +597,19 @@ splice     (\\[ \f\t\v]*\n)*
     verify (UCHAR_MAX < ULONG_MAX);
     unsigned long int c = strtoul (yytext + 2, NULL, 16);
     if (!c || UCHAR_MAX < c)
-      complain_at (*loc, _("invalid number after \\-escape: %s"),
+      complain (loc, complaint, _("invalid number after \\-escape: %s"),
                    yytext+1);
     else
       obstack_1grow (&obstack_for_string, c);
   }
 
-  \\a  obstack_1grow (&obstack_for_string, '\a');
-  \\b  obstack_1grow (&obstack_for_string, '\b');
-  \\f  obstack_1grow (&obstack_for_string, '\f');
-  \\n  obstack_1grow (&obstack_for_string, '\n');
-  \\r  obstack_1grow (&obstack_for_string, '\r');
-  \\t  obstack_1grow (&obstack_for_string, '\t');
-  \\v  obstack_1grow (&obstack_for_string, '\v');
+  \\a   obstack_1grow (&obstack_for_string, '\a');
+  \\b   obstack_1grow (&obstack_for_string, '\b');
+  \\f   obstack_1grow (&obstack_for_string, '\f');
+  \\n   obstack_1grow (&obstack_for_string, '\n');
+  \\r   obstack_1grow (&obstack_for_string, '\r');
+  \\t   obstack_1grow (&obstack_for_string, '\t');
+  \\v   obstack_1grow (&obstack_for_string, '\v');
 
   /* \\[\"\'?\\] would be shorter, but it confuses xgettext.  */
   \\("\""|"'"|"?"|"\\")  obstack_1grow (&obstack_for_string, yytext[1]);
@@ -558,19 +617,20 @@ splice     (\\[ \f\t\v]*\n)*
   \\(u|U[0-9abcdefABCDEF]{4})[0-9abcdefABCDEF]{4} {
     int c = convert_ucn_to_byte (yytext);
     if (c <= 0)
-      complain_at (*loc, _("invalid number after \\-escape: %s"),
+      complain (loc, complaint, _("invalid number after \\-escape: %s"),
                    yytext+1);
     else
       obstack_1grow (&obstack_for_string, c);
   }
-  \\(.|\n)     {
+  \\(.|\n)      {
     char const *p = yytext + 1;
     /* Quote only if escaping won't make the character visible.  */
     if (c_isspace ((unsigned char) *p) && c_isprint ((unsigned char) *p))
       p = quote (p);
     else
       p = quotearg_style_mem (escape_quoting_style, p, 1);
-    complain_at (*loc, _("invalid character after \\-escape: %s"), p);
+    complain (loc, complaint, _("invalid character after \\-escape: %s"),
+                 p);
   }
 }
 
@@ -580,21 +640,21 @@ splice     (\\[ \f\t\v]*\n)*
 
 <SC_CHARACTER,SC_STRING>
 {
-  {splice}|\\{splice}[^\n\[\]] STRING_GROW;
+  {splice}|\\{splice}[^\n\[\]]  STRING_GROW;
 }
 
 <SC_CHARACTER>
 {
-  "'"          STRING_GROW; BEGIN context_state;
-  \n           unexpected_newline (token_start, "'"); BEGIN context_state;
-  <<EOF>>      unexpected_eof (token_start, "'"); BEGIN context_state;
+  "'"           STRING_GROW; BEGIN context_state;
+  \n            unexpected_newline (token_start, "'");
+  <<EOF>>       unexpected_eof (token_start, "'");
 }
 
 <SC_STRING>
 {
-  "\""         STRING_GROW; BEGIN context_state;
-  \n           unexpected_newline (token_start, "\""); BEGIN context_state;
-  <<EOF>>      unexpected_eof (token_start, "\""); BEGIN context_state;
+  "\""          STRING_GROW; BEGIN context_state;
+  \n            unexpected_newline (token_start, "\"");
+  <<EOF>>       unexpected_eof (token_start, "\"");
 }
 
 
@@ -602,7 +662,7 @@ splice       (\\[ \f\t\v]*\n)*
   | Strings, comments etc. can be found in user code.  |
   `---------------------------------------------------*/
 
-<SC_BRACED_CODE,SC_PROLOGUE,SC_EPILOGUE>
+<SC_BRACED_CODE,SC_PROLOGUE,SC_EPILOGUE,SC_PREDICATE>
 {
   "'" {
     STRING_GROW;
@@ -632,43 +692,56 @@ splice     (\\[ \f\t\v]*\n)*
 
 
   /*-----------------------------------------------------------.
-  | Scanning some code in braces (actions). The initial "{" is |
-  | already eaten.                                             |
+  | Scanning some code in braces (actions, predicates). The    |
+  | initial "{" is already eaten.                              |
   `-----------------------------------------------------------*/
 
+<SC_BRACED_CODE,SC_PREDICATE>
+{
+  "{"|"<"{splice}"%"  STRING_GROW; nesting++;
+  "%"{splice}">"      STRING_GROW; nesting--;
+
+  /* Tokenize '<<%' correctly (as '<<' '%') rather than incorrrectly
+     (as '<' '<%').  */
+  "<"{splice}"<"  STRING_GROW;
+
+  <<EOF>>   unexpected_eof (code_start, "}");
+}
+
 <SC_BRACED_CODE>
 {
-  "{"|"<"{splice}"%"  STRING_GROW; braces_level++;
-  "%"{splice}">"      STRING_GROW; braces_level--;
   "}" {
     obstack_1grow (&obstack_for_string, '}');
 
-    --braces_level;
-    if (braces_level < 0)
+    --nesting;
+    if (nesting < 0)
       {
-       STRING_FINISH;
-       loc->start = code_start;
-       val->code = last_string;
-       BEGIN INITIAL;
-       return BRACED_CODE;
+        STRING_FINISH;
+        loc->start = code_start;
+        val->code = last_string;
+        BEGIN INITIAL;
+        return BRACED_CODE;
       }
   }
+}
 
-  /* Tokenize '<<%' correctly (as '<<' '%') rather than incorrrectly
-     (as '<' '<%').  */
-  "<"{splice}"<"  STRING_GROW;
-
-  <<EOF>> {
-    unexpected_eof (code_start, "}");
-    STRING_FINISH;
-    loc->start = code_start;
-    val->code = last_string;
-    BEGIN INITIAL;
-    return BRACED_CODE;
+<SC_PREDICATE>
+{
+  "}" {
+    --nesting;
+    if (nesting < 0)
+      {
+        STRING_FINISH;
+        loc->start = code_start;
+        val->code = last_string;
+        BEGIN INITIAL;
+        return BRACED_PREDICATE;
+      }
+    else
+      obstack_1grow (&obstack_for_string, '}');
   }
 }
 
-
   /*--------------------------------------------------------------.
   | Scanning some prologue: from "%{" (already scanned) to "%}".  |
   `--------------------------------------------------------------*/
@@ -683,14 +756,7 @@ splice      (\\[ \f\t\v]*\n)*
     return PROLOGUE;
   }
 
-  <<EOF>> {
-    unexpected_eof (code_start, "%}");
-    STRING_FINISH;
-    loc->start = code_start;
-    val->chars = last_string;
-    BEGIN INITIAL;
-    return PROLOGUE;
-  }
+  <<EOF>>   unexpected_eof (code_start, "%}");
 }
 
 
@@ -715,8 +781,8 @@ splice       (\\[ \f\t\v]*\n)*
   | By default, grow the string obstack with the input.  |
   `-----------------------------------------------------*/
 
-<SC_COMMENT,SC_LINE_COMMENT,SC_BRACED_CODE,SC_PROLOGUE,SC_EPILOGUE,SC_STRING,SC_CHARACTER,SC_ESCAPED_STRING,SC_ESCAPED_CHARACTER>.     |
-<SC_COMMENT,SC_LINE_COMMENT,SC_BRACED_CODE,SC_PROLOGUE,SC_EPILOGUE>\n  STRING_GROW;
+<SC_COMMENT,SC_LINE_COMMENT,SC_BRACED_CODE,SC_PREDICATE,SC_PROLOGUE,SC_EPILOGUE,SC_STRING,SC_CHARACTER,SC_ESCAPED_STRING,SC_ESCAPED_CHARACTER>. |
+  <SC_COMMENT,SC_LINE_COMMENT,SC_BRACED_CODE,SC_PREDICATE,SC_PROLOGUE,SC_EPILOGUE>\n    STRING_GROW;
 
 %%
 
@@ -732,35 +798,35 @@ no_cr_read (FILE *fp, char *buf, size_t size)
     {
       char *w = memchr (buf, '\r', bytes_read);
       if (w)
-       {
-         char const *r = ++w;
-         char const *lim = buf + bytes_read;
-
-         for (;;)
-           {
-             /* Found an '\r'.  Treat it like '\n', but ignore any
-                '\n' that immediately follows.  */
-             w[-1] = '\n';
-             if (r == lim)
-               {
-                 int ch = getc (fp);
-                 if (ch != '\n' && ungetc (ch, fp) != ch)
-                   break;
-               }
-             else if (*r == '\n')
-               r++;
-
-             /* Copy until the next '\r'.  */
-             do
-               {
-                 if (r == lim)
-                   return w - buf;
-               }
-             while ((*w++ = *r++) != '\r');
-           }
-
-         return w - buf;
-       }
+        {
+          char const *r = ++w;
+          char const *lim = buf + bytes_read;
+
+          for (;;)
+            {
+              /* Found an '\r'.  Treat it like '\n', but ignore any
+                 '\n' that immediately follows.  */
+              w[-1] = '\n';
+              if (r == lim)
+                {
+                  int ch = getc (fp);
+                  if (ch != '\n' && ungetc (ch, fp) != ch)
+                    break;
+                }
+              else if (*r == '\n')
+                r++;
+
+              /* Copy until the next '\r'.  */
+              do
+                {
+                  if (r == lim)
+                    return w - buf;
+                }
+              while ((*w++ = *r++) != '\r');
+            }
+
+          return w - buf;
+        }
     }
 
   return bytes_read;
@@ -780,7 +846,8 @@ scan_integer (char const *number, int base, location loc)
 
   if (INT_MAX < num)
     {
-      complain_at (loc, _("integer out of range: %s"), quote (number));
+      complain (&loc, complaint, _("integer out of range: %s"),
+                   quote (number));
       num = INT_MAX;
     }
 
@@ -791,7 +858,7 @@ scan_integer (char const *number, int base, location loc)
 /*------------------------------------------------------------------.
 | Convert universal character name UCN to a single-byte character,  |
 | and return that character.  Return -1 if UCN does not correspond  |
-| to a single-byte character.                                      |
+| to a single-byte character.                                       |
 `------------------------------------------------------------------*/
 
 static int
@@ -819,22 +886,22 @@ convert_ucn_to_byte (char const *ucn)
        about.  */
     static signed char const table[] =
       {
-       '\0',   -1,   -1,   -1,   -1,   -1,   -1, '\a',
-       '\b', '\t', '\n', '\v', '\f', '\r',   -1,   -1,
-         -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
-         -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
-        ' ',  '!',  '"',  '#',  '$',  '%',  '&', '\'',
-        '(',  ')',  '*',  '+',  ',',  '-',  '.',  '/',
-        '0',  '1',  '2',  '3',  '4',  '5',  '6',  '7',
-        '8',  '9',  ':',  ';',  '<',  '=',  '>',  '?',
-        '@',  'A',  'B',  'C',  'D',  'E',  'F',  'G',
-        'H',  'I',  'J',  'K',  'L',  'M',  'N',  'O',
-        'P',  'Q',  'R',  'S',  'T',  'U',  'V',  'W',
-        'X',  'Y',  'Z',  '[', '\\',  ']',  '^',  '_',
-        '`',  'a',  'b',  'c',  'd',  'e',  'f',  'g',
-        'h',  'i',  'j',  'k',  'l',  'm',  'n',  'o',
-        'p',  'q',  'r',  's',  't',  'u',  'v',  'w',
-        'x',  'y',  'z',  '{',  '|',  '}',  '~'
+        '\0',   -1,   -1,   -1,   -1,   -1,   -1, '\a',
+        '\b', '\t', '\n', '\v', '\f', '\r',   -1,   -1,
+          -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+          -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+         ' ',  '!',  '"',  '#',  '$',  '%',  '&', '\'',
+         '(',  ')',  '*',  '+',  ',',  '-',  '.',  '/',
+         '0',  '1',  '2',  '3',  '4',  '5',  '6',  '7',
+         '8',  '9',  ':',  ';',  '<',  '=',  '>',  '?',
+         '@',  'A',  'B',  'C',  'D',  'E',  'F',  'G',
+         'H',  'I',  'J',  'K',  'L',  'M',  'N',  'O',
+         'P',  'Q',  'R',  'S',  'T',  'U',  'V',  'W',
+         'X',  'Y',  'Z',  '[', '\\',  ']',  '^',  '_',
+         '`',  'a',  'b',  'c',  'd',  'e',  'f',  'g',
+         'h',  'i',  'j',  'k',  'l',  'm',  'n',  'o',
+         'p',  'q',  'r',  's',  't',  'u',  'v',  'w',
+         'x',  'y',  'z',  '{',  '|',  '}',  '~'
       };
 
     code = code < sizeof table ? table[code] : -1;
@@ -856,14 +923,14 @@ handle_syncline (char *args, location loc)
   unsigned long int lineno = strtoul (args, &file, 10);
   if (INT_MAX <= lineno)
     {
-      warn_at (loc, _("line number overflow"));
+      complain (&loc, Wother, _("line number overflow"));
       lineno = INT_MAX;
     }
 
-  file = mbschr (file, '"');
+  file = strchr (file, '"');
   if (file)
     {
-      *mbschr (file + 1, '"') = '\0';
+      *strchr (file + 1, '"') = '\0';
       current_file = uniqstr_new (file + 1);
     }
   boundary_set (&scanner_cursor, current_file, lineno, 1);
@@ -872,8 +939,8 @@ handle_syncline (char *args, location loc)
 
 /*----------------------------------------------------------------.
 | For a token or comment starting at START, report message MSGID, |
-| which should say that an end marker was found before           |
-| the expected TOKEN_END.                                        |
+| which should say that an end marker was found before the        |
+| expected TOKEN_END. Then, pretend that TOKEN_END was found.     |
 `----------------------------------------------------------------*/
 
 static void
@@ -882,17 +949,27 @@ unexpected_end (boundary start, char const *msgid, char const *token_end)
   location loc;
   loc.start = start;
   loc.end = scanner_cursor;
+  size_t i = strlen (token_end);
+
+/* Adjust scanner cursor so that any later message does not count
+     the characters about to be inserted.  */
+  scanner_cursor.column -= i;
+
+  while (i != 0)
+    unput (token_end[--i]);
+
   token_end = quote (token_end);
   /* Instead of '\'', display "'".  */
-  if (!strcmp (token_end, "'\\''"))
+  if (STREQ (token_end, "'\\''"))
     token_end = "\"'\"";
-  complain_at (loc, _(msgid), token_end);
+  complain (&loc, complaint, _(msgid), token_end);
 }
 
 
 /*------------------------------------------------------------------------.
 | Report an unexpected EOF in a token or comment starting at START.       |
 | An end of file was encountered and the expected TOKEN_END was missing.  |
+| After reporting the problem, pretend that TOKEN_END was found.          |
 `------------------------------------------------------------------------*/
 
 static void
index fb1aea61398e1b5d00ffd87720536bd1944ebaf3..3e1e73deb0fbfa4b915c69280de827d013753fd3 100644 (file)
@@ -1,3 +1,3 @@
 #include <config.h>
 #include "system.h"
-#include "scan-skel.c"
+#include "src/scan-skel.c"
index 715971a6b95e17909729050350f581ef8dfb365e..654491ef78ec308e2b1a20ea1f2a9ba40f360d85 100644 (file)
@@ -1,6 +1,6 @@
 /* Scan Bison Skeletons.                                       -*- C -*-
 
-   Copyright (C) 2001-2007, 2009-2013 Free Software Foundation, Inc.
+   Copyright (C) 2001-2013 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;
 
-#define QPUTS(String) \
-   fputs (quotearg_style (c_quoting_style, String), yyout)
-
-static void at_directive_perform (int at_directive_argc,
-                                  char *at_directive_argv[],
-                                  char **outnamep, int *out_linenop);
+typedef void (*at_directive)(int, char**, char **, int*);
+static void at_init (int *argc, char *argv[], at_directive *at_ptr, at_directive fun);
+static void at_basename (int argc, char *argv[], char**, int*);
+static void at_complain (int argc, char *argv[], char**, int*);
+static void at_output (int argc, char *argv[], char **name, int *lineno);
 static void fail_for_at_directive_too_many_args (char const *at_directive_name);
 static void fail_for_at_directive_too_few_args (char const *at_directive_name);
 static void fail_for_invalid_at (char const *at);
@@ -59,42 +58,39 @@ static void fail_for_invalid_at (char const *at);
 
 %{
   int out_lineno PACIFY_CC (= 0);
-  char *outname = NULL;
-
-  /* Currently, only the @warn, @complain, @fatal, @warn_at, @complain_at, and
-     @fatal_at directives take multiple arguments, and the last three already
-     can't take more than 7.  at_directive_argv[0] is the directive name.  */
-  #define AT_DIRECTIVE_ARGC_MAX 8
-  int at_directive_argc = 0;
-  char *at_directive_argv[AT_DIRECTIVE_ARGC_MAX];
+  char *out_name = NULL;
+
+  /* Currently, only the @complain directive takes multiple arguments, and
+     never more than 7, with argv[0] being the directive name and argv[1]
+     being the type of complaint to dispatch. */
+#define ARGC_MAX 9
+  int argc = 0;
+  char *argv[ARGC_MAX];
+  at_directive at_ptr = NULL;
 %}
 
 "@@" fputc ('@', yyout);
 "@{" fputc ('[', yyout);
 "@}" fputc (']', yyout);
-"@`" continue;  /* Used by b4_cat in ../data/bison.m4.  */
+"@'" continue;  /* Used by b4_cat in ../data/bison.m4.  */
 @\n  continue;
 
 "@oline@"  fprintf (yyout, "%d", out_lineno + 1);
-"@ofile@"  QPUTS (outname);
+"@ofile@"  fputs (quotearg_style (c_quoting_style, out_name), yyout);
 
-@[a-z_]+"(" {
-  yytext[yyleng-1] = '\0';
-  obstack_grow (&obstack_for_string, yytext, yyleng);
-  at_directive_argv[at_directive_argc++] =
-    obstack_finish (&obstack_for_string);
-  BEGIN SC_AT_DIRECTIVE_ARGS;
-}
+"@basename("    at_init (&argc, argv, &at_ptr, &at_basename);
+"@complain("    at_init (&argc, argv, &at_ptr, &at_complain);
+"@output("      at_init (&argc, argv, &at_ptr, &at_output);
 
   /* 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>> {
-  if (outname)
+  if (out_name)
     {
-      free (outname);
+      free (out_name);
       xfclose (yyout);
     }
   return EOF;
@@ -107,26 +103,24 @@ static void fail_for_invalid_at (char const *at);
   "@@"   obstack_1grow (&obstack_for_string, '@');
   "@{"   obstack_1grow (&obstack_for_string, '[');
   "@}"   obstack_1grow (&obstack_for_string, ']');
-  "@`"   continue; /* For starting an argument that begins with whitespace. */
+  "@'"   continue; /* For starting an argument that begins with whitespace. */
   @\n    continue;
 
   @[,)] {
-    if (at_directive_argc >= AT_DIRECTIVE_ARGC_MAX)
-      fail_for_at_directive_too_many_args (at_directive_argv[0]);
+    if (argc >= ARGC_MAX)
+      fail_for_at_directive_too_many_args (argv[0]);
 
-    obstack_1grow (&obstack_for_string, '\0');
-    at_directive_argv[at_directive_argc++] =
-      obstack_finish (&obstack_for_string);
+    argv[argc++] = obstack_finish0 (&obstack_for_string);
 
     /* Like M4, skip whitespace after a comma.  */
     if (yytext[1] == ',')
       BEGIN SC_AT_DIRECTIVE_SKIP_WS;
     else
       {
-        at_directive_perform (at_directive_argc, at_directive_argv,
-                              &outname, &out_lineno);
-        obstack_free (&obstack_for_string, at_directive_argv[0]);
-        at_directive_argc = 0;
+        aver (at_ptr);
+        at_ptr (argc, argv, &out_name, &out_lineno);
+        obstack_free (&obstack_for_string, argv[0]);
+        argc = 0;
         BEGIN INITIAL;
       }
   }
@@ -137,18 +131,26 @@ static void fail_for_invalid_at (char const *at);
 <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>
 {
-  <<EOF>> {
-    fatal (_("unclosed %s directive in skeleton"), at_directive_argv[0]);
-  }
+  <<EOF>>  complain (NULL, fatal, _("unclosed %s directive in skeleton"), argv[0]);
 }
 
 %%
 
+static void
+at_init (int *argc, char *argv[], at_directive *at_ptr, at_directive fun)
+{
+  *at_ptr = fun;
+  yytext[yyleng-1] = '\0';
+  obstack_grow (&obstack_for_string, yytext, yyleng);
+  argv[(*argc)++] = obstack_finish (&obstack_for_string);
+  BEGIN SC_AT_DIRECTIVE_ARGS;
+}
+
 /*------------------------.
 | Scan a Bison skeleton.  |
 `------------------------*/
@@ -175,132 +177,92 @@ skel_scanner_free (void)
   yylex_destroy ();
 }
 
+static inline warnings
+flag (const char *arg)
+{
+  /* compare with values issued from b4_error */
+  if (STREQ (arg, "complain"))
+    return complaint;
+  else if (STREQ (arg, "fatal"))
+    return fatal;
+  else if (STREQ (arg, "note"))
+    return silent | complaint | no_caret;
+  else if (STREQ (arg, "warn"))
+    return Wother;
+  else
+    aver (false);
+}
+
 static void
-at_directive_perform (int at_directive_argc,
-                      char *at_directive_argv[],
-                      char **outnamep, int *out_linenop)
+at_basename (int argc, char *argv[], char **out_namep, int *out_linenop)
 {
-  if (0 == strcmp (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"))
-    {
-      void (*func)(char const *, ...);
-      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;
-        }
-      switch (at_directive_argc)
-        {
-          case 2:
-            func (_(at_directive_argv[1]));
-            break;
-          case 3:
-            func (_(at_directive_argv[1]), at_directive_argv[2]);
-            break;
-          case 4:
-            func (_(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]);
-            break;
-          case 6:
-            func (_(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"))
+  (void) out_namep;
+  (void) out_linenop;
+  if (2 < argc)
+    fail_for_at_directive_too_many_args (argv[0]);
+  fputs (last_component (argv[1]), yyout);
+}
+
+static void
+at_complain (int argc, char *argv[], char **out_namep, int *out_linenop)
+{
+  static unsigned indent;
+  warnings w = flag (argv[1]);
+  location loc;
+  location *locp = NULL;
+
+  (void) out_namep;
+  (void) out_linenop;
+
+  if (argc < 4)
+    fail_for_at_directive_too_few_args (argv[0]);
+  if (argv[2] && argv[2][0])
     {
-      void (*func)(location, char const *, ...);
-      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;
-        }
-      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]));
-            break;
-          case 5:
-            func (loc, _(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]);
-            break;
-          case 7:
-            func (loc, _(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]);
-            break;
-          default:
-            fail_for_at_directive_too_many_args (at_directive_argv[0]);
-            break;
-        }
+      boundary_set_from_string (&loc.start, argv[2]);
+      boundary_set_from_string (&loc.end, argv[3]);
+      locp = &loc;
     }
-  else if (0 == strcmp (at_directive_argv[0], "@output"))
+  if (w & silent)
+    indent += SUB_INDENT;
+  else
+    indent = 0;
+  complain_args (locp, w, &indent, argc - 4, argv + 4);
+  if (w & silent)
+    indent -= SUB_INDENT;
+}
+
+static void
+at_output (int argc, char *argv[], char **out_namep, int *out_linenop)
+{
+  if (2 < argc)
+    fail_for_at_directive_too_many_args (argv[0]);
+  if (*out_namep)
     {
-      if (at_directive_argc > 2)
-        fail_for_at_directive_too_many_args (at_directive_argv[0]);
-      if (*outnamep)
-        {
-          free (*outnamep);
-          xfclose (yyout);
-        }
-      *outnamep = xstrdup (at_directive_argv[1]);
-      output_file_name_check (outnamep);
-      yyout = xfopen (*outnamep, "w");
-      *out_linenop = 1;
+      free (*out_namep);
+      xfclose (yyout);
     }
-  else
-    fail_for_invalid_at (at_directive_argv[0]);
+  *out_namep = xstrdup (argv[1]);
+  output_file_name_check (out_namep);
+  yyout = xfopen (*out_namep, "w");
+  *out_linenop = 1;
 }
 
 static void
 fail_for_at_directive_too_few_args (char const *at_directive_name)
 {
-  fatal (_("too few arguments for %s directive in skeleton"),
-         at_directive_name);
+  complain (NULL, 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 (NULL, 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 (NULL, fatal, "invalid @ in skeleton: %s", at);
 }
index bdf6ce635eca702650e5282c7b8d70347c1bfbcd..c11b10f7ddaf92f6e5463a59cafd7e28d3ec037f 100644 (file)
@@ -28,9 +28,9 @@
 #include "print-xml.h"
 
 
-                       /*-------------------.
-                       | Shifts and Gotos.  |
-                       `-------------------*/
+                        /*-------------------.
+                        | Shifts and Gotos.  |
+                        `-------------------*/
 
 
 /*-----------------------------------------.
@@ -61,14 +61,14 @@ transitions_to (transitions *shifts, symbol_number sym)
     {
       aver (j < shifts->num);
       if (TRANSITION_SYMBOL (shifts, j) == sym)
-       return shifts->states[j];
+        return shifts->states[j];
     }
 }
 
 
-                       /*--------------------.
-                       | Error transitions.  |
-                       `--------------------*/
+                        /*--------------------.
+                        | Error transitions.  |
+                        `--------------------*/
 
 
 /*---------------------------------.
@@ -88,9 +88,9 @@ errs_new (int num, symbol **tokens)
 
 
 
-                       /*-------------.
-                       | Reductions.  |
-                       `-------------*/
+                        /*-------------.
+                        | Reductions.  |
+                        `-------------*/
 
 
 /*---------------------------------------.
@@ -110,9 +110,9 @@ reductions_new (int num, rule **reds)
 
 
 
-                       /*---------.
-                       | States.  |
-                       `---------*/
+                        /*---------.
+                        | States.  |
+                        `---------*/
 
 
 state_number nstates = 0;
@@ -128,7 +128,7 @@ state *final_state = NULL;
 
 state *
 state_new (symbol_number accessing_symbol,
-          size_t nitems, item_number *core)
+           size_t nitems, item_number *core)
 {
   state *res;
   size_t items_size = nitems * sizeof *core;
@@ -264,17 +264,17 @@ state_rule_lookahead_tokens_print (state *s, rule *r, FILE *out)
       char const *sep = "";
       fprintf (out, "  [");
       BITSET_FOR_EACH (biter, reds->lookahead_tokens[red], k, 0)
-       {
-         fprintf (out, "%s%s", sep, symbols[k]->tag);
-         sep = ", ";
-       }
+        {
+          fprintf (out, "%s%s", sep, symbols[k]->tag);
+          sep = ", ";
+        }
       fprintf (out, "]");
     }
 }
 
 void
 state_rule_lookahead_tokens_print_xml (state *s, rule *r,
-                                      FILE *out, int level)
+                                       FILE *out, int level)
 {
   /* Find the reduction we are handling.  */
   reductions *reds = s->reductions;
@@ -287,10 +287,10 @@ state_rule_lookahead_tokens_print_xml (state *s, rule *r,
       int k;
       xml_puts (out, level, "<lookaheads>");
       BITSET_FOR_EACH (biter, reds->lookahead_tokens[red], k, 0)
-       {
-         xml_printf (out, level + 1, "<symbol>%s</symbol>",
-                     xml_escape (symbols[k]->tag));
-       }
+        {
+          xml_printf (out, level + 1, "<symbol>%s</symbol>",
+                      xml_escape (symbols[k]->tag));
+        }
       xml_puts (out, level, "</lookaheads>");
     }
 }
@@ -353,10 +353,10 @@ void
 state_hash_new (void)
 {
   state_table = hash_initialize (HT_INITIAL_CAPACITY,
-                                NULL,
-                                state_hasher,
-                                state_comparator,
-                                NULL);
+                                 NULL,
+                                 state_hasher,
+                                 state_comparator,
+                                 NULL);
 }
 
 
index 9937acff804fc46027cb593d0671a5c80906dbdb..37cd9bf9ec7362fa89caf720f32ae20023367a85 100644 (file)
@@ -119,41 +119,41 @@ typedef struct
    TRANSITIONS->states[Num]?  Can be a token (amongst which the error
    token), or non terminals in case of gotos.  */
 
-#define TRANSITION_SYMBOL(Transitions, Num) \
+# define TRANSITION_SYMBOL(Transitions, Num) \
   (Transitions->states[Num]->accessing_symbol)
 
 /* Is the TRANSITIONS->states[Num] a shift? (as opposed to gotos).  */
 
-#define TRANSITION_IS_SHIFT(Transitions, Num) \
+# define TRANSITION_IS_SHIFT(Transitions, Num) \
   (ISTOKEN (TRANSITION_SYMBOL (Transitions, Num)))
 
 /* Is the TRANSITIONS->states[Num] a goto?. */
 
-#define TRANSITION_IS_GOTO(Transitions, Num) \
+# define TRANSITION_IS_GOTO(Transitions, Num) \
   (!TRANSITION_IS_SHIFT (Transitions, Num))
 
 /* Is the TRANSITIONS->states[Num] labelled by the error token?  */
 
-#define TRANSITION_IS_ERROR(Transitions, Num) \
+# define TRANSITION_IS_ERROR(Transitions, Num) \
   (TRANSITION_SYMBOL (Transitions, Num) == errtoken->number)
 
 /* When resolving a SR conflicts, if the reduction wins, the shift is
    disabled.  */
 
-#define TRANSITION_DISABLE(Transitions, Num) \
+# define TRANSITION_DISABLE(Transitions, Num) \
   (Transitions->states[Num] = NULL)
 
-#define TRANSITION_IS_DISABLED(Transitions, Num) \
+# define TRANSITION_IS_DISABLED(Transitions, Num) \
   (Transitions->states[Num] == NULL)
 
 
 /* Iterate over each transition over a token (shifts).  */
-#define FOR_EACH_SHIFT(Transitions, Iter)                      \
-  for (Iter = 0;                                               \
-       Iter < Transitions->num                                 \
-        && (TRANSITION_IS_DISABLED (Transitions, Iter)         \
-            || TRANSITION_IS_SHIFT (Transitions, Iter));       \
-       ++Iter)                                                 \
+# define FOR_EACH_SHIFT(Transitions, Iter)                       \
+  for (Iter = 0;                                                \
+       Iter < Transitions->num                                  \
+         && (TRANSITION_IS_DISABLED (Transitions, Iter)         \
+             || TRANSITION_IS_SHIFT (Transitions, Iter));       \
+       ++Iter)                                                  \
     if (!TRANSITION_IS_DISABLED (Transitions, Iter))
 
 
@@ -228,7 +228,7 @@ extern state *final_state;
 
 /* Create a new state with ACCESSING_SYMBOL for those items.  */
 state *state_new (symbol_number accessing_symbol,
-                 size_t core_size, item_number *core);
+                  size_t core_size, item_number *core);
 state *state_new_isocore (state const *s);
 
 /* Set the transitions of STATE.  */
@@ -246,7 +246,7 @@ void state_errs_set (state *s, int num, symbol **errors);
    reduce R.  */
 void state_rule_lookahead_tokens_print (state *s, rule *r, FILE *out);
 void state_rule_lookahead_tokens_print_xml (state *s, rule *r,
-                                           FILE *out, int level);
+                                            FILE *out, int level);
 
 /* Create/destroy the states hash table.  */
 void state_hash_new (void);
index b6956677a7337077f9636ea9d4e3840a43e4a8c6..50915c18bdeebc99590795cd6a2bbe268e63c446 100644 (file)
@@ -24,7 +24,6 @@
 #include "complain.h"
 #include "symlist.h"
 
-
 /*--------------------------------------.
 | Create a list containing SYM at LOC.  |
 `--------------------------------------*/
@@ -37,18 +36,20 @@ symbol_list_sym_new (symbol *sym, location loc)
   res->content_type = SYMLIST_SYMBOL;
   res->content.sym = sym;
   res->location = res->sym_loc = loc;
+  res->named_ref = NULL;
 
   res->midrule = NULL;
   res->midrule_parent_rule = NULL;
   res->midrule_parent_rhs_index = 0;
 
-  code_props_none_init (&res->action_props);
-
+  /* Members used for LHS only.  */
   res->ruleprec = NULL;
+  res->percent_empty_loc = empty_location;
+  code_props_none_init (&res->action_props);
   res->dprec = 0;
+  res->dprec_location = empty_location;
   res->merger = 0;
-
-  res->named_ref = NULL;
+  res->merger_declaration_location = empty_location;
 
   res->next = NULL;
 
@@ -66,43 +67,11 @@ symbol_list_type_new (uniqstr type_name, location loc)
   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;
@@ -118,12 +87,17 @@ symbol_list_default_tagless_new (location loc)
 void
 symbol_list_syms_print (const symbol_list *l, FILE *f)
 {
+  char const *sep = "";
   for (/* Nothing. */; l && l->content.sym; l = l->next)
     {
+      fputs (sep, f);
+      fputs (l->content_type == SYMLIST_SYMBOL ? "symbol: "
+             : l->content_type == SYMLIST_TYPE ? "type: "
+             : "invalid content_type: ",
+             f);
       symbol_print (l->content.sym, f);
-      fprintf (stderr, l->action_props.is_value_used ? " used" : " unused");
-      if (l && l->content.sym)
-       fprintf (f, ", ");
+      fputs (l->action_props.is_value_used ? " used" : " unused", f);
+      sep = ", ";
     }
 }
 
@@ -140,6 +114,23 @@ symbol_list_prepend (symbol_list *list, symbol_list *node)
 }
 
 
+/*-------------------------.
+| Append NODE to the LIST. |
+`-------------------------*/
+
+symbol_list *
+symbol_list_append (symbol_list *list, symbol_list *node)
+{
+  if (!list)
+    return node;
+  symbol_list *next = list;
+  while (next->next)
+    next = next->next;
+  next->next = node;
+  return list;
+}
+
+
 /*-----------------------------------------------.
 | Free the LIST, but not the items it contains.  |
 `-----------------------------------------------*/
@@ -152,6 +143,8 @@ symbol_list_free (symbol_list *list)
     {
       next = node->next;
       named_ref_free (node->named_ref);
+      if (node->content_type == SYMLIST_TYPE)
+        free (node->content.sem_type);
       free (node);
     }
 }
@@ -190,7 +183,7 @@ symbol_list_n_get (symbol_list *l, int n)
       l = l->next;
       if (l == NULL
           || (l->content_type == SYMLIST_SYMBOL && l->content.sym == NULL))
-       return NULL;
+        return NULL;
     }
 
   return l;
@@ -208,7 +201,7 @@ symbol_list_n_type_name_get (symbol_list *l, location loc, int n)
   l = symbol_list_n_get (l, n);
   if (!l)
     {
-      complain_at (loc, _("invalid $ value: $%d"), n);
+      complain (&loc, complaint, _("invalid $ value: $%d"), n);
       return NULL;
     }
   aver (l->content_type == SYMLIST_SYMBOL);
@@ -223,43 +216,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,
+                            code_props const *cprops)
 {
   switch (node->content_type)
     {
-      case SYMLIST_SYMBOL:
-        symbol_printer_set (node->content.sym, printer);
-        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);
-        break;
+    case SYMLIST_SYMBOL:
+      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_code_props_set
+        (semantic_type_get (node->content.sem_type->tag,
+                            &node->content.sem_type->location),
+         kind, cprops);
+      if (node->content.sem_type->status == undeclared)
+        node->content.sem_type->status = used;
+      break;
     }
 }
index 9417f9ee47deb6cb34f74642d5935b13bf6405d0..c369f69bb1067a6d6f32a594090093e9eaf1fd49 100644 (file)
@@ -34,8 +34,8 @@ typedef struct symbol_list
    * \c <>.
    */
   enum {
-    SYMLIST_SYMBOL, SYMLIST_TYPE,
-    SYMLIST_DEFAULT_TAGGED, SYMLIST_DEFAULT_TAGLESS
+    SYMLIST_SYMBOL,
+    SYMLIST_TYPE
   } content_type;
   union {
     /**
@@ -46,10 +46,13 @@ typedef struct symbol_list
     /**
      * The semantic type iff <tt>symbol_list::content_type = SYMLIST_TYPE</tt>.
      */
-    uniqstr type_name;
+    semantic_type *sem_type;
   } content;
   location location;
 
+  /* Named reference. */
+  named_ref *named_ref;
+
   /* Proper location of the symbol, not all the rule */
   location sym_loc;
 
@@ -64,19 +67,26 @@ typedef struct symbol_list
   struct symbol_list *midrule_parent_rule;
   int midrule_parent_rhs_index;
 
+  /* ---------------------------------------------- */
+  /* Apply to the rule (attached to the LHS only).  */
+  /* ---------------------------------------------- */
+
+  /* Precedence/associativity.  */
+  symbol *ruleprec;
+
   /* The action is attached to the LHS of a rule, but action properties for
    * each RHS are also stored here.  */
   code_props action_props;
 
-  /* Precedence/associativity.  */
-  symbol *ruleprec;
+  /* The location of the first %empty for this rule, or \a
+     empty_location.  */
+  location percent_empty_loc;
+
   int dprec;
+  location dprec_location;
   int merger;
   location merger_declaration_location;
 
-  /* Named reference. */
-  named_ref *named_ref;
-
   /* The list.  */
   struct symbol_list *next;
 } symbol_list;
@@ -88,11 +98,6 @@ symbol_list *symbol_list_sym_new (symbol *sym, location loc);
 /** 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 =
@@ -102,6 +107,9 @@ void symbol_list_syms_print (const symbol_list *l, FILE *f);
 /** Prepend \c node to \c list.  */
 symbol_list *symbol_list_prepend (symbol_list *list, symbol_list *node);
 
+/** Append \c node to \c list.  */
+symbol_list *symbol_list_append (symbol_list *list, symbol_list *node);
+
 /** Free \c list, but not the items it contains.  */
 void symbol_list_free (symbol_list *list);
 
@@ -118,12 +126,8 @@ uniqstr symbol_list_n_type_name_get (symbol_list *l, location loc, int n);
 /* Check whether the node is a border element of a rule. */
 bool symbol_list_null (symbol_list *node);
 
-/** 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,
+                                 code_props const *cprops);
 
 #endif /* !SYMLIST_H_ */
index c793288e202968d9b759954db9ba45e71963ce01..b132e07bcd2b71ccfc61a3443760cc00587dc3b1 100644 (file)
@@ -33,6 +33,7 @@
 `-------------------------------------------------------------------*/
 
 static symbol **symbols_sorted = NULL;
+static symbol **semantic_types_sorted = NULL;
 
 /*------------------------.
 | Distinguished symbols.  |
@@ -45,14 +46,17 @@ symbol *accept = NULL;
 symbol *startsymbol = NULL;
 location startsymbol_location;
 
-/*---------------------------------------.
-| Default %destructor's and %printer's.  |
-`---------------------------------------*/
+/*---------------------------.
+| Precedence relation graph. |
+`---------------------------*/
+
+static symgraph **prec_nodes;
 
-static code_props default_tagged_destructor = CODE_PROPS_NONE_INIT;
-static code_props default_tagless_destructor = CODE_PROPS_NONE_INIT;
-static code_props default_tagged_printer = CODE_PROPS_NONE_INIT;
-static code_props default_tagless_printer = CODE_PROPS_NONE_INIT;
+/*-----------------------------------.
+| Store which associativity is used. |
+`-----------------------------------*/
+
+bool *used_assoc = NULL;
 
 /*---------------------------------.
 | Create a new symbol, named TAG.  |
@@ -62,21 +66,23 @@ static symbol *
 symbol_new (uniqstr tag, location loc)
 {
   symbol *res = xmalloc (sizeof *res);
-
   uniqstr_assert (tag);
 
   /* If the tag is not a string (starts with a double quote), check
      that it is valid for Yacc. */
-  if (tag[0] != '\"' && tag[0] != '\'' && mbschr (tag, '-'))
-    yacc_at (loc, _("POSIX Yacc forbids dashes in symbol names: %s"),
-             tag);
+  if (tag[0] != '\"' && tag[0] != '\'' && strchr (tag, '-'))
+    complain (&loc, Wyacc,
+              _("POSIX Yacc forbids dashes in symbol names: %s"), tag);
 
   res->tag = tag;
   res->location = loc;
 
   res->type_name = NULL;
-  code_props_none_init (&res->destructor);
-  code_props_none_init (&res->printer);
+  {
+    int i;
+    for (i = 0; i < CODE_PROPS_SIZE; ++i)
+      code_props_none_init (&res->props[i]);
+  }
 
   res->number = NUMBER_UNDEFINED;
   res->prec = 0;
@@ -85,28 +91,46 @@ symbol_new (uniqstr tag, location loc)
 
   res->alias = NULL;
   res->class = unknown_sym;
-  res->declared = false;
+  res->status = undeclared;
 
   if (nsyms == SYMBOL_NUMBER_MAXIMUM)
-    fatal (_("too many symbols in input grammar (limit is %d)"),
-          SYMBOL_NUMBER_MAXIMUM);
+    complain (NULL, fatal, _("too many symbols in input grammar (limit is %d)"),
+              SYMBOL_NUMBER_MAXIMUM);
   nsyms++;
   return res;
 }
 
+char const *
+code_props_type_string (code_props_type kind)
+{
+  switch (kind)
+    {
+    case destructor:
+      return "%destructor";
+    case printer:
+      return "%printer";
+    }
+  assert (0);
+}
+
 /*----------------------------------------.
 | Create a new semantic type, named TAG.  |
 `----------------------------------------*/
 
 static semantic_type *
-semantic_type_new (uniqstr tag)
+semantic_type_new (uniqstr tag, const location *loc)
 {
   semantic_type *res = xmalloc (sizeof *res);
 
   uniqstr_assert (tag);
   res->tag = tag;
-  code_props_none_init (&res->destructor);
-  code_props_none_init (&res->printer);
+  res->location = loc ? *loc : empty_location;
+  res->status = undeclared;
+  {
+    int i;
+    for (i = 0; i < CODE_PROPS_SIZE; ++i)
+      code_props_none_init (&res->props[i]);
+  }
 
   return res;
 }
@@ -116,31 +140,66 @@ semantic_type_new (uniqstr tag)
 | Print a symbol.  |
 `-----------------*/
 
-#define SYMBOL_ATTR_PRINT(Attr)                                \
-  if (s->Attr)                                         \
+#define SYMBOL_ATTR_PRINT(Attr)                         \
+  if (s->Attr)                                          \
     fprintf (f, " %s { %s }", #Attr, s->Attr)
 
-#define SYMBOL_CODE_PRINT(Attr)                         \
-  if (s->Attr.code)                                     \
-    fprintf (f, " %s { %s }", #Attr, s->Attr.code)
+#define SYMBOL_CODE_PRINT(Attr)                                         \
+  if (s->props[Attr].code)                                              \
+    fprintf (f, " %s { %s }", #Attr, s->props[Attr].code)
 
 void
-symbol_print (symbol *s, FILE *f)
+symbol_print (symbol const *s, FILE *f)
 {
   if (s)
     {
-      fprintf (f, "\"%s\"", s->tag);
+      fputs (s->tag, f);
       SYMBOL_ATTR_PRINT (type_name);
       SYMBOL_CODE_PRINT (destructor);
       SYMBOL_CODE_PRINT (printer);
     }
   else
-    fprintf (f, "<NULL>");
+    fputs ("<NULL>", f);
 }
 
 #undef SYMBOL_ATTR_PRINT
 #undef SYMBOL_CODE_PRINT
 
+
+/*----------------------------------.
+| Whether S is a valid identifier.  |
+`----------------------------------*/
+
+static bool
+is_identifier (uniqstr s)
+{
+  static char const alphanum[26 + 26 + 1 + 10] =
+    "abcdefghijklmnopqrstuvwxyz"
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+    "_"
+    "0123456789";
+  if (!s || ! memchr (alphanum, *s, sizeof alphanum - 10))
+    return false;
+  for (++s; *s; ++s)
+    if (! memchr (alphanum, *s, sizeof alphanum))
+      return false;
+  return true;
+}
+
+
+/*-----------------------------------------------.
+| Get the identifier associated to this symbol.  |
+`-----------------------------------------------*/
+uniqstr
+symbol_id_get (symbol const *sym)
+{
+  aver (sym->user_token_number != USER_NUMBER_HAS_STRING_ALIAS);
+  if (sym->alias)
+    sym = sym->alias;
+  return is_identifier (sym->tag) ? sym->tag : 0;
+}
+
+
 /*------------------------------------------------------------------.
 | Complain that S's WHAT is redeclared at SECOND, and was first set |
 | at FIRST.                                                         |
@@ -151,9 +210,11 @@ symbol_redeclaration (symbol *s, const char *what, location first,
                       location second)
 {
   unsigned i = 0;
-  complain_at_indent (second, &i, _("%s redeclaration for %s"), what, s->tag);
+  complain_indent (&second, complaint, &i,
+                   _("%s redeclaration for %s"), what, s->tag);
   i += SUB_INDENT;
-  complain_at_indent (first, &i, _("previous declaration"));
+  complain_indent (&first, complaint, &i,
+                   _("previous declaration"));
 }
 
 static void
@@ -161,9 +222,11 @@ semantic_type_redeclaration (semantic_type *s, const char *what, location first,
                              location second)
 {
   unsigned i = 0;
-  complain_at_indent (second, &i, _("%s redeclaration for <%s>"), what, s->tag);
+  complain_indent (&second, complaint, &i,
+                   _("%s redeclaration for <%s>"), what, s->tag);
   i += SUB_INDENT;
-  complain_at_indent (first, &i, _("previous declaration"));
+  complain_indent (&first, complaint, &i,
+                   _("previous declaration"));
 }
 
 
@@ -179,122 +242,73 @@ symbol_type_set (symbol *sym, uniqstr type_name, location loc)
   if (type_name)
     {
       if (sym->type_name)
-       symbol_redeclaration (sym, "%type", sym->type_location, loc);
+        symbol_redeclaration (sym, "%type", sym->type_location, loc);
       uniqstr_assert (type_name);
       sym->type_name = type_name;
       sym->type_location = loc;
     }
 }
 
-/*-----------------------------------------.
-| Set the DESTRUCTOR associated with SYM.  |
-`-----------------------------------------*/
+/*--------------------------------------------------------.
+| Set the DESTRUCTOR or PRINTER associated with the SYM.  |
+`--------------------------------------------------------*/
 
 void
-symbol_destructor_set (symbol *sym, code_props const *destructor)
+symbol_code_props_set (symbol *sym, code_props_type kind,
+                       code_props const *code)
 {
-  if (sym->destructor.code)
-    symbol_redeclaration (sym, "%destructor", sym->destructor.location,
-                          destructor->location);
-  sym->destructor = *destructor;
+  if (sym->props[kind].code)
+    symbol_redeclaration (sym, code_props_type_string (kind),
+                          sym->props[kind].location,
+                          code->location);
+  sym->props[kind] = *code;
 }
 
-/*------------------------------------------.
-| Set the DESTRUCTOR associated with TYPE.  |
-`------------------------------------------*/
+/*-----------------------------------------------------.
+| Set the DESTRUCTOR or PRINTER associated with TYPE.  |
+`-----------------------------------------------------*/
 
 void
-semantic_type_destructor_set (semantic_type *type,
-                              code_props const *destructor)
+semantic_type_code_props_set (semantic_type *type,
+                              code_props_type kind,
+                              code_props const *code)
 {
-  if (type->destructor.code)
-    semantic_type_redeclaration (type, "%destructor",
-                                 type->destructor.location,
-                                 destructor->location);
-  type->destructor = *destructor;
+  if (type->props[kind].code)
+    semantic_type_redeclaration (type, code_props_type_string (kind),
+                                 type->props[kind].location,
+                                 code->location);
+  type->props[kind] = *code;
 }
 
-/*---------------------------------------.
-| Get the computed %destructor for SYM.  |
-`---------------------------------------*/
+/*---------------------------------------------------.
+| Get the computed %destructor or %printer for SYM.  |
+`---------------------------------------------------*/
 
-code_props const *
-symbol_destructor_get (symbol const *sym)
+code_props *
+symbol_code_props_get (symbol *sym, code_props_type kind)
 {
-  /* Per-symbol %destructor.  */
-  if (sym->destructor.code)
-    return &sym->destructor;
+  /* Per-symbol code props.  */
+  if (sym->props[kind].code)
+    return &sym->props[kind];
 
-  /* Per-type %destructor.  */
+  /* Per-type code props.  */
   if (sym->type_name)
     {
-      code_props const *destructor =
-        &semantic_type_get (sym->type_name)->destructor;
-      if (destructor->code)
-        return destructor;
+      code_props *code =
+        &semantic_type_get (sym->type_name, NULL)->props[kind];
+      if (code->code)
+        return code;
     }
 
-  /* Apply default %destructor's only to user-defined symbols.  */
-  if (sym->tag[0] == '$' || sym == errtoken)
-    return &code_props_none;
-
-  if (sym->type_name)
-    return &default_tagged_destructor;
-  return &default_tagless_destructor;
-}
-
-/*--------------------------------------.
-| Set the PRINTER associated with SYM.  |
-`--------------------------------------*/
-
-void
-symbol_printer_set (symbol *sym, code_props const *printer)
-{
-  if (sym->printer.code)
-    symbol_redeclaration (sym, "%printer",
-                          sym->printer.location, printer->location);
-  sym->printer = *printer;
-}
-
-/*---------------------------------------.
-| Set the PRINTER associated with TYPE.  |
-`---------------------------------------*/
-
-void
-semantic_type_printer_set (semantic_type *type, code_props const *printer)
-{
-  if (type->printer.code)
-    semantic_type_redeclaration (type, "%printer",
-                                 type->printer.location, printer->location);
-  type->printer = *printer;
-}
-
-/*------------------------------------.
-| Get the computed %printer for SYM.  |
-`------------------------------------*/
-
-code_props const *
-symbol_printer_get (symbol const *sym)
-{
-  /* Per-symbol %printer.  */
-  if (sym->printer.code)
-    return &sym->printer;
-
-  /* Per-type %printer.  */
-  if (sym->type_name)
+  /* Apply default code props's only to user-defined symbols.  */
+  if (sym->tag[0] != '$' && sym != errtoken)
     {
-      code_props const *printer = &semantic_type_get (sym->type_name)->printer;
-      if (printer->code)
-        return printer;
+      code_props *code =
+        &semantic_type_get (sym->type_name ? "*" : "", NULL)->props[kind];
+      if (code->code)
+        return code;
     }
-
-  /* Apply the default %printer only to user-defined symbols.  */
-  if (sym->tag[0] == '$' || sym == errtoken)
-    return &code_props_none;
-
-  if (sym->type_name)
-    return &default_tagged_printer;
-  return &default_tagless_printer;
+  return &code_props_none;
 }
 
 /*-----------------------------------------------------------------.
@@ -308,7 +322,7 @@ symbol_precedence_set (symbol *sym, int prec, assoc a, location loc)
   if (a != undef_assoc)
     {
       if (sym->prec != 0)
-       symbol_redeclaration (sym, assoc_to_string (a), sym->prec_location,
+        symbol_redeclaration (sym, assoc_to_string (a), sym->prec_location,
                               loc);
       sym->prec = prec;
       sym->assoc = a;
@@ -327,10 +341,12 @@ symbol_precedence_set (symbol *sym, int prec, assoc a, location loc)
 void
 symbol_class_set (symbol *sym, symbol_class class, location loc, bool declaring)
 {
+  bool warned = false;
   if (sym->class != unknown_sym && sym->class != class)
     {
-      complain_at (loc, _("symbol %s redefined"), sym->tag);
-      sym->declared = false;
+      complain (&loc, complaint, _("symbol %s redefined"), sym->tag);
+      /* Don't report both "redefined" and "redeclared".  */
+      warned = true;
     }
 
   if (class == nterm_sym && sym->class != nterm_sym)
@@ -342,9 +358,9 @@ symbol_class_set (symbol *sym, symbol_class class, location loc, bool declaring)
 
   if (declaring)
     {
-      if (sym->declared)
-       warn_at (loc, _("symbol %s redeclared"), sym->tag);
-      sym->declared = true;
+      if (sym->status == declared && !warned)
+        complain (&loc, Wother, _("symbol %s redeclared"), sym->tag);
+      sym->status = declared;
     }
 }
 
@@ -364,7 +380,8 @@ symbol_user_token_number_set (symbol *sym, int user_token_number, location loc)
     user_token_numberp = &sym->alias->user_token_number;
   if (*user_token_numberp != USER_NUMBER_UNDEFINED
       && *user_token_numberp != user_token_number)
-    complain_at (loc, _("redefining user token number of %s"), sym->tag);
+    complain (&loc, complaint, _("redefining user token number of %s"),
+              sym->tag);
 
   *user_token_numberp = user_token_number;
   /* User defined $end token? */
@@ -372,7 +389,7 @@ symbol_user_token_number_set (symbol *sym, int user_token_number, location loc)
     {
       endtoken = sym;
       /* It is always mapped to 0, so it was already counted in
-        NTOKENS.  */
+         NTOKENS.  */
       if (endtoken->number != NUMBER_UNDEFINED)
         --ntokens;
       endtoken->number = 0;
@@ -390,14 +407,55 @@ symbol_check_defined (symbol *sym)
 {
   if (sym->class == unknown_sym)
     {
-      complain_at
-       (sym->location,
-        _("symbol %s is used, but is not defined as a token and has no rules"),
-        sym->tag);
+      assert (sym->status != declared);
+      complain (&sym->location,
+                sym->status == needed ? complaint : Wother,
+                _("symbol %s is used, but is not defined as a token"
+                  " and has no rules"),
+                  sym->tag);
       sym->class = nterm_sym;
       sym->number = nvars++;
     }
 
+  {
+    int i;
+    for (i = 0; i < 2; ++i)
+      symbol_code_props_get (sym, i)->is_used = true;
+  }
+
+  /* Set the semantic type status associated to the current symbol to
+     'declared' so that we could check semantic types unnecessary uses. */
+  if (sym->type_name)
+    {
+      semantic_type *sem_type = semantic_type_get (sym->type_name, NULL);
+      if (sem_type)
+        sem_type->status = declared;
+    }
+
+  return true;
+}
+
+static inline bool
+semantic_type_check_defined (semantic_type *sem_type)
+{
+  /* <*> and <> do not have to be "declared".  */
+  if (sem_type->status == declared
+      || !*sem_type->tag
+      || STREQ(sem_type->tag, "*"))
+    {
+      int i;
+      for (i = 0; i < 2; ++i)
+        if (sem_type->props[i].kind != CODE_PROPS_NONE
+            && ! sem_type->props[i].is_used)
+          complain (&sem_type->location, Wother,
+                    _("useless %s for type <%s>"),
+                    code_props_type_string (i), sem_type->tag);
+    }
+  else
+    complain (&sem_type->location, Wother,
+              _("type <%s> is used, but is not associated to any symbol"),
+              sem_type->tag);
+
   return true;
 }
 
@@ -407,16 +465,23 @@ symbol_check_defined_processor (void *sym, void *null ATTRIBUTE_UNUSED)
   return symbol_check_defined (sym);
 }
 
+static bool
+semantic_type_check_defined_processor (void *sem_type,
+                                       void *null ATTRIBUTE_UNUSED)
+{
+  return semantic_type_check_defined (sem_type);
+}
+
 
 void
 symbol_make_alias (symbol *sym, symbol *str, location loc)
 {
   if (str->alias)
-    warn_at (loc, _("symbol %s used more than once as a literal string"),
-             str->tag);
+    complain (&loc, Wother,
+              _("symbol %s used more than once as a literal string"), str->tag);
   else if (sym->alias)
-    warn_at (loc, _("symbol %s given more than one literal string"),
-             sym->tag);
+    complain (&loc, Wother,
+              _("symbol %s given more than one literal string"), sym->tag);
   else
     {
       str->class = token_sym;
@@ -449,42 +514,35 @@ symbol_check_alias_consistency (symbol *this)
   if (str->type_name != sym->type_name)
     {
       if (str->type_name)
-       symbol_type_set (sym, str->type_name, str->type_location);
+        symbol_type_set (sym, str->type_name, str->type_location);
       else
-       symbol_type_set (str, sym->type_name, sym->type_location);
+        symbol_type_set (str, sym->type_name, sym->type_location);
     }
 
 
-  if (str->destructor.code || sym->destructor.code)
-    {
-      if (str->destructor.code)
-       symbol_destructor_set (sym, &str->destructor);
-      else
-       symbol_destructor_set (str, &sym->destructor);
-    }
-
-  if (str->printer.code || sym->printer.code)
-    {
-      if (str->printer.code)
-       symbol_printer_set (sym, &str->printer);
-      else
-       symbol_printer_set (str, &sym->printer);
-    }
+  {
+    int i;
+    for (i = 0; i < CODE_PROPS_SIZE; ++i)
+      if (str->props[i].code)
+        symbol_code_props_set (sym, i, &str->props[i]);
+      else if (sym->props[i].code)
+        symbol_code_props_set (str, i, &sym->props[i]);
+  }
 
   if (sym->prec || str->prec)
     {
       if (str->prec)
-       symbol_precedence_set (sym, str->prec, str->assoc,
-                              str->prec_location);
+        symbol_precedence_set (sym, str->prec, str->assoc,
+                               str->prec_location);
       else
-       symbol_precedence_set (str, sym->prec, sym->assoc,
-                              sym->prec_location);
+        symbol_precedence_set (str, sym->prec, sym->assoc,
+                               sym->prec_location);
     }
 }
 
 static bool
 symbol_check_alias_consistency_processor (void *this,
-                                         void *null ATTRIBUTE_UNUSED)
+                                          void *null ATTRIBUTE_UNUSED)
 {
   symbol_check_alias_consistency (this);
   return true;
@@ -531,13 +589,13 @@ user_token_number_redeclaration (int num, symbol *first, symbol *second)
       first = second;
       second = tmp;
     }
-  complain_at_indent (second->location, &i,
-                      _("user token number %d redeclaration for %s"),
-                      num, second->tag);
+  complain_indent (&second->location, complaint, &i,
+                   _("user token number %d redeclaration for %s"),
+                   num, second->tag);
   i += SUB_INDENT;
-  complain_at_indent (first->location, &i,
-                      _("previous declaration for %s"),
-                      first->tag);
+  complain_indent (&first->location, complaint, &i,
+                   _("previous declaration for %s"),
+                   first->tag);
 }
 
 /*--------------------------------------------------.
@@ -553,7 +611,7 @@ symbol_translation (symbol *this)
     {
       /* A token which translation has already been set? */
       if (token_translations[this->user_token_number] != undeftoken->number)
-       user_token_number_redeclaration
+        user_token_number_redeclaration
           (this->user_token_number,
            symbols[token_translations[this->user_token_number]],
            this);
@@ -641,15 +699,15 @@ void
 symbols_new (void)
 {
   symbol_table = hash_initialize (HT_INITIAL_CAPACITY,
-                                 NULL,
-                                 hash_symbol_hasher,
-                                 hash_symbol_comparator,
-                                 free);
+                                  NULL,
+                                  hash_symbol_hasher,
+                                  hash_symbol_comparator,
+                                  free);
   semantic_type_table = hash_initialize (HT_INITIAL_CAPACITY,
-                                        NULL,
-                                        hash_semantic_type_hasher,
-                                        hash_semantic_type_comparator,
-                                        free);
+                                         NULL,
+                                         hash_semantic_type_hasher,
+                                         hash_semantic_type_comparator,
+                                         free);
 }
 
 
@@ -685,7 +743,7 @@ symbol_from_uniqstr (const uniqstr key, location loc)
 `-----------------------------------------------------------------------*/
 
 semantic_type *
-semantic_type_from_uniqstr (const uniqstr key)
+semantic_type_from_uniqstr (const uniqstr key, const location *loc)
 {
   semantic_type probe;
   semantic_type *entry;
@@ -696,7 +754,7 @@ semantic_type_from_uniqstr (const uniqstr key)
   if (!entry)
     {
       /* First insertion in the hash. */
-      entry = semantic_type_new (key);
+      entry = semantic_type_new (key, loc);
       if (!hash_insert (semantic_type_table, entry))
         xalloc_die ();
     }
@@ -722,9 +780,9 @@ symbol_get (const char *key, location loc)
 `-----------------------------------------------------------------------*/
 
 semantic_type *
-semantic_type_get (const char *key)
+semantic_type_get (const char *key, const location *loc)
 {
-  return semantic_type_from_uniqstr (uniqstr_new (key));
+  return semantic_type_from_uniqstr (uniqstr_new (key), loc);
 }
 
 
@@ -766,6 +824,7 @@ symbols_free (void)
   hash_free (semantic_type_table);
   free (symbols);
   free (symbols_sorted);
+  free (semantic_types_sorted);
 }
 
 
@@ -787,20 +846,20 @@ symbols_cmp_qsort (void const *a, void const *b)
 }
 
 static void
-symbols_do (Hash_processor processor, void *processor_data)
+symbols_do (Hash_processor processor, void *processor_data,
+            struct hash_table *table, symbol ***sorted)
 {
-  size_t count = hash_get_n_entries (symbol_table);
-  if (!symbols_sorted)
+  size_t count = hash_get_n_entries (table);
+  if (!*sorted)
     {
-      symbols_sorted = xnmalloc (count, sizeof *symbols_sorted);
-      hash_get_entries (symbol_table, (void**)symbols_sorted, count);
-      qsort (symbols_sorted, count, sizeof *symbols_sorted,
-             symbols_cmp_qsort);
+      *sorted = xnmalloc (count, sizeof **sorted);
+      hash_get_entries (table, (void**)*sorted, count);
+      qsort (*sorted, count, sizeof **sorted, symbols_cmp_qsort);
     }
   {
     size_t i;
     for (i = 0; i < count; ++i)
-      processor (symbols_sorted[i], processor_data);
+      processor ((*sorted)[i], processor_data);
   }
 }
 
@@ -812,7 +871,10 @@ symbols_do (Hash_processor processor, void *processor_data)
 void
 symbols_check_defined (void)
 {
-  symbols_do (symbol_check_defined_processor, NULL);
+  symbols_do (symbol_check_defined_processor, NULL,
+              symbol_table, &symbols_sorted);
+  symbols_do (semantic_type_check_defined_processor, NULL,
+              semantic_type_table, &semantic_types_sorted);
 }
 
 /*------------------------------------------------------------------.
@@ -833,12 +895,12 @@ symbols_token_translations_init (void)
     {
       symbol *this = symbols[i];
       if (this->user_token_number != USER_NUMBER_UNDEFINED)
-       {
-         if (this->user_token_number > max_user_token_number)
-           max_user_token_number = this->user_token_number;
-         if (this->user_token_number == 256)
-           num_256_available_p = false;
-       }
+        {
+          if (this->user_token_number > max_user_token_number)
+            max_user_token_number = this->user_token_number;
+          if (this->user_token_number == 256)
+            num_256_available_p = false;
+        }
     }
 
   /* If 256 is not used, assign it to error, to follow POSIX.  */
@@ -854,20 +916,20 @@ symbols_token_translations_init (void)
     {
       symbol *this = symbols[i];
       if (this->user_token_number == USER_NUMBER_UNDEFINED)
-       this->user_token_number = ++max_user_token_number;
+        this->user_token_number = ++max_user_token_number;
       if (this->user_token_number > max_user_token_number)
-       max_user_token_number = this->user_token_number;
+        max_user_token_number = this->user_token_number;
     }
 
   token_translations = xnmalloc (max_user_token_number + 1,
-                                sizeof *token_translations);
+                                 sizeof *token_translations);
 
-  /* Initialize all entries for literal tokens to 2, the internal
-     token number for $undefined, which represents all invalid inputs.
-     */
+  /* Initialize all entries for literal tokens to the internal token
+     number for $undefined, which represents all invalid inputs.  */
   for (i = 0; i < max_user_token_number + 1; i++)
     token_translations[i] = undeftoken->number;
-  symbols_do (symbol_translation_processor, NULL);
+  symbols_do (symbol_translation_processor, NULL,
+              symbol_table, &symbols_sorted);
 }
 
 
@@ -879,10 +941,11 @@ symbols_token_translations_init (void)
 void
 symbols_pack (void)
 {
-  symbols_do (symbol_check_alias_consistency_processor, NULL);
+  symbols_do (symbol_check_alias_consistency_processor, NULL,
+              symbol_table, &symbols_sorted);
 
   symbols = xcalloc (nsyms, sizeof *symbols);
-  symbols_do (symbol_pack_processor, NULL);
+  symbols_do (symbol_pack_processor, NULL, symbol_table, &symbols_sorted);
 
   /* Aliases leave empty slots in symbols, so remove them.  */
   {
@@ -911,76 +974,195 @@ symbols_pack (void)
   symbols_token_translations_init ();
 
   if (startsymbol->class == unknown_sym)
-    fatal_at (startsymbol_location,
-             _("the start symbol %s is undefined"),
-             startsymbol->tag);
+    complain (&startsymbol_location, fatal,
+              _("the start symbol %s is undefined"),
+              startsymbol->tag);
   else if (startsymbol->class == token_sym)
-    fatal_at (startsymbol_location,
-             _("the start symbol %s is a token"),
-             startsymbol->tag);
+    complain (&startsymbol_location, fatal,
+              _("the start symbol %s is a token"),
+              startsymbol->tag);
 }
 
+/*---------------------------------.
+| Initialize relation graph nodes. |
+`---------------------------------*/
 
-/*--------------------------------------------------.
-| Set default tagged/tagless %destructor/%printer.  |
-`--------------------------------------------------*/
+static void
+init_prec_nodes (void)
+{
+  int i;
+  prec_nodes = xcalloc (nsyms, sizeof *prec_nodes);
+  for (i = 0; i < nsyms; ++i)
+    {
+      prec_nodes[i] = xmalloc (sizeof *prec_nodes[i]);
+      symgraph *s = prec_nodes[i];
+      s->id = i;
+      s->succ = 0;
+      s->pred = 0;
+    }
+}
 
-void
-default_tagged_destructor_set (code_props const *destructor)
+/*----------------.
+| Create a link.  |
+`----------------*/
+
+static symgraphlink *
+symgraphlink_new (graphid id, symgraphlink *next)
+{
+  symgraphlink *l = xmalloc (sizeof *l);
+  l->id = id;
+  l->next = next;
+  return l;
+}
+
+
+/*------------------------------------------------------------------.
+| Register the second symbol of the precedence relation, and return |
+| whether this relation is new.  Use only in register_precedence.   |
+`------------------------------------------------------------------*/
+
+static bool
+register_precedence_second_symbol (symgraphlink **first, graphid sym)
 {
-  if (default_tagged_destructor.code)
+  if (!*first || sym < (*first)->id)
+    *first = symgraphlink_new (sym, *first);
+  else
     {
-      unsigned i = 0;
-      complain_at_indent (destructor->location, &i,
-                          _("redeclaration for default tagged %%destructor"));
-      i += SUB_INDENT;
-      complain_at_indent (default_tagged_destructor.location, &i,
-                         _("previous declaration"));
+      symgraphlink *slist = *first;
+
+      while (slist->next && slist->next->id <= sym)
+        slist = slist->next;
+
+      if (slist->id == sym)
+        /* Relation already present. */
+        return false;
+
+      slist->next = symgraphlink_new (sym, slist->next);
     }
-  default_tagged_destructor = *destructor;
+  return true;
 }
 
+/*------------------------------------------------------------------.
+| Register a new relation between symbols as used. The first symbol |
+| has a greater precedence than the second one.                     |
+`------------------------------------------------------------------*/
+
 void
-default_tagless_destructor_set (code_props const *destructor)
+register_precedence (graphid first, graphid snd)
 {
-  if (default_tagless_destructor.code)
+  if (!prec_nodes)
+    init_prec_nodes ();
+  register_precedence_second_symbol (&(prec_nodes[first]->succ), snd);
+  register_precedence_second_symbol (&(prec_nodes[snd]->pred), first);
+}
+
+
+/*---------------------------------------.
+| Deep clear a linked / adjacency list). |
+`---------------------------------------*/
+
+static void
+linkedlist_free (symgraphlink *node)
+{
+  if (node)
     {
-      unsigned i = 0;
-      complain_at_indent (destructor->location, &i,
-                          _("redeclaration for default tagless %%destructor"));
-      i += SUB_INDENT;
-      complain_at_indent (default_tagless_destructor.location, &i,
-                          _("previous declaration"));
+      while (node->next)
+        {
+          symgraphlink *tmp = node->next;
+          free (node);
+          node = tmp;
+        }
+      free (node);
     }
-  default_tagless_destructor = *destructor;
 }
 
-void
-default_tagged_printer_set (code_props const *printer)
+/*----------------------------------------------.
+| Clear and destroy association tracking table. |
+`----------------------------------------------*/
+
+static void
+assoc_free (void)
 {
-  if (default_tagged_printer.code)
+  int i;
+  for (i = 0; i < nsyms; ++i)
     {
-      unsigned i = 0;
-      complain_at_indent (printer->location, &i,
-                          _("redeclaration for default tagged %%printer"));
-      i += SUB_INDENT;
-      complain_at_indent (default_tagged_printer.location, &i,
-                         _("previous declaration"));
+      linkedlist_free (prec_nodes[i]->pred);
+      linkedlist_free (prec_nodes[i]->succ);
+      free (prec_nodes[i]);
     }
-  default_tagged_printer = *printer;
+  free (prec_nodes);
+}
+
+/*---------------------------------------.
+| Initialize association tracking table. |
+`---------------------------------------*/
+
+static void
+init_assoc (void)
+{
+  graphid i;
+  used_assoc = xcalloc(nsyms, sizeof(*used_assoc));
+  for (i = 0; i < nsyms; ++i)
+    used_assoc[i] = false;
 }
 
+/*------------------------------------------------------------------.
+| Test if the associativity for the symbols is defined and useless. |
+`------------------------------------------------------------------*/
+
+static inline bool
+is_assoc_useless (symbol *s)
+{
+  return s
+      && s->assoc != undef_assoc
+      && s->assoc != precedence_assoc
+      && !used_assoc[s->number];
+}
+
+/*-------------------------------.
+| Register a used associativity. |
+`-------------------------------*/
+
 void
-default_tagless_printer_set (code_props const *printer)
+register_assoc (graphid i, graphid j)
 {
-  if (default_tagless_printer.code)
+  if (!used_assoc)
+    init_assoc ();
+  used_assoc[i] = true;
+  used_assoc[j] = true;
+}
+
+/*--------------------------------------------------.
+| Print a warning for unused precedence relations.  |
+`--------------------------------------------------*/
+
+void
+print_precedence_warnings (void)
+{
+  int i;
+  if (!prec_nodes)
+    init_prec_nodes ();
+  if (!used_assoc)
+    init_assoc ();
+  for (i = 0; i < nsyms; ++i)
     {
-      unsigned i = 0;
-      complain_at_indent (printer->location, &i,
-                          _("redeclaration for default tagless %%printer"));
-      i += SUB_INDENT;
-      complain_at_indent (default_tagless_printer.location, &i,
-                         _("previous declaration"));
+      symbol *s = symbols[i];
+      if (s
+          && s->prec != 0
+          && !prec_nodes[i]->pred
+          && !prec_nodes[i]->succ)
+        {
+          if (is_assoc_useless (s))
+            complain (&s->location, Wprecedence,
+                      _("useless precedence and associativity for %s"), s->tag);
+          else if (s->assoc == precedence_assoc)
+            complain (&s->location, Wprecedence,
+                      _("useless precedence for %s"), s->tag);
+        }
+      else if (is_assoc_useless (s))
+        complain (&s->location, Wprecedence,
+                  _("useless associativity for %s, use %%precedence"), s->tag);
     }
-  default_tagless_printer = *printer;
+  free (used_assoc);
+  assoc_free ();
 }
index b54f5d726e0d69dc94e56a12dcb90eb42dfb0a79..bcc749511c2d20465bcc3e092e6af6f0131fca94 100644 (file)
@@ -1,7 +1,7 @@
 /* Definitions for symtab.c and callers, part of Bison.
 
-   Copyright (C) 1984, 1989, 1992, 2000-2002, 2004-2007, 2009-2013 Free
-   Software Foundation, Inc.
+   Copyright (C) 1984, 1989, 1992, 2000-2002, 2004-2013 Free Software
+   Foundation, Inc.
 
    This file is part of Bison, the GNU Compiler Compiler.
 
 typedef enum
 {
   unknown_sym,          /**< Undefined.  */
-  token_sym,           /**< Terminal. */
-  nterm_sym            /**< Non-terminal. */
+  token_sym,            /**< Terminal. */
+  nterm_sym             /**< Non-terminal. */
 } symbol_class;
 
 
 /** Internal token numbers. */
 typedef int symbol_number;
-#define SYMBOL_NUMBER_MAXIMUM INT_MAX
+# define SYMBOL_NUMBER_MAXIMUM INT_MAX
 
 
 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" but used in
+   a rule, it is "needed".  Finally, if declared (via a rule for
+   nonterminals, or %token), 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
@@ -71,20 +102,14 @@ struct symbol
   /** 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
+      = NULL</tt>), a default \c \%destructor (resp. \%printer) or a per-type
+      \c symbol_destructor_printer_get will compute the correct one. */
+  code_props props[CODE_PROPS_SIZE];
 
   symbol_number number;
   location prec_location;
@@ -97,23 +122,20 @@ struct symbol
      symbol-string pair for an alias.  */
   symbol *alias;
   symbol_class class;
-  bool declared;
+  status status;
 };
 
 /** Undefined user number.  */
-#define USER_NUMBER_UNDEFINED -1
+# define USER_NUMBER_UNDEFINED -1
 
-/* `symbol->user_token_number == USER_NUMBER_HAS_STRING_ALIAS' means
-   this symbol has a literal string alias.  For instance, `%token foo
-   "foo"' has `"foo"' numbered regularly, and `foo' numbered as
+/* 'symbol->user_token_number == USER_NUMBER_HAS_STRING_ALIAS' means
+   this symbol has a literal string alias.  For instance, '%token foo
+   "foo"' has '"foo"' numbered regularly, and 'foo' numbered as
    USER_NUMBER_HAS_STRING_ALIAS.  */
-#define USER_NUMBER_HAS_STRING_ALIAS -9991
+# define USER_NUMBER_HAS_STRING_ALIAS -9991
 
 /* Undefined internal token number.  */
-#define NUMBER_UNDEFINED (-1)
-
-/** Print a symbol (for debugging). */
-void symbol_print (symbol *s, FILE *f);
+# define NUMBER_UNDEFINED (-1)
 
 /** Fetch (or create) the symbol associated to KEY.  */
 symbol *symbol_from_uniqstr (const uniqstr key, location loc);
@@ -126,9 +148,26 @@ symbol *symbol_get (const char *key, location loc);
    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.
@@ -140,34 +179,34 @@ void symbol_make_alias (symbol *sym, symbol *str, location loc);
     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.  */
@@ -185,6 +224,59 @@ extern symbol *startsymbol;
 extern location startsymbol_location;
 
 
+
+/*-------------------.
+| Symbol Relations.  |
+`-------------------*/
+
+/* The symbol relations are represented by a directed graph. */
+
+/* The id of a node */
+typedef int graphid;
+
+typedef struct symgraphlink symgraphlink;
+
+struct symgraphlink
+{
+  /** The second \c symbol or group of a precedence relation.
+   * See \c symgraph. */
+  graphid id;
+
+  symgraphlink *next;
+};
+
+/* Symbol precedence graph, to store the used precedence relations between
+ * symbols. */
+
+typedef struct symgraph symgraph;
+
+struct symgraph
+{
+  /** Identifier for the node: equal to the number of the symbol. */
+  graphid id;
+
+  /** The list of related symbols that have a smaller precedence. */
+  symgraphlink *succ;
+
+  /** The list of related symbols that have a greater precedence. */
+  symgraphlink *pred;
+};
+
+/** Register a new precedence relation as used. */
+
+void register_precedence (graphid first, graphid snd);
+
+/** Print a warning for each symbol whose precedence and/or associativity
+ * is useless. */
+
+void print_precedence_warnings (void);
+
+/*----------------------.
+| Symbol associativity  |
+`----------------------*/
+
+void register_assoc (graphid i, graphid j);
+
 /*-----------------.
 | Semantic types.  |
 `-----------------*/
@@ -197,25 +289,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);
-
-/** Set the \c destructor associated with \c type.  */
-void semantic_type_destructor_set (semantic_type *type,
-                                   code_props const *destructor);
+semantic_type *semantic_type_get (const char *key, const location *loc);
 
-/** 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.  |
@@ -238,19 +335,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_ */
index f40e0fc0ca8b99b6cd49957898600f8f45bfc3bd..3267f2d24c6cc2dbc4d2ea755f3a2fa341c7aaee 100644 (file)
 # 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)
+
 # include <unistd.h>
 # include <inttypes.h>
 
-#define ARRAY_CARDINALITY(Array) (sizeof (Array) / sizeof *(Array))
-#define STREQ(L, R)  (strcmp(L, R) == 0)
-#define STRNEQ(L, R) (!STREQ(L, R))
-
 # ifndef UINTPTR_MAX
 /* This isn't perfect, but it's good enough for Bison, which needs
    only to hash pointers.  */
@@ -89,7 +99,7 @@ typedef size_t uintptr_t;
 #  endif
 # endif
 
-/* The __-protected variants of `format' and `printf' attributes
+/* 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
@@ -158,7 +168,9 @@ typedef size_t uintptr_t;
 # define obstack_chunk_free  free
 # include <obstack.h>
 
-# define obstack_sgrow(Obs, Str)                \
+/* String-grow: append Str to Obs.  */
+
+# define obstack_sgrow(Obs, Str) \
   obstack_grow (Obs, Str, strlen (Str))
 
 /* Output Str escaped for our postprocessing (i.e., escape M4 special
@@ -168,15 +180,15 @@ typedef size_t uintptr_t;
 
 # 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)
 
@@ -204,7 +216,7 @@ typedef size_t uintptr_t;
 
 /* Append the ending 0, finish Obs, and return the string.  */
 
-# define obstack_finish0(Obs)                           \
+# define obstack_finish0(Obs)                                   \
   (obstack_1grow (Obs, '\0'), (char *) obstack_finish (Obs))
 
 
index 9a851a9358177d42b1cb063907fdc5e69aac4fcb..f06cba86b9c23d5b3b54829712c02f229a1390d4 100644 (file)
@@ -35,7 +35,7 @@
 #include "tables.h"
 
 /* Several tables are indexed both by state and nonterminal numbers.
-   We call such an index a `vector'; i.e., a vector is either a state
+   We call such an index a 'vector'; i.e., a vector is either a state
    or a nonterminal number.
 
    Of course vector_number_t ought to be wide enough to contain
@@ -84,24 +84,24 @@ int nvectors;
 static base_number **froms;
 static base_number **tos;
 static unsigned int **conflict_tos;
-static int *tally;
+static size_t *tally;
 static base_number *width;
 
 
 /* For a given state, N = ACTROW[SYMBOL]:
 
-   If N = 0, stands for `run the default action'.
-   If N = MIN, stands for `raise a syntax error'.
-   If N > 0, stands for `shift SYMBOL and go to n'.
-   If N < 0, stands for `reduce -N'.  */
+   If N = 0, stands for 'run the default action'.
+   If N = MIN, stands for 'raise a syntax error'.
+   If N > 0, stands for 'shift SYMBOL and go to n'.
+   If N < 0, stands for 'reduce -N'.  */
 typedef int action_number;
 #define ACTION_NUMBER_MINIMUM INT_MIN
 
 static action_number *actrow;
 
 /* FROMS and TOS are reordered to be compressed.  ORDER[VECTOR] is the
-   new vector number of VECTOR.  We skip `empty' vectors (i.e.,
-   TALLY[VECTOR] = 0), and call these `entries'.  */
+   new vector number of VECTOR.  We skip 'empty' vectors (i.e.,
+   TALLY[VECTOR] = 0), and call these 'entries'.  */
 static vector_number *order;
 static int nentries;
 
@@ -135,11 +135,11 @@ int high;
 state_number *yydefgoto;
 rule_number *yydefact;
 
-/*----------------------------------------------------------------.
-| If TABLE (and CHECK) appear to be small to be addressed at      |
-| DESIRED, grow them.  Note that TABLE[DESIRED] is to be used, so |
-| the desired size is at least DESIRED + 1.                       |
-`----------------------------------------------------------------*/
+/*-------------------------------------------------------------------.
+| If TABLE, CONFLICT_TABLE, and CHECK are too small to be addressed  |
+| at DESIRED, grow them.  TABLE[DESIRED] can be used, so the desired |
+| size is at least DESIRED + 1.                                      |
+`-------------------------------------------------------------------*/
 
 static void
 table_grow (int desired)
@@ -151,11 +151,11 @@ table_grow (int desired)
 
   if (trace_flag & trace_resource)
     fprintf (stderr, "growing table and check from: %d to %d\n",
-            old_size, table_size);
+             old_size, table_size);
 
   table = xnrealloc (table, table_size, sizeof *table);
   conflict_table = xnrealloc (conflict_table, table_size,
-                             sizeof *conflict_table);
+                              sizeof *conflict_table);
   check = xnrealloc (check, table_size, sizeof *check);
 
   for (/* Nothing. */; old_size < table_size; ++old_size)
@@ -171,12 +171,12 @@ table_grow (int desired)
 
 /*-------------------------------------------------------------------.
 | For GLR parsers, for each conflicted token in S, as indicated      |
-| by non-zero entries in CONFLROW, create a list of possible        |
-| reductions that are alternatives to the shift or reduction        |
+| by non-zero entries in CONFLROW, create a list of possible         |
+| reductions that are alternatives to the shift or reduction         |
 | currently recorded for that token in S.  Store the alternative     |
-| reductions followed by a 0 in CONFLICT_LIST, updating                     |
+| reductions followed by a 0 in CONFLICT_LIST, updating              |
 | CONFLICT_LIST_CNT, and storing an index to the start of the list   |
-| back into CONFLROW.                                               |
+| back into CONFLROW.                                                |
 `-------------------------------------------------------------------*/
 
 static void
@@ -191,26 +191,26 @@ conflict_row (state *s)
   for (j = 0; j < ntokens; j += 1)
     if (conflrow[j])
       {
-       conflrow[j] = conflict_list_cnt;
-
-       /* Find all reductions for token J, and record all that do not
-          match ACTROW[J].  */
-       for (i = 0; i < reds->num; i += 1)
-         if (bitset_test (reds->lookahead_tokens[i], j)
-             && (actrow[j]
-                 != rule_number_as_item_number (reds->rules[i]->number)))
-           {
-             aver (0 < conflict_list_free);
-             conflict_list[conflict_list_cnt] = reds->rules[i]->number + 1;
-             conflict_list_cnt += 1;
-             conflict_list_free -= 1;
-           }
-
-       /* Leave a 0 at the end.  */
-       aver (0 < conflict_list_free);
-       conflict_list[conflict_list_cnt] = 0;
-       conflict_list_cnt += 1;
-       conflict_list_free -= 1;
+        conflrow[j] = conflict_list_cnt;
+
+        /* Find all reductions for token J, and record all that do not
+           match ACTROW[J].  */
+        for (i = 0; i < reds->num; i += 1)
+          if (bitset_test (reds->lookahead_tokens[i], j)
+              && (actrow[j]
+                  != rule_number_as_item_number (reds->rules[i]->number)))
+            {
+              aver (0 < conflict_list_free);
+              conflict_list[conflict_list_cnt] = reds->rules[i]->number + 1;
+              conflict_list_cnt += 1;
+              conflict_list_free -= 1;
+            }
+
+        /* Leave a 0 at the end.  */
+        aver (0 < conflict_list_free);
+        conflict_list[conflict_list_cnt] = 0;
+        conflict_list_cnt += 1;
+        conflict_list_free -= 1;
       }
 }
 
@@ -221,9 +221,9 @@ conflict_row (state *s)
 | default action (yydefact) for the state.  In addition, ACTROW is  |
 | filled with what to do for each kind of token, index by symbol    |
 | number, with zero meaning do the default action.  The value       |
-| ACTION_NUMBER_MINIMUM, a very negative number, means this        |
-| situation is an error.  The parser recognizes this value         |
-| specially.                                                       |
+| ACTION_NUMBER_MINIMUM, a very negative number, means this         |
+| situation is an error.  The parser recognizes this value          |
+| specially.                                                        |
 |                                                                   |
 | This is where conflicts are resolved.  The loop over lookahead    |
 | rules considered lower-numbered rules last, and the last rule     |
@@ -255,22 +255,22 @@ action_row (state *s)
       int j;
       bitset_iterator biter;
       /* loop over all the rules available here which require
-        lookahead (in reverse order to give precedence to the first
-        rule) */
+         lookahead (in reverse order to give precedence to the first
+         rule) */
       for (i = reds->num - 1; i >= 0; --i)
-       /* and find each token which the rule finds acceptable
-          to come next */
-       BITSET_FOR_EACH (biter, reds->lookahead_tokens[i], j, 0)
-       {
-         /* and record this rule as the rule to use if that
-            token follows.  */
-         if (actrow[j] != 0)
-           {
-             conflicted = true;
-             conflrow[j] = 1;
-           }
-         actrow[j] = rule_number_as_item_number (reds->rules[i]->number);
-       }
+        /* and find each token which the rule finds acceptable
+           to come next */
+        BITSET_FOR_EACH (biter, reds->lookahead_tokens[i], j, 0)
+        {
+          /* and record this rule as the rule to use if that
+             token follows.  */
+          if (actrow[j] != 0)
+            {
+              conflicted = true;
+              conflrow[j] = 1;
+            }
+          actrow[j] = rule_number_as_item_number (reds->rules[i]->number);
+        }
     }
 
   /* Now see which tokens are allowed for shifts in this state.  For
@@ -282,16 +282,16 @@ action_row (state *s)
       state *shift_state = trans->states[i];
 
       if (actrow[sym] != 0)
-       {
-         conflicted = true;
-         conflrow[sym] = 1;
-       }
+        {
+          conflicted = true;
+          conflrow[sym] = 1;
+        }
       actrow[sym] = state_number_as_int (shift_state->number);
 
       /* Do not use any default reduction if there is a shift for
-        error */
+         error */
       if (sym == errtoken->number)
-       nodefault = true;
+        nodefault = true;
     }
 
   /* See which tokens are an explicit error in this state (due to
@@ -308,8 +308,8 @@ action_row (state *s)
      labeled as consistent.  */
   {
     char *default_reductions =
-      muscle_percent_define_get ("lr.default-reductions");
-    if (0 != strcmp (default_reductions, "most") && !s->consistent)
+      muscle_percent_define_get ("lr.default-reduction");
+    if (STRNEQ (default_reductions, "most") && !s->consistent)
       nodefault = true;
     free (default_reductions);
   }
@@ -320,43 +320,43 @@ action_row (state *s)
   if (reds->num >= 1 && !nodefault)
     {
       if (s->consistent)
-       default_reduction = reds->rules[0];
+        default_reduction = reds->rules[0];
       else
-       {
-         int max = 0;
-         for (i = 0; i < reds->num; i++)
-           {
-             int count = 0;
-             rule *r = reds->rules[i];
-             symbol_number j;
-
-             for (j = 0; j < ntokens; j++)
-               if (actrow[j] == rule_number_as_item_number (r->number))
-                 count++;
-
-             if (count > max)
-               {
-                 max = count;
-                 default_reduction = r;
-               }
-           }
-
-         /* GLR parsers need space for conflict lists, so we can't
-            default conflicted entries.  For non-conflicted entries
-            or as long as we are not building a GLR parser,
-            actions that match the default are replaced with zero,
-            which means "use the default". */
-
-         if (max > 0)
-           {
-             int j;
-             for (j = 0; j < ntokens; j++)
-               if (actrow[j]
+        {
+          int max = 0;
+          for (i = 0; i < reds->num; i++)
+            {
+              int count = 0;
+              rule *r = reds->rules[i];
+              symbol_number j;
+
+              for (j = 0; j < ntokens; j++)
+                if (actrow[j] == rule_number_as_item_number (r->number))
+                  count++;
+
+              if (count > max)
+                {
+                  max = count;
+                  default_reduction = r;
+                }
+            }
+
+          /* GLR parsers need space for conflict lists, so we can't
+             default conflicted entries.  For non-conflicted entries
+             or as long as we are not building a GLR parser,
+             actions that match the default are replaced with zero,
+             which means "use the default". */
+
+          if (max > 0)
+            {
+              int j;
+              for (j = 0; j < ntokens; j++)
+                if (actrow[j]
                     == rule_number_as_item_number (default_reduction->number)
-                   && ! (nondeterministic_parser && conflrow[j]))
-                 actrow[j] = 0;
-           }
-       }
+                    && ! (nondeterministic_parser && conflrow[j]))
+                  actrow[j] = 0;
+            }
+        }
     }
 
   /* If have no default reduction, the default is an error.
@@ -365,7 +365,7 @@ action_row (state *s)
   if (!default_reduction)
     for (i = 0; i < ntokens; i++)
       if (actrow[i] == ACTION_NUMBER_MINIMUM)
-       actrow[i] = 0;
+        actrow[i] = 0;
 
   if (conflicted)
     conflict_row (s);
@@ -382,39 +382,34 @@ static void
 save_row (state_number s)
 {
   symbol_number i;
-  int count;
-  base_number *sp;
-  base_number *sp1;
-  base_number *sp2;
-  unsigned int *sp3;
 
   /* Number of non default actions in S.  */
-  count = 0;
+  size_t count = 0;
   for (i = 0; i < ntokens; i++)
     if (actrow[i] != 0)
       count++;
 
-  if (count == 0)
-    return;
-
-  /* Allocate non defaulted actions.  */
-  froms[s] = sp = sp1 = xnmalloc (count, sizeof *sp1);
-  tos[s] = sp2 = xnmalloc (count, sizeof *sp2);
-  conflict_tos[s] = sp3 =
-    nondeterministic_parser ? xnmalloc (count, sizeof *sp3) : NULL;
-
-  /* Store non defaulted actions.  */
-  for (i = 0; i < ntokens; i++)
-    if (actrow[i] != 0)
-      {
-       *sp1++ = i;
-       *sp2++ = actrow[i];
-       if (nondeterministic_parser)
-         *sp3++ = conflrow[i];
-      }
-
-  tally[s] = count;
-  width[s] = sp1[-1] - sp[0] + 1;
+  if (count)
+    {
+      /* Allocate non defaulted actions.  */
+      base_number *sp1 = froms[s] = xnmalloc (count, sizeof *sp1);
+      base_number *sp2 = tos[s] = xnmalloc (count, sizeof *sp2);
+      unsigned int *sp3 = conflict_tos[s] =
+        nondeterministic_parser ? xnmalloc (count, sizeof *sp3) : NULL;
+
+      /* Store non defaulted actions.  */
+      for (i = 0; i < ntokens; i++)
+        if (actrow[i] != 0)
+          {
+            *sp1++ = i;
+            *sp2++ = actrow[i];
+            if (nondeterministic_parser)
+              *sp3++ = conflrow[i];
+          }
+
+      tally[s] = count;
+      width[s] = sp1[-1] - froms[s][0] + 1;
+    }
 }
 
 
@@ -429,10 +424,6 @@ save_row (state_number s)
 static void
 token_actions (void)
 {
-  state_number i;
-  symbol_number j;
-  rule_number r;
-
   int nconflict = nondeterministic_parser ? conflicts_total_count () : 0;
 
   yydefact = xnmalloc (nstates, sizeof *yydefact);
@@ -446,28 +437,34 @@ token_actions (void)
 
   /* Find the rules which are reduced.  */
   if (!nondeterministic_parser)
-    for (r = 0; r < nrules; ++r)
-      rules[r].useful = false;
-
-  for (i = 0; i < nstates; ++i)
     {
-      rule *default_reduction = action_row (states[i]);
-      yydefact[i] = default_reduction ? default_reduction->number + 1 : 0;
-      save_row (i);
-
-      /* Now that the parser was computed, we can find which rules are
-        really reduced, and which are not because of SR or RR
-        conflicts.  */
-      if (!nondeterministic_parser)
-       {
-         for (j = 0; j < ntokens; ++j)
-           if (actrow[j] < 0 && actrow[j] != ACTION_NUMBER_MINIMUM)
-             rules[item_number_as_rule_number (actrow[j])].useful = true;
-         if (yydefact[i])
-           rules[yydefact[i] - 1].useful = true;
-       }
+      rule_number r;
+      for (r = 0; r < nrules; ++r)
+        rules[r].useful = false;
     }
 
+  {
+    state_number i;
+    for (i = 0; i < nstates; ++i)
+      {
+        rule *default_reduction = action_row (states[i]);
+        yydefact[i] = default_reduction ? default_reduction->number + 1 : 0;
+        save_row (i);
+
+        /* Now that the parser was computed, we can find which rules are
+           really reduced, and which are not because of SR or RR
+           conflicts.  */
+        if (!nondeterministic_parser)
+          {
+            symbol_number j;
+            for (j = 0; j < ntokens; ++j)
+              if (actrow[j] < 0 && actrow[j] != ACTION_NUMBER_MINIMUM)
+                rules[item_number_as_rule_number (actrow[j])].useful = true;
+            if (yydefact[i])
+              rules[yydefact[i] - 1].useful = true;
+          }
+      }
+  }
   free (actrow);
   free (conflrow);
 }
@@ -486,72 +483,68 @@ static void
 save_column (symbol_number sym, state_number default_state)
 {
   goto_number i;
-  base_number *sp;
-  base_number *sp1;
-  base_number *sp2;
-  int count;
-  vector_number symno = symbol_number_to_vector_number (sym);
-
   goto_number begin = goto_map[sym - ntokens];
   goto_number end = goto_map[sym - ntokens + 1];
 
   /* Number of non default GOTO.  */
-  count = 0;
+  size_t count = 0;
   for (i = begin; i < end; i++)
     if (to_state[i] != default_state)
       count++;
 
-  if (count == 0)
-    return;
-
-  /* Allocate room for non defaulted gotos.  */
-  froms[symno] = sp = sp1 = xnmalloc (count, sizeof *sp1);
-  tos[symno] = sp2 = xnmalloc (count, sizeof *sp2);
-
-  /* Store the state numbers of the non defaulted gotos.  */
-  for (i = begin; i < end; i++)
-    if (to_state[i] != default_state)
-      {
-       *sp1++ = from_state[i];
-       *sp2++ = to_state[i];
-      }
-
-  tally[symno] = count;
-  width[symno] = sp1[-1] - sp[0] + 1;
+  if (count)
+    {
+      /* Allocate room for non defaulted gotos.  */
+      vector_number symno = symbol_number_to_vector_number (sym);
+      base_number *sp1 = froms[symno] = xnmalloc (count, sizeof *sp1);
+      base_number *sp2 = tos[symno] = xnmalloc (count, sizeof *sp2);
+
+      /* Store the state numbers of the non defaulted gotos.  */
+      for (i = begin; i < end; i++)
+        if (to_state[i] != default_state)
+          {
+            *sp1++ = from_state[i];
+            *sp2++ = to_state[i];
+          }
+
+      tally[symno] = count;
+      width[symno] = sp1[-1] - froms[symno][0] + 1;
+    }
 }
 
 
-/*-------------------------------------------------------------.
-| Return `the' most common destination GOTO on SYM (a nterm).  |
-`-------------------------------------------------------------*/
+/*----------------------------------------------------------------.
+| The default state for SYM: the state which is 'the' most common |
+| GOTO destination on SYM (an nterm).                             |
+`----------------------------------------------------------------*/
 
 static state_number
 default_goto (symbol_number sym, size_t state_count[])
 {
-  state_number s;
-  goto_number i;
-  goto_number m = goto_map[sym - ntokens];
-  goto_number n = goto_map[sym - ntokens + 1];
-  state_number default_state = -1;
-  size_t max = 0;
-
-  if (m == n)
-    return -1;
-
-  for (s = 0; s < nstates; s++)
-    state_count[s] = 0;
-
-  for (i = m; i < n; i++)
-    state_count[to_state[i]]++;
-
-  for (s = 0; s < nstates; s++)
-    if (state_count[s] > max)
-      {
-       max = state_count[s];
-       default_state = s;
-      }
+  goto_number begin = goto_map[sym - ntokens];
+  goto_number end = goto_map[sym - ntokens + 1];
+  state_number res = -1;
 
-  return default_state;
+  if (begin != end)
+    {
+      size_t max = 0;
+      goto_number i;
+      state_number s;
+
+      for (s = 0; s < nstates; s++)
+        state_count[s] = 0;
+
+      for (i = begin; i < end; i++)
+        state_count[to_state[i]]++;
+
+      for (s = 0; s < nstates; s++)
+        if (max < state_count[s])
+          {
+            max = state_count[s];
+            res = s;
+          }
+    }
+  return res;
 }
 
 
@@ -596,29 +589,29 @@ sort_actions (void)
   nentries = 0;
 
   for (i = 0; i < nvectors; i++)
-    if (tally[i] > 0)
+    if (0 < tally[i])
       {
-       int k;
-       int t = tally[i];
-       int w = width[i];
-       int j = nentries - 1;
+        int k;
+        size_t t = tally[i];
+        int w = width[i];
+        int j = nentries - 1;
 
-       while (j >= 0 && (width[order[j]] < w))
-         j--;
+        while (0 <= j && width[order[j]] < w)
+          j--;
 
-       while (j >= 0 && (width[order[j]] == w) && (tally[order[j]] < t))
-         j--;
+        while (0 <= j && width[order[j]] == w && tally[order[j]] < t)
+          j--;
 
-       for (k = nentries - 1; k > j; k--)
-         order[k + 1] = order[k];
+        for (k = nentries - 1; k > j; k--)
+          order[k + 1] = order[k];
 
-       order[j + 1] = i;
-       nentries++;
+        order[j + 1] = i;
+        nentries++;
       }
 }
 
 
-/* If VECTOR is a state which actions (reflected by FROMS, TOS, TALLY
+/* If VECTOR is a state whose actions (reflected by FROMS, TOS, TALLY
    and WIDTH of VECTOR) are common to a previous state, return this
    state number.
 
@@ -628,46 +621,43 @@ static state_number
 matching_state (vector_number vector)
 {
   vector_number i = order[vector];
-  int t;
-  int w;
-  int prev;
-
   /* If VECTOR is a nterm, return -1.  */
-  if (nstates <= i)
-    return -1;
-
-  t = tally[i];
-  w = width[i];
-
-  /* If VECTOR has GLR conflicts, return -1 */
-  if (conflict_tos[i] != NULL)
-    {
-      int j;
-      for (j = 0; j < t; j += 1)
-       if (conflict_tos[i][j] != 0)
-         return -1;
-    }
-
-  for (prev = vector - 1; prev >= 0; prev--)
+  if (i < nstates)
     {
-      vector_number j = order[prev];
-      int k;
-      int match = 1;
-
-      /* Given how ORDER was computed, if the WIDTH or TALLY is
-        different, there cannot be a matching state.  */
-      if (width[j] != w || tally[j] != t)
-       return -1;
-
-      for (k = 0; match && k < t; k++)
-       if (tos[j][k] != tos[i][k] || froms[j][k] != froms[i][k]
-           || (conflict_tos[j] != NULL && conflict_tos[j][k] != 0))
-         match = 0;
-
-      if (match)
-       return j;
+      size_t t = tally[i];
+      int w = width[i];
+      int prev;
+
+      /* If VECTOR has GLR conflicts, return -1 */
+      if (conflict_tos[i] != NULL)
+        {
+          int j;
+          for (j = 0; j < t; j += 1)
+            if (conflict_tos[i][j] != 0)
+              return -1;
+        }
+
+      for (prev = vector - 1; 0 <= prev; prev--)
+        {
+          vector_number j = order[prev];
+          /* Given how ORDER was computed, if the WIDTH or TALLY is
+             different, there cannot be a matching state.  */
+          if (width[j] != w || tally[j] != t)
+            return -1;
+          else
+            {
+              bool match = true;
+              int k;
+              for (k = 0; match && k < t; k++)
+                if (tos[j][k] != tos[i][k]
+                    || froms[j][k] != froms[i][k]
+                    || (conflict_tos[j] != NULL && conflict_tos[j][k] != 0))
+                  match = false;
+              if (match)
+                return j;
+            }
+        }
     }
-
   return -1;
 }
 
@@ -675,57 +665,59 @@ matching_state (vector_number vector)
 static base_number
 pack_vector (vector_number vector)
 {
+  base_number res;
   vector_number i = order[vector];
-  int j;
-  int t = tally[i];
-  int loc = 0;
+  size_t t = tally[i];
   base_number *from = froms[i];
   base_number *to = tos[i];
   unsigned int *conflict_to = conflict_tos[i];
 
   aver (t != 0);
 
-  for (j = lowzero - from[0]; ; j++)
+  for (res = lowzero - from[0]; ; res++)
     {
-      int k;
       bool ok = true;
-
-      aver (j < table_size);
-
-      for (k = 0; ok && k < t; k++)
-       {
-         loc = j + state_number_as_int (from[k]);
-         if (table_size <= loc)
-           table_grow (loc);
-
-         if (table[loc] != 0)
-           ok = false;
-       }
-
-      for (k = 0; ok && k < vector; k++)
-       if (pos[k] == j)
-         ok = false;
+      aver (res < table_size);
+      {
+        int k;
+        for (k = 0; ok && k < t; k++)
+          {
+            int loc = res + state_number_as_int (from[k]);
+            if (table_size <= loc)
+              table_grow (loc);
+
+            if (table[loc] != 0)
+              ok = false;
+          }
+
+        if (ok)
+          for (k = 0; k < vector; k++)
+            if (pos[k] == res)
+              ok = false;
+      }
 
       if (ok)
-       {
-         for (k = 0; k < t; k++)
-           {
-             loc = j + from[k];
-             table[loc] = to[k];
-             if (nondeterministic_parser && conflict_to != NULL)
-               conflict_table[loc] = conflict_to[k];
-             check[loc] = from[k];
-           }
-
-         while (table[lowzero] != 0)
-           lowzero++;
-
-         if (loc > high)
-           high = loc;
-
-         aver (BASE_MINIMUM <= j && j <= BASE_MAXIMUM);
-         return j;
-       }
+        {
+          int loc;
+          int k;
+          for (k = 0; k < t; k++)
+            {
+              loc = res + state_number_as_int (from[k]);
+              table[loc] = to[k];
+              if (nondeterministic_parser && conflict_to != NULL)
+                conflict_table[loc] = conflict_to[k];
+              check[loc] = from[k];
+            }
+
+          while (table[lowzero] != 0)
+            lowzero++;
+
+          if (high < loc)
+            high = loc;
+
+          aver (BASE_MINIMUM <= res && res <= BASE_MAXIMUM);
+          return res;
+        }
     }
 }
 
@@ -783,11 +775,11 @@ pack_table (void)
       base_number place;
 
       if (s < 0)
-       /* A new set of state actions, or a nonterminal.  */
-       place = pack_vector (i);
+        /* A new set of state actions, or a nonterminal.  */
+        place = pack_vector (i);
       else
-       /* Action of I were already coded for S.  */
-       place = base[s];
+        /* Action of I were already coded for S.  */
+        place = base[s];
 
       pos[i] = place;
       base[order[i]] = place;
@@ -816,7 +808,7 @@ tables_generate (void)
      correlated.  In particular the signedness is not taken into
      account.  But it's not useless.  */
   verify (sizeof nstates <= sizeof nvectors
-         && sizeof nvars <= sizeof nvectors);
+          && sizeof nvars <= sizeof nvectors);
 
   nvectors = state_number_as_int (nstates) + nvars;
 
index 2278db59134a495c2b7c84af4176f22e87b77a74..161b24d4ea957ef8cbc1d3ee4b10a87ef4af2a14 100644 (file)
@@ -80,7 +80,7 @@ uniqstr_assert (char const *str)
   if (!hash_lookup (uniqstrs_table, str))
     {
       error (0, 0,
-            "not a uniqstr: %s", quotearg (str));
+             "not a uniqstr: %s", quotearg (str));
       abort ();
     }
 }
@@ -103,7 +103,17 @@ uniqstr_print_processor (void *ustr, void *null ATTRIBUTE_UNUSED)
   return uniqstr_print (ustr);
 }
 
-\f
+
+int
+uniqstr_cmp(uniqstr l, uniqstr r)
+{
+  return (l == r ? 0
+          : !l ? -1
+          : !r ? +1
+          : strcmp (l, r));
+}
+
+
 /*-----------------------.
 | A uniqstr hash table.  |
 `-----------------------*/
@@ -111,7 +121,7 @@ uniqstr_print_processor (void *ustr, void *null ATTRIBUTE_UNUSED)
 static bool
 hash_compare_uniqstr (void const *m1, void const *m2)
 {
-  return strcmp (m1, m2) == 0;
+  return STREQ (m1, m2);
 }
 
 static size_t
@@ -120,6 +130,7 @@ hash_uniqstr (void const *m, size_t tablesize)
   return hash_string (m, tablesize);
 }
 
+
 /*----------------------------.
 | Create the uniqstrs table.  |
 `----------------------------*/
@@ -128,10 +139,10 @@ void
 uniqstrs_new (void)
 {
   uniqstrs_table = hash_initialize (HT_INITIAL_CAPACITY,
-                                   NULL,
-                                   hash_uniqstr,
-                                   hash_compare_uniqstr,
-                                   free);
+                                    NULL,
+                                    hash_uniqstr,
+                                    hash_compare_uniqstr,
+                                    free);
 }
 
 
index d3178d7fb2bbf38edadf65113afcb6131aed5084..143f7aae3ed725d79f43669cc0eb4f55a4e54146 100644 (file)
@@ -36,28 +36,15 @@ uniqstr uniqstr_vsprintf (char const *format, ...)
   __attribute__ ((__format__ (__printf__, 1, 2)));
 
 /* Two uniqstr values have the same value iff they are the same.  */
-#define UNIQSTR_EQ(USTR1, USTR2) (!!((USTR1) == (USTR2)))
+# define UNIQSTR_EQ(Ustr1, Ustr2) (!!((Ustr1) == (Ustr2)))
 
 /* Compare two uniqstr a la strcmp: negative for <, nul for =, and
    positive for >.  Undefined order, relies on addresses.  */
-#define UNIQSTR_CMP(USTR1, USTR2) ((USTR1) - (USTR2))
-
-/*--------------------------------------.
-| Initializing, destroying, debugging.  |
-`--------------------------------------*/
-
-/* Create the string table.  */
-void uniqstrs_new (void);
+int uniqstr_cmp(uniqstr u1, uniqstr u2);
 
 /* Die if STR is not a uniqstr.  */
 void uniqstr_assert (char const *str);
 
-/* Free all the memory allocated for symbols.  */
-void uniqstrs_free (void);
-
-/* Report them all.  */
-void uniqstrs_print (void);
-
 /*----------------.
 | Concatenation.  |
 `----------------*/
@@ -69,30 +56,43 @@ void uniqstrs_print (void);
    checking.  Unfortunately, because of the missing format string in the
    macro invocation, the argument number reported by gcc for a bad
    argument type is 1 too large.  */
-#define UNIQSTR_CONCAT(...)                                            \
-  uniqstr_vsprintf (UNIQSTR_GEN_FORMAT (__VA_ARGS__,                   \
-                                        "%s", "%s", "%s", "%s", "%s",  \
-                                        "%s", "%s", "%s", "%s", "%s",  \
-                                        "%s", "%s", "%s", "%s", "%s",  \
-                                        "%s", "%s", "%s", "%s", "%s"), \
+# define UNIQSTR_CONCAT(...)                                            \
+  uniqstr_vsprintf (UNIQSTR_GEN_FORMAT (__VA_ARGS__,                    \
+                                        "%s", "%s", "%s", "%s", "%s",   \
+                                        "%s", "%s", "%s", "%s", "%s",   \
+                                        "%s", "%s", "%s", "%s", "%s",   \
+                                        "%s", "%s", "%s", "%s", "%s"),  \
                     __VA_ARGS__)
 
-#define UNIQSTR_GEN_FORMAT(F1,  F2,  F3,  F4,  F5,  \
-                           F6,  F7,  F8,  F9,  F10, \
-                           F11, F12, F13, F14, F15, \
-                           F16, F17, F18, F19, F20, \
-                           ...)                     \
-  UNIQSTR_GEN_FORMAT_ (__VA_ARGS__,                 \
-                       "", "", "", "", "",          \
-                       "", "", "", "", "",          \
-                       "", "", "", "", "",          \
+# define UNIQSTR_GEN_FORMAT(F1,  F2,  F3,  F4,  F5,     \
+                           F6,  F7,  F8,  F9,  F10,     \
+                           F11, F12, F13, F14, F15,     \
+                           F16, F17, F18, F19, F20,     \
+                           ...)                         \
+  UNIQSTR_GEN_FORMAT_ (__VA_ARGS__,                     \
+                       "", "", "", "", "",              \
+                       "", "", "", "", "",              \
+                       "", "", "", "", "",              \
                        "", "", "", "", "")
 
-#define UNIQSTR_GEN_FORMAT_(F1,  F2,  F3,  F4,  F5,       \
-                            F6,  F7,  F8,  F9,  F10,      \
-                            F11, F12, F13, F14, F15,      \
-                            F16, F17, F18, F19, F20, ...) \
-  F1  F2  F3  F4  F5  F6  F7  F8  F9  F10                 \
+# define UNIQSTR_GEN_FORMAT_(F1,  F2,  F3,  F4,  F5,            \
+                            F6,  F7,  F8,  F9,  F10,            \
+                            F11, F12, F13, F14, F15,            \
+                            F16, F17, F18, F19, F20, ...)       \
+  F1  F2  F3  F4  F5  F6  F7  F8  F9  F10                       \
   F11 F12 F13 F14 F15 F16 F17 F18 F19 F20
 
+/*--------------------.
+| Table of uniqstrs.  |
+`--------------------*/
+
+/* Create the string table.  */
+void uniqstrs_new (void);
+
+/* Free all the memory allocated for symbols.  */
+void uniqstrs_free (void);
+
+/* Report them all.  */
+void uniqstrs_print (void);
+
 #endif /* ! defined UNIQSTR_H_ */
index 26cb0918d38d756b7c2a3f82226551f6facee47e..9e087dd343b67ac58a7f54e08335ac62fc33ed53 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 26cb0918d38d756b7c2a3f82226551f6facee47e
+Subproject commit 9e087dd343b67ac58a7f54e08335ac62fc33ed53
index 0d5d32c62d95cd2e0c0cbbe41532615ece872c68..70ae9c31c46ae7d89033a21861d8fc3d532453fd 100644 (file)
@@ -7,9 +7,6 @@
 /calc
 /calc.[chy]
 /calc.tab.*
-/Makefile
-/Makefile.in
-/Makefile.in
 /package.m4
 /testsuite
 /testsuite.dir
diff --git a/tests/Makefile.am b/tests/Makefile.am
deleted file mode 100644 (file)
index a11adde..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-## Process this file with automake to create Makefile.in.
-
-## Makefile for Bison testsuite.
-
-## Copyright (C) 2000-2013 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/>.
-
-EXTRA_DIST = $(TESTSUITE_AT) testsuite package.m4
-
-DISTCLEANFILES       = atconfig $(check_SCRIPTS)
-MAINTAINERCLEANFILES = Makefile.in $(TESTSUITE)
-
-## ------------ ##
-## package.m4.  ##
-## ------------ ##
-
-$(srcdir)/package.m4: $(top_srcdir)/configure
-       $(AM_V_GEN) { \
-         echo '# Signature of the current package.'; \
-         echo 'm4_define([AT_PACKAGE_NAME],      [$(PACKAGE_NAME)])'; \
-         echo 'm4_define([AT_PACKAGE_TARNAME],   [$(PACKAGE_TARNAME)])'; \
-         echo 'm4_define([AT_PACKAGE_VERSION],   [$(PACKAGE_VERSION)])'; \
-         echo 'm4_define([AT_PACKAGE_STRING],    [$(PACKAGE_STRING)])'; \
-         echo 'm4_define([AT_PACKAGE_BUGREPORT], [$(PACKAGE_BUGREPORT)])'; \
-       } >$@.tmp
-       $(AM_V_at) mv $@.tmp $@
-
-## ------------ ##
-## Test suite.  ##
-## ------------ ##
-
-TESTSUITE_AT = \
-       local.at \
-       testsuite.at \
-       input.at named-refs.at \
-       output.at skeletons.at sets.at reduce.at \
-       synclines.at headers.at actions.at conflicts.at \
-       calc.at \
-        torture.at existing.at regression.at \
-        c++.at \
-        java.at \
-       cxx-type.at glr-regression.at \
-       push.at
-
-TESTSUITE = $(srcdir)/testsuite
-
-AUTOTEST = $(AUTOM4TE) --language=autotest
-$(TESTSUITE): $(srcdir)/package.m4 $(TESTSUITE_AT)
-       $(AM_V_GEN) $(AUTOTEST) -I $(srcdir) testsuite.at -o $@.tmp
-       $(AM_V_at) mv $@.tmp $@
-
-atconfig: $(top_builddir)/config.status
-       cd $(top_builddir) && ./config.status tests/$@
-
-clean-local:
-       test ! -f $(TESTSUITE) || $(SHELL) $(TESTSUITE) --clean
-
-check-local: atconfig atlocal $(TESTSUITE)
-       $(SHELL) $(TESTSUITE) $(TESTSUITEFLAGS)
-
-check_SCRIPTS = bison
-
-# Run the test suite on the *installed* tree.
-installcheck-local: atconfig atlocal $(TESTSUITE)
-       $(TESTSUITE) AUTOTEST_PATH="$(bindir)" $(TESTSUITEFLAGS)
-
-# Be real mean with it.
-.PHONY: maintainer-check-g++
-maintainer-check-g++: atconfig atlocal $(TESTSUITE)
-       $(TESTSUITE) $(TESTSUITEFLAGS) --compile-c-with-cxx
-
-.PHONY: maintainer-check-posix
-maintainer-check-posix: atconfig atlocal $(TESTSUITE)
-       $(TESTSUITE) $(TESTSUITEFLAGS) POSIXLY_CORRECT=1 _POSIX2_VERSION=200112
-
-.PHONY: maintainer-check-valgrind
-maintainer-check-valgrind: atconfig atlocal $(TESTSUITE)
-       test -z '$(VALGRIND)' ||                                        \
-         $(TESTSUITE) $(TESTSUITEFLAGS)                                \
-         PREBISON='$(VALGRIND_PREBISON)' PREPARSER='$(VALGRIND) -q'    \
-         VALGRIND_OPTS='--leak-check=full --show-reachable=yes'
-
-.PHONY: maintainer-check
-maintainer-check: maintainer-check-posix maintainer-check-valgrind maintainer-check-g++
-
-.PHONY: maintainer-push-check
-maintainer-push-check:
-       BISON_USE_PUSH_FOR_PULL=1 $(MAKE) $(AM_MAKEFLAGS) maintainer-check
-
-.PHONY: maintainer-xml-check
-maintainer-xml-check:
-       BISON_TEST_XML=1 $(MAKE) $(AM_MAKEFLAGS) maintainer-check
-
-.PHONY: maintainer-release-check
-maintainer-release-check: maintainer-check maintainer-push-check maintainer-xml-check
index 35e49c564120e20f6da3181c17969b9271e4bf5e..b1695132b0124f3af391d624bb7b67e1abe290ce 100644 (file)
@@ -1,4 +1,4 @@
-# Executing Actions.                               -*- Autotest -*-
+e# Executing Actions.                               -*- Autotest -*-
 
 # Copyright (C) 2001-2013 Free Software Foundation, Inc.
 
@@ -30,12 +30,12 @@ AT_SETUP([Mid-rule actions])
 
 AT_BISON_OPTION_PUSHDEFS
 AT_DATA_GRAMMAR([[input.y]],
-[[%error-verbose
+[[%define parse.error verbose
 %debug
-%{
+%code {
 ]AT_YYERROR_DECLARE[
 ]AT_YYLEX_DECLARE[
-%}
+}
 %%
 exp:     { putchar ('0'); }
      '1' { putchar ('1'); }
@@ -52,11 +52,7 @@ exp:     { putchar ('0'); }
 %%
 ]AT_YYERROR_DEFINE[
 ]AT_YYLEX_DEFINE(["123456789"])[
-int
-main (void)
-{
-  return yyparse ();
-}
+]AT_MAIN_DEFINE[
 ]])
 AT_BISON_OPTION_POPDEFS
 
@@ -68,6 +64,119 @@ AT_PARSER_CHECK([./input], 0,
 
 AT_CLEANUP
 
+## ----------------------- ##
+## Implicitly empty rule.  ##
+## ----------------------- ##
+
+AT_SETUP([Implicitly empty rule])
+
+AT_DATA_GRAMMAR([[1.y]],
+[[%%
+exp: a b;
+a: /* empty. */ {};
+// A mid-rule action does not count as an empty rule.
+b: {} {};
+]])
+
+AT_BISON_CHECK([-fcaret -Wempty-rule 1.y], [0], [],
+[[1.y:11.17-18: warning: empty rule without %empty [-Wempty-rule]
+ a: /* empty. */ {};
+                 ^^
+]])
+
+AT_DATA_GRAMMAR([[2.y]],
+[[%%
+exp: a b c;
+a: /* empty. */ {};
+b: %empty       {};
+c: /* empty. */ {};
+]])
+
+AT_BISON_CHECK([-fcaret 2.y], [0], [],
+[[2.y:11.17-18: warning: empty rule without %empty [-Wempty-rule]
+ a: /* empty. */ {};
+                 ^^
+2.y:13.17-18: warning: empty rule without %empty [-Wempty-rule]
+ c: /* empty. */ {};
+                 ^^
+]])
+
+AT_BISON_CHECK([-fcaret -Wno-empty-rule 2.y], [0])
+
+AT_CLEANUP
+
+## ------------------------ ##
+## Invalid uses of %empty.  ##
+## ------------------------ ##
+
+AT_SETUP([Invalid uses of %empty])
+
+AT_DATA_GRAMMAR([[one.y]],
+[[%%
+exp:
+  %empty {} %empty
+;
+]])
+
+AT_BISON_CHECK([-fcaret one.y], [1], [],
+[[one.y:11.13-18: error: only one %empty allowed per rule
+   %empty {} %empty
+             ^^^^^^
+one.y:11.3-8: previous declaration
+   %empty {} %empty
+   ^^^^^^
+]])
+
+AT_DATA_GRAMMAR([[two.y]],
+[[%%
+exp:
+  'a' %empty    {}
+| %empty 'a'    {}
+| %empty {}     {}
+;
+]])
+
+AT_BISON_CHECK([-fcaret two.y], [1], [],
+[[two.y:11.7-12: error: %empty on non-empty rule
+   'a' %empty    {}
+       ^^^^^^
+two.y:12.3-8: error: %empty on non-empty rule
+ | %empty 'a'    {}
+   ^^^^^^
+two.y:13.3-8: error: %empty on non-empty rule
+ | %empty {}     {}
+   ^^^^^^
+]])
+
+AT_CLEANUP
+
+## ---------------------- ##
+## Valid uses of %empty.  ##
+## ---------------------- ##
+
+AT_SETUP([Valid uses of %empty])
+
+AT_BISON_OPTION_PUSHDEFS
+AT_DATA_GRAMMAR([[input.y]],
+[[
+%debug
+%code
+{
+]AT_YYERROR_DECLARE[
+]AT_YYLEX_DECLARE[
+}
+%%
+exp: %empty {}
+%%
+]AT_YYERROR_DEFINE[
+]AT_YYLEX_DEFINE[
+]AT_MAIN_DEFINE[
+]])
+
+AT_FULL_COMPILE([input])
+AT_PARSER_CHECK([./input])
+AT_BISON_OPTION_POPDEFS
+AT_CLEANUP
 
 ## ------------------ ##
 ## Initial location.  ##
@@ -81,8 +190,7 @@ m4_pushdef([AT_TEST],
 
 AT_BISON_OPTION_PUSHDEFS([%locations %skeleton "$1" $2])
 AT_DATA_GRAMMAR([[input.y]],
-[[%defines /* FIXME: Required by lalr1.cc in Bison 2.6. */
-%locations
+[[%locations
 %debug
 %skeleton "$1"
 ]$2[
@@ -96,7 +204,7 @@ AT_DATA_GRAMMAR([[input.y]],
 }
 %%
 exp: { ]AT_SKEL_CC_IF([[std::cerr << @$ << std::endl]],
-                      [[YY_LOCATION_PRINT(stderr, @$); fputc ('\n', stderr)]])[; }
+                      [[LOCATION_PRINT(stderr, @$); fputc ('\n', stderr)]])[; }
 %%
 ]AT_YYERROR_DEFINE[
 
@@ -150,7 +258,7 @@ AT_TEST([glr.cc])
 AT_TEST([yacc.c], [%define api.pure full],
 [[%{
 # define YYLTYPE int
-# define YY_LOCATION_PRINT(Stream, Loc)      \
+# define LOCATION_PRINT(Stream, Loc)      \
    (void) (Loc)
 # define YYLLOC_DEFAULT(Current, Rhs, N)    \
   (Current) = ((Rhs)[N ? 1 : 0])
@@ -161,7 +269,7 @@ AT_TEST([yacc.c], [%define api.pure full],
 AT_TEST([yacc.c], [%define api.pure full],
 [[%{
 # define YYLTYPE int
-# define YY_LOCATION_PRINT(Stream, Loc)      \
+# define LOCATION_PRINT(Stream, Loc)      \
     fprintf ((Stream), "%d", (Loc))
 # define YYLLOC_DEFAULT(Current, Rhs, N)    \
   (Current) = ((Rhs)[N ? 1 : 0])
@@ -186,21 +294,18 @@ m4_pushdef([AT_TEST],
 
 AT_BISON_OPTION_PUSHDEFS([%locations %skeleton "$1" $2])
 AT_DATA_GRAMMAR([[input.y]],
-[[%defines /* FIXME: Required by lalr1.cc in Bison 2.6. */
-%locations
+[[%locations
 %debug
 %skeleton "$1"
 ]$2[
 ]$3[
 %code
 {
-# include <stdio.h>
-# include <stdlib.h> /* getenv */
 ]AT_YYERROR_DECLARE[
 ]AT_YYLEX_DECLARE[
 }
 %%
-exp:;
+exp: %empty;
 %%
 ]AT_YYERROR_DEFINE[
 ]AT_YYLEX_DEFINE[
@@ -208,12 +313,15 @@ exp:;
 int
 main (void)
 {
+  ]AT_YYLTYPE[ loc;
+]AT_GLR_CC_IF([loc.initialize();])[
 #define TEST(L1, C1, L2, C2)          \
-  ]AT_LOC_FIRST_LINE[ = L1;           \
-  ]AT_LOC_FIRST_COLUMN[ = C1;         \
-  ]AT_LOC_LAST_LINE[ = L2;            \
-  ]AT_LOC_LAST_COLUMN[ = C2;          \
-  ]YY_LOCATION_PRINT(stdout, AT_LOC)[;\
+  loc.]AT_FIRST_LINE[ = L1;           \
+  loc.]AT_FIRST_COLUMN[ = C1;         \
+  loc.]AT_LAST_LINE[ = L2;            \
+  loc.]AT_LAST_COLUMN[ = C2;          \
+  ]AT_SKEL_CC_IF([std::cout << loc],
+                 [LOCATION_PRINT(stdout, loc)])[;\
   putchar ('\n');
 
   TEST(1, 1, 1, 1);
@@ -243,8 +351,8 @@ AT_CLEANUP
 ## FIXME: test Java, and iterate over skeletons.
 AT_TEST([yacc.c])
 AT_TEST([glr.c])
-#AT_TEST([lalr1.cc])
-#AT_TEST([glr.cc])
+AT_TEST([lalr1.cc])
+AT_TEST([glr.cc])
 
 m4_popdef([AT_TEST])
 
@@ -258,13 +366,13 @@ AT_SETUP([Exotic Dollars])
 
 AT_BISON_OPTION_PUSHDEFS
 AT_DATA_GRAMMAR([[input.y]],
-[[%error-verbose
+[[%define parse.error verbose
 %debug
-%{
+%code {
 ]AT_YYERROR_DECLARE[
 ]AT_YYLEX_DECLARE[
 # define USE(Var)
-%}
+}
 
 %union
 {
@@ -295,11 +403,7 @@ sum_of_the_five_previous_values:
 %%
 ]AT_YYERROR_DEFINE[
 ]AT_YYLEX_DEFINE[
-int
-main (void)
-{
-  return yyparse ();
-}
+]AT_MAIN_DEFINE[
 ]])
 
 AT_BISON_CHECK([-d -v -o input.c input.y], 0)
@@ -314,7 +418,6 @@ AT_PARSER_CHECK([./input], 0,
 AT_DATA_GRAMMAR([[input.y]],
 [[
 %{
-#include <stdio.h>
 ]AT_YYERROR_DECLARE[
 ]AT_YYLEX_DECLARE[
   typedef struct { int val; } stype;
@@ -330,11 +433,7 @@ sum: { printf ("%d\n", $0.val + $-1.val + $-2.val); } ;
 %%
 ]AT_YYERROR_DEFINE[
 ]AT_YYLEX_DEFINE[
-int
-main (void)
-{
-  return yyparse ();
-}
+]AT_MAIN_DEFINE[
 ]])
 
 AT_FULL_COMPILE([input])
@@ -429,7 +528,7 @@ AT_LALR1_CC_IF([typedef yy::location YYLTYPE;])[
 %%
 /*
    This grammar is made to exercise error recovery.
-   "Lines" starting with `(' support error recovery, with
+   "Lines" starting with '(' support error recovery, with
    ')' as synchronizing token.  Lines starting with 'x' can never
    be recovered from if in error.
 */
@@ -482,7 +581,7 @@ line:
       $$ = -1;
       V(line,  $$, @$, ": ");
       V('(',   $1, @1, " ");
-      fprintf (stderr, "error (@%d-%d) ", RANGE (@2));
+      fprintf (stderr, "error (@%d-%d) ", RANGE(@2));
       V(')',   $3, @3, "\n");
     }
 ;
@@ -592,7 +691,7 @@ Successful parse.
 
 # Syntax errors caught by the parser
 # ----------------------------------
-# Exercise the discarding of stack top and input until `error'
+# Exercise the discarding of stack top and input until 'error'
 # can be reduced.
 #
 #     '(', 'x', 'x', 'x', 'x', 'x', ')',
@@ -738,7 +837,7 @@ m4_define([AT_CHECK_PRINTER_AND_DESTRUCTOR],
 
 $3
 _AT_CHECK_PRINTER_AND_DESTRUCTOR($[1], $[2], $[3], $[4],
-[%error-verbose
+[%define parse.error verbose
 %debug
 %verbose
 %locations
@@ -749,13 +848,13 @@ AT_CLEANUP
 
 
 AT_CHECK_PRINTER_AND_DESTRUCTOR([])
-AT_CHECK_PRINTER_AND_DESTRUCTOR([], [ with union])
+AT_CHECK_PRINTER_AND_DESTRUCTOR([], [with union])
 
 AT_CHECK_PRINTER_AND_DESTRUCTOR([%defines %skeleton "lalr1.cc"])
-AT_CHECK_PRINTER_AND_DESTRUCTOR([%defines %skeleton "lalr1.cc"], [ with union])
+AT_CHECK_PRINTER_AND_DESTRUCTOR([%defines %skeleton "lalr1.cc"], [with union])
 
 AT_CHECK_PRINTER_AND_DESTRUCTOR([%glr-parser])
-AT_CHECK_PRINTER_AND_DESTRUCTOR([%glr-parser], [ with union])
+AT_CHECK_PRINTER_AND_DESTRUCTOR([%glr-parser], [with union])
 
 
 
@@ -767,19 +866,17 @@ AT_CHECK_PRINTER_AND_DESTRUCTOR([%glr-parser], [ with union])
 # called for $end, and that $$ and @$ work correctly.
 
 AT_SETUP([Default tagless %printer and %destructor])
-AT_BISON_OPTION_PUSHDEFS([%locations])
+AT_BISON_OPTION_PUSHDEFS([%locations %debug])
 AT_DATA_GRAMMAR([[input.y]],
-[[%error-verbose
+[[%define parse.error verbose
 %debug
 %locations
 
-%{
-# include <stdio.h>
-# include <stdlib.h>
+%code {
 ]AT_YYLEX_DECLARE[
 ]AT_YYERROR_DECLARE[
 # define USE(SYM)
-%}
+}
 
 %printer {
   fprintf (yyoutput, "<*> printer should not be called.\n");
@@ -810,18 +907,15 @@ start: 'a' 'b' 'c' 'd' 'e' { $$ = 'S'; USE(($1, $2, $3, $4, $5)); } ;
 %%
 ]AT_YYERROR_DEFINE[
 ]AT_YYLEX_DEFINE(["abcd"], [[yylval = res]])[
-
-int
-main (void)
-{
-  yydebug = 1;
-  return yyparse ();
-}
+]AT_MAIN_DEFINE[
 ]])
 
-AT_BISON_CHECK([-o input.c input.y])
+AT_BISON_CHECK([-o input.c input.y], [], [],
+[[input.y:30.3-5: warning: useless %destructor for type <*> [-Wother]
+input.y:30.3-5: warning: useless %printer for type <*> [-Wother]
+]])
 AT_COMPILE([input])
-AT_PARSER_CHECK([./input], 1,
+AT_PARSER_CHECK([./input --debug], 1,
 [[<> destructor for 'd' @ 4.
 'b'/'c' destructor for 'c' @ 3.
 'b'/'c' destructor for 'b' @ 2.
@@ -865,14 +959,12 @@ AT_CLEANUP
 ## ------------------------------------------------------ ##
 
 AT_SETUP([Default tagged and per-type %printer and %destructor])
-AT_BISON_OPTION_PUSHDEFS
+AT_BISON_OPTION_PUSHDEFS([%debug])
 AT_DATA_GRAMMAR([[input.y]],
-[[%error-verbose
+[[%define parse.error verbose
 %debug
 
 %{
-# include <stdio.h>
-# include <stdlib.h>
 ]AT_YYERROR_DECLARE[
 ]AT_YYLEX_DECLARE[
 # define USE(SYM)
@@ -922,18 +1014,15 @@ start:
 %%
 ]AT_YYERROR_DEFINE[
 ]AT_YYLEX_DEFINE(["abcdef"])[
-
-int
-main (void)
-{
-  yydebug = 1;
-  return yyparse ();
-}
+]AT_MAIN_DEFINE[
 ]])
 
-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,
+AT_PARSER_CHECK([./input --debug], 1,
 [[<*>/<field2>/e destructor.
 <*>/<field2>/e destructor.
 'd' destructor.
@@ -990,26 +1079,24 @@ AT_CLEANUP
 
 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_BISON_OPTION_PUSHDEFS([%locations %debug])
 AT_DATA_GRAMMAR([[input]]$1[[.y]],
-[[%error-verbose
+[[%define parse.error verbose
 %debug
 %locations
 
-%{
-# include <stdio.h>
-# include <stdlib.h>
+%code {
 ]AT_YYERROR_DECLARE[
 ]AT_YYLEX_DECLARE[
 # define USE(SYM)
-%}
+}
 
 %destructor {
   fprintf (yyoutput, "<]]not_kind[[> destructor should not be called.\n");
@@ -1037,7 +1124,7 @@ AT_DATA_GRAMMAR([[input]]$1[[.y]],
 start: { $$ = 'S'; } ;
 
 %%
-
+#include <stdlib.h> /* abort */
 static int
 yylex (void)
 {
@@ -1050,25 +1137,28 @@ yylex (void)
   return 0;
 }
 ]AT_YYERROR_DEFINE[
-
-int
-main (void)
-{
-  yydebug = 1;
-  return yyparse ();
-}
+]AT_MAIN_DEFINE[
 ]])
 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:30.3-5: warning: useless %destructor for type <*> [-Wother]
+input0.y:30.3-5: warning: useless %printer for type <*> [-Wother]
+]],
+[[input1.y:30.3-4: warning: useless %destructor for type <> [-Wother]
+input1.y:30.3-4: warning: useless %printer for type <> [-Wother]
+]])])
+
 AT_COMPILE([input$1])
-AT_PARSER_CHECK([./input$1], 0,
+
+AT_PARSER_CHECK([./input$1 --debug], 0,
 [[<]]kind[[> for 'E' @ 1.
 <]]kind[[> for 'S' @ 1.
 ]],
 [[Starting parse
 Entering state 0
-Reducing stack by rule 1 (line 42):
+Reducing stack by rule 1 (line 49):
 -> $$ = nterm start (1.1: <]]kind[[> for 'S' @ 1)
 Stack now 0
 Entering state 1
@@ -1084,8 +1174,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
 
@@ -1105,7 +1197,7 @@ AT_SETUP([Default %printer and %destructor are not for error or $undefined])
 #       semantic value, which would be initialized from the lookahead, which
 #       would be destroyed separately.
 #   - For $undefined, who knows what the semantic value would be.
-AT_BISON_OPTION_PUSHDEFS
+AT_BISON_OPTION_PUSHDEFS([%debug])
 AT_DATA_GRAMMAR([[input.y]],
 [[%debug
 
@@ -1136,18 +1228,16 @@ start:
 %%
 ]AT_YYERROR_DEFINE[
 ]AT_YYLEX_DEFINE(["abd"], [yylval = res])[
-int
-main (void)
-{
-  yydebug = 1;
-  return yyparse ();
-}
+]AT_MAIN_DEFINE[
 ]])
 AT_BISON_OPTION_POPDEFS
 
-AT_BISON_CHECK([-o input.c input.y])
+AT_BISON_CHECK([-o input.c input.y], [], [],
+[[input.y:23.6-8: warning: useless %destructor for type <*> [-Wother]
+input.y:23.6-8: warning: useless %printer for type <*> [-Wother]
+]])
 AT_COMPILE([input])
-AT_PARSER_CHECK([./input], [1], [],
+AT_PARSER_CHECK([./input --debug], [1], [],
 [[Starting parse
 Entering state 0
 Reading a token: Next token is token 'a' ('a')
@@ -1197,7 +1287,7 @@ AT_SETUP([Default %printer and %destructor are not for $accept])
 #   - The %printer and %destructor code generated for $accept would always be
 #     dead code because $accept is currently never shifted onto the stack.
 #   - $$ for $accept would always be of type YYSTYPE because it's not possible
-#     to declare `%type <field> $accept'.  (Also true for $undefined.)
+#     to declare '%type <field> $accept'.  (Also true for $undefined.)
 #   - Thus, the compiler might complain that the user code assumes the wrong
 #     type for $$ since the code might assume the type associated with a
 #     specific union field, which is especially reasonable in C++ since that
@@ -1205,7 +1295,7 @@ AT_SETUP([Default %printer and %destructor are not for $accept])
 #     true for $undefined and the error token, so there are three warnings for
 #     %printer and three for %destructor.)
 
-AT_BISON_OPTION_PUSHDEFS
+AT_BISON_OPTION_PUSHDEFS([%debug])
 AT_DATA_GRAMMAR([[input.y]],
 [[%debug /* So that %printer is actually compiled.  */
 
@@ -1236,15 +1326,14 @@ start: { USE($$); } ;
 %%
 ]AT_YYERROR_DEFINE[
 ]AT_YYLEX_DEFINE[
-int
-main (void)
-{
-  return yyparse ();
-}
+]AT_MAIN_DEFINE[
 ]])
 AT_BISON_OPTION_POPDEFS
 
-AT_BISON_CHECK([-o input.c input.y])
+AT_BISON_CHECK([-o input.c input.y], [], [],
+[[input.y:24.3-4: warning: useless %destructor for type <> [-Wother]
+input.y:24.3-4: warning: useless %printer for type <> [-Wother]
+]])
 AT_COMPILE([input])
 
 AT_CLEANUP
@@ -1257,19 +1346,17 @@ AT_CLEANUP
 
 AT_SETUP([Default %printer and %destructor for mid-rule values])
 
-AT_BISON_OPTION_PUSHDEFS
+AT_BISON_OPTION_PUSHDEFS([%debug])
 AT_DATA_GRAMMAR([[input.y]],
 [[%debug /* So that %printer is actually compiled.  */
 
 %{
-# include <stdio.h>
-# include <stdlib.h>
 ]AT_YYERROR_DECLARE[
 ]AT_YYLEX_DECLARE[
 # define USE(SYM)
 # define YYLTYPE int
 # define YYLLOC_DEFAULT(Current, Rhs, N) (void)(Rhs)
-# define YY_LOCATION_PRINT(File, Loc)
+# define LOCATION_PRINT(File, Loc)
 %}
 
 %printer { fprintf (yyoutput, "%d", @$); } <>
@@ -1291,31 +1378,34 @@ start:
 %%
 ]AT_YYERROR_DEFINE[
 ]AT_YYLEX_DEFINE[
-int
-main (void)
-{
-  yydebug = 1;
-  return yyparse ();
-}
+]AT_MAIN_DEFINE[
 ]])
 AT_BISON_OPTION_POPDEFS
 
 AT_BISON_CHECK([-o input.c input.y], 0,,
-[[input.y:33.3-23: warning: unset value: $$
-input.y:32.3-23: 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:32.3-23: warning: unused value: $3 [-Wother]
 ]])
 
 AT_BISON_CHECK([-fcaret -o input.c input.y], 0,,
-[[input.y:33.3-23: warning: unset value: $$
+[[input.y:24.70-72: warning: useless %destructor for type <*> [-Wother]
+ %printer { fprintf (yyoutput, "<*> printer should not be called"); } <*>
+                                                                      ^^^
+input.y:24.70-72: warning: useless %printer for type <*> [-Wother]
+ %printer { fprintf (yyoutput, "<*> printer should not be called"); } <*>
+                                                                      ^^^
+input.y:33.3-23: warning: unset value: $$ [-Wother]
    {           @$ = 4; } // Only used.
    ^^^^^^^^^^^^^^^^^^^^^
-input.y:32.3-23: warning: unused value: $3
+input.y:32.3-23: warning: unused value: $3 [-Wother]
    { USE ($$); @$ = 3; } // Only set.
    ^^^^^^^^^^^^^^^^^^^^^
 ]])
 
 AT_COMPILE([input])
-AT_PARSER_CHECK([./input], 1,,
+AT_PARSER_CHECK([./input --debug], 1,,
 [[Starting parse
 Entering state 0
 Reducing stack by rule 1 (line 30):
@@ -1364,7 +1454,7 @@ AT_CLEANUP
 # -------------------------------------------
 m4_define([AT_CHECK_ACTION_LOCATIONS],
 [AT_SETUP([[@$ in ]$1[ implies %locations]])
-AT_BISON_OPTION_PUSHDEFS
+AT_BISON_OPTION_PUSHDEFS([%debug])
 AT_DATA_GRAMMAR([[input.y]],
 [[%code {
   #include <stdio.h>
@@ -1391,11 +1481,7 @@ yylex (void)
 }
 
 ]AT_YYERROR_DEFINE[
-int
-main (void)
-{
-  return yyparse ();
-}
+]AT_MAIN_DEFINE[
 ]])
 
 AT_BISON_CHECK([[-o input.c input.y]])
@@ -1412,8 +1498,9 @@ 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.
+# Check that we can use qualified $$ (v.g., $<type>$) not only in rule
+# actions, but also where $$ is valid: %destructor/%printer and
+# %initial-action.
 #
 # FIXME: Not actually checking %destructor, but it's the same code as
 # %printer...
@@ -1426,12 +1513,10 @@ AT_CHECK_ACTION_LOCATIONS([[%printer]])
 m4_pushdef([AT_TEST],
 [AT_SETUP([[Qualified $$ in actions: $1]])
 
-AT_BISON_OPTION_PUSHDEFS([%locations %skeleton "$1"])
+AT_BISON_OPTION_PUSHDEFS([%skeleton "$1" %debug])
 
 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
 {
@@ -1492,25 +1577,14 @@ float: UNTYPED 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_MAIN_DEFINE[
 ]])
 
 AT_FULL_COMPILE([[input]])
-AT_PARSER_CHECK([./input], 0, [], [stderr])
+AT_PARSER_CHECK([./input --debug], 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,
+AT_CHECK([[sed -ne '/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)
@@ -1533,115 +1607,6 @@ AT_TEST([glr.cc])
 
 m4_popdef([AT_TEST])
 
-## ----------------------------------------------- ##
-## Fix user actions without a trailing semicolon.  ##
-## ----------------------------------------------- ##
-
-AT_SETUP([[Fix user actions without a trailing semicolon]])
-
-# This feature is undocumented, but we accidentally broke it in 2.3a,
-# and there was a complaint at:
-# <http://lists.gnu.org/archive/html/bug-bison/2008-11/msg00001.html>.
-AT_BISON_OPTION_PUSHDEFS
-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 */ }
-;
-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 ;
-} ;
-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 {}
-} ;
-
-testc
-: 'a' {
-#define TEST_MACRO_N \
-[]"broken\" $ @ $$ @$ [];\
-string;"}
-| 'b' {
-no_semi
-#define TEST_MACRO_N \
-[]"broken\" $ @ $$ @$ [];\
-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:     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:     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:     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:     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:     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:     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:     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:     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:     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:     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:     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:     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:     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:     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:     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:     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:     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:     future versions of Bison will not add the ';'
-]])
-
-AT_MATCHES_CHECK([input.c], [[/\* TEST:N:2 \*/ \}$]],       [[3]])
-AT_MATCHES_CHECK([input.c], [[/\* TEST:Y:2 \*/ ;\}$]],      [[6]])
-AT_MATCHES_CHECK([input.c], [[// TEST:N:1 [;{}]*\n\}$]],    [[6]])
-AT_MATCHES_CHECK([input.c], [[// TEST:Y:1 [;{}]*\n;\}$]],  [[12]])
-AT_MATCHES_CHECK([input.c], [[#define TEST_MACRO_N \\\n\[\]"broken\\" \$ \@ \$\$ \@\$ \[\];\\\nstring;"\}]], [[2]])
-
-AT_CLEANUP
-
-
 ## -------------------------------------------------- ##
 ## Destroying lookahead assigned by semantic action.  ##
 ## -------------------------------------------------- ##
@@ -1676,7 +1641,7 @@ AT_DATA_GRAMMAR([input.y],
 // that has set yychar might not always return normally.  Instead,
 // skeletons must translate before every use of yytoken.
 start: 'a' accept { USE($1); } ;
-accept: /*empty*/ {
+accept: %empty {
   assert (yychar == YYEMPTY);
   yychar = 'b';
   YYACCEPT;
@@ -1685,11 +1650,7 @@ accept: /*empty*/ {
 %%
 ]AT_YYERROR_DEFINE[
 ]AT_YYLEX_DEFINE(["a"])[
-int
-main (void)
-{
-  return yyparse ();
-}
+]AT_MAIN_DEFINE[
 ]])
 AT_BISON_OPTION_POPDEFS
 AT_BISON_CHECK([[-o input.c input.y]])
@@ -1707,7 +1668,7 @@ AT_CLEANUP
 
 AT_SETUP([[YYBACKUP]])
 
-AT_BISON_OPTION_PUSHDEFS([%pure-parser])
+AT_BISON_OPTION_PUSHDEFS([%pure-parser %debug])
 
 AT_DATA_GRAMMAR([input.y],
 [[
@@ -1736,13 +1697,7 @@ exp:
 %%
 ]AT_YYERROR_DEFINE[
 ]AT_YYLEX_DEFINE(["bcd"], [*lvalp = (toknum + 1) * 10])[
-
-int
-main (void)
-{
-  yydebug = !!getenv("YYDEBUG");
-  return yyparse ();
-}
+]AT_MAIN_DEFINE[
 ]])
 AT_BISON_OPTION_POPDEFS
 
index 72e15f3757bf9138171a7981d3fb7444a5e1cdaa..763ca9022942b29a9971b0324f9ebf8f8beeed8d 100644 (file)
@@ -1,4 +1,4 @@
-# @configure_input@                                    -*- shell-script -*-
+# @configure_input@                                     -*- shell-script -*-
 # Configurable variable values for Bison test suite.
 
 # Copyright (C) 2000-2013 Free Software Foundation, Inc.
@@ -16,7 +16,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/>.
 
-# We need `config.h'.
+# We need 'config.h'.
 CPPFLAGS="-I$abs_top_builddir/lib @CPPFLAGS@"
 
 # Don't just check if $POSIXLY_CORRECT is set, as Bash, when launched
@@ -47,8 +47,7 @@ NO_WERROR_CXXFLAGS='@CXXFLAGS@ @WARN_CXXFLAGS@ @WARN_CXXFLAGS_TEST@'
   CFLAGS="$NO_WERROR_CFLAGS   @WERROR_CFLAGS@"
 CXXFLAGS="$NO_WERROR_CXXFLAGS @WERROR_CXXFLAGS@"
 
-# If 'exit 77'; skip all C/C++ tests; otherwise ':'.
-BISON_C_WORKS='@BISON_C_WORKS@'
+# If 'exit 77'; skip all C++ tests; otherwise ':'.
 BISON_CXX_WORKS='@BISON_CXX_WORKS@'
 
 # Whether the compiler supports POSIXLY_CORRECT defined.
@@ -84,8 +83,9 @@ CONF_JAVAC='@CONF_JAVAC@'
 # Empty if no Java VM was found
 CONF_JAVA='@CONF_JAVA@'
 
-# We need egrep.
+# We need egrep and perl.
 : ${EGREP='@EGREP@'}
+: ${PERL='@PERL@'}
 
 # Use simple quotes (lib/quote.c).
 LC_CTYPE=C
@@ -100,4 +100,12 @@ LIBS="$abs_top_builddir/lib/libbison.a @LIBS@ @INTLLIBS@"
 # Empty if no xsltproc was found
 : ${XSLTPROC='@XSLTPROC@'}
 
-: ${PERL='@PERL@'}
+# Don't just check if $POSIXLY_CORRECT is set, as Bash, when launched
+# as /bin/sh, sets the shell variable POSIXLY_CORRECT to y, but not
+# the environment variable.
+: ${C_COMPILER_POSIXLY_CORRECT='@C_COMPILER_POSIXLY_CORRECT@'}
+if env | grep '^POSIXLY_CORRECT=' >/dev/null; then
+  POSIXLY_CORRECT_IS_EXPORTED=true
+else
+  POSIXLY_CORRECT_IS_EXPORTED=false
+fi
index bf6add7141b1c70d1f0f31a9c254240b50555256..5c5881f773a00c15758d20cfb82f9c2529500f7f 100644 (file)
@@ -34,14 +34,15 @@ status=$?
 for i
 do
   case $i in
-    */parse-gram.y)
+    */src/parse-gram.y)
     if $PERL --version >/dev/null; then
-      # We are called by ylwrap which still uses y.tab.*, and
-      # post-processes the synclines on y.tab.c itself.  Don't let it
-      # do it.  Besides, it leaves "parse-gram.y" as the source,
-      # dropping the src/ part.
-      $PERL -pi -e 's{"y\.tab\.}{"parse-gram.}g;'    \
-                -e 's{".*/(parse-gram\.y)"}{"$1"}g;' \
+      # We are called by ylwrap which (if it's an old version) still
+      # uses y.tab.*, and post-processes the synclines on y.tab.c
+      # itself.  Don't let it do it.  Besides, it leaves
+      # "parse-gram.y" as the source, dropping the src/ part.
+      $PERL -pi -e 's{"y\.tab\.}{"parse-gram.}g;'                       \
+                -e 's{"(?:.*/)?(parse-gram\.[chy])"}{"src/$1"}g;'       \
+                -e 's{GRAM_Y_TAB_H}{GRAM_SRC_PARSE_GRAM_H}g;'           \
            y.tab.[ch]
     fi
     ;;
index a65f953c9aa1b5811c696573e78b80b43adef12b..3300352d8cfcaf326f3e46eb94f7b69d8045efd0 100644 (file)
@@ -1,7 +1,6 @@
 # Checking the C++ Features.                    -*- Autotest -*-
 
-# Copyright (C) 2004-2005, 2007, 2009-2013 Free Software Foundation,
-# Inc.
+# Copyright (C) 2004-2005, 2007-2013 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
 AT_BANNER([[C++ Features.]])
 
 
+## --------------------------- ##
+## C++ Variant-based Symbols.  ##
+## --------------------------- ##
+
+AT_SETUP([C++ Variant-based Symbols])
+
+AT_KEYWORDS([variant])
+
+AT_BISON_OPTION_PUSHDEFS([%skeleton "lalr1.cc" %debug $1])
+# Store strings and integers in a list of strings.
+AT_DATA_GRAMMAR([list.y],
+[[%skeleton "lalr1.cc"
+%define api.value.type variant
+%define parse.assert
+%debug
+
+%code top
+{
+  // Get access to stack_symbol_type for the tests.
+# define private public
+}
+%code provides
+{
+  ]AT_YYLEX_DECLARE[
+}
+
+%token <int> INT "int"
+%type < std::list<int> > exp
+
+%printer { yyo << $$; } <int>
+%printer
+  {
+    for (std::list<int>::const_iterator i = $$.begin (); i != $$.end (); ++i)
+      {
+        if (i != $$.begin ())
+          yyo << ", ";
+        yyo << *i;
+      }
+  } < std::list<int> >
+
+%code requires { #include <list> }
+%code { int yylex (yy::parser::semantic_type* yylval); }
+
+%%
+exp: "int" { $$.push_back ($1); }
+%%
+]AT_YYERROR_DEFINE[
+]AT_YYLEX_DEFINE[
+
+int main()
+{
+  {
+    yy::parser::symbol_type s = yy::parser::make_INT(12);
+    std::cerr << s.value.as<int>() << std::endl;
+  }
+
+  {
+    yy::parser::symbol_type s = yy::parser::make_INT(123);
+    yy::parser::stack_symbol_type ss(1, s);
+    std::cerr << ss.value.as<int>() << std::endl;
+  }
+
+  {
+    yy::parser::stack_type st;
+    for (int i = 0; i < 100; ++i)
+      {
+        yy::parser::symbol_type s(yy::parser::make_INT(i));
+        yy::parser::stack_symbol_type ss(1, s);
+        st.push(ss);
+      }
+  }
+}
+]])
+
+AT_FULL_COMPILE([list])
+AT_PARSER_CHECK([./list], 0, [],
+[12
+123
+])
+
+AT_BISON_OPTION_POPDEFS
+AT_CLEANUP
+
+
+## ---------- ##
+## Variants.  ##
+## ---------- ##
+
+# AT_TEST([DIRECTIVES])
+# ---------------------
+# Check the support of variants in C++, with the additional DIRECTIVES.
+m4_pushdef([AT_TEST],
+[AT_SETUP([Variants $1])
+
+AT_BISON_OPTION_PUSHDEFS([%skeleton "lalr1.cc" %debug $1])
+# Store strings and integers in a list of strings.
+AT_DATA_GRAMMAR([list.y],
+[[%debug
+%skeleton "lalr1.cc"
+%define api.value.type variant
+]m4_bpatsubst([$1], [\\n], [
+])[
+
+%code requires // code for the .hh file
+{
+#include <list>
+#include <string>
+typedef std::list<std::string> strings_type;
+}
+
+%code // code for the .cc file
+{
+#include <cstdlib> // abort, getenv
+#include <iostream>
+#include <sstream>
+
+  namespace yy
+  {
+    static]AT_TOKEN_CTOR_IF([[
+    parser::symbol_type yylex ()]], [[
+    parser::token_type yylex (parser::semantic_type* yylval]AT_LOCATION_IF([,
+                              parser::location_type* yylloc])[)]])[;
+  }
+
+  // Printing a list of strings (for %printer).
+  // Koening look up will look into std, since that's an std::list.
+  namespace std
+  {
+    std::ostream&
+    operator<<(std::ostream& o, const strings_type& s)
+    {
+      o << '(';
+      for (strings_type::const_iterator i = s.begin (); i != s.end (); ++i)
+        {
+          if (i != s.begin ())
+            o << ", ";
+          o << *i;
+        }
+      return o << ')';
+    }
+  }
+
+  // Conversion to string.
+  template <typename T>
+    inline
+    std::string
+    string_cast (const T& t)
+  {
+    std::ostringstream o;
+    o << t;
+    return o.str ();
+  }
+}
+
+%token <::std::string> TEXT;
+%token <int> NUMBER;
+%token END_OF_FILE 0;
+
+%type <::std::string> item;
+// Using the template type to exercize its parsing.
+// Starting with :: to ensure we don't output "<::" which starts by the
+// digraph for the left square bracket.
+%type <::std::list<std::string>> list result;
+
+%printer { yyo << $][$; }
+  <int> <::std::string> <::std::list<std::string>>;
+%%
+
+result:
+  list          { std::cout << $][1 << std::endl; }
+;
+
+list:
+  /* nothing */ { /* Generates an empty string list */ }
+| list item     { std::swap ($][$,$][1); $$.push_back ($][2); }
+| list error    { std::swap ($][$,$][1); }
+;
+
+item:
+  TEXT          { std::swap ($][$,$][1); }
+| NUMBER        { if ($][1 == 3) YYERROR; else $][$ = string_cast ($][1); }
+;
+%%
+]AT_TOKEN_CTOR_IF([],
+[[#ifdef TWO_STAGE_BUILD
+# define BUILD(Type, Value) build<Type> () = Value
+#else
+# define BUILD(Type, Value) build (Value)
+#endif
+]])[
+#define STAGE_MAX 5
+namespace yy
+{
+  static]AT_TOKEN_CTOR_IF([[
+  parser::symbol_type yylex ()]], [[
+  parser::token_type yylex (parser::semantic_type* yylval]AT_LOCATION_IF([,
+                            parser::location_type* yylloc])[)]])[
+  {]AT_LOCATION_IF([
+    typedef parser::location_type location;])[
+    static int stage = -1;
+    ++stage;
+    if (stage == STAGE_MAX)
+      {]AT_TOKEN_CTOR_IF([[
+        return parser::make_END_OF_FILE (]AT_LOCATION_IF([location ()])[);]],
+[AT_LOCATION_IF([
+        *yylloc = location ();])[
+        return parser::token::END_OF_FILE;]])[
+      }
+    else if (stage % 2)
+      {]AT_TOKEN_CTOR_IF([[
+        return parser::make_NUMBER (stage]AT_LOCATION_IF([, location ()])[);]],
+[[
+        yylval->BUILD (int, stage);]AT_LOCATION_IF([
+        *yylloc = location ();])[
+        return parser::token::NUMBER;]])[
+      }
+    else
+      {]AT_TOKEN_CTOR_IF([[
+        return parser::make_TEXT (string_cast (stage)]AT_LOCATION_IF([, location ()])[);]], [[
+        yylval->BUILD (std::string, string_cast (stage));]AT_LOCATION_IF([
+        *yylloc = location ();])[
+        return parser::token::TEXT;]])[
+      }
+    abort ();
+  }
+}
+
+]AT_YYERROR_DEFINE[
+]AT_MAIN_DEFINE[
+]])
+
+AT_FULL_COMPILE([list])
+AT_PARSER_CHECK([./list], 0,
+[(0, 1, 2, 4)
+])
+
+AT_BISON_OPTION_POPDEFS
+AT_CLEANUP
+])
+
+AT_TEST([])
+AT_TEST([%define parse.assert])
+AT_TEST([%locations %define parse.assert])
+AT_TEST([[%define parse.assert %code {\n#define TWO_STAGE_BUILD\n}]])
+AT_TEST([[%define parse.assert %define api.token.constructor]])
+AT_TEST([[%define parse.assert %define api.token.constructor %define api.token.prefix "TOK_"]])
+AT_TEST([[%locations %define parse.assert %define api.token.constructor %define api.token.prefix "TOK_"]])
+
+m4_popdef([AT_TEST])
+
+
 ## ----------------------- ##
 ## Doxygen Documentation.  ##
 ## ----------------------- ##
@@ -27,7 +277,7 @@ m4_define([AT_CHECK_DOXYGEN],
 [m4_case([$1],
          [Public],  [m4_pushdef([AT_DOXYGEN_PRIVATE], [NO])],
          [Private], [m4_pushdef([AT_DOXYGEN_PRIVATE], [YES])],
-        [m4_fatal([invalid argument: $1])])
+         [m4_fatal([invalid argument: $1])])
 AT_SETUP([Doxygen $1 Documentation])
 
 AT_BISON_OPTION_PUSHDEFS([%skeleton "lalr1.cc"])
@@ -35,9 +285,8 @@ AT_DATA([input.yy],
 [[%skeleton "lalr1.cc"
 %locations
 %debug
-%defines
 %%
-exp:;
+exp: /* empty */;
 %%
 ]AT_YYERROR_DEFINE[
 ]])
@@ -101,28 +350,28 @@ m4_popdef([AT_DOXYGEN_PRIVATE])
 AT_CHECK_DOXYGEN([Public])
 AT_CHECK_DOXYGEN([Private])
 
+
 ## ------------ ##
 ## Namespaces.  ##
 ## ------------ ##
 
-# AT_CHECK_NAMESPACE(NAMESPACE-DECL, [COMPILE-ERROR])
-# ---------------------------------------------------
+# AT_TEST(NAMESPACE-DECL, [COMPILE-ERROR])
+# ----------------------------------------
 # See if Bison can handle %define namespace "NAMESPACE-DECL".  If COMPILE-ERROR
 # is specified, then Bison should accept the input, but compilation will fail,
 # so don't check compilation.
-m4_define([AT_CHECK_NAMESPACE],
-[
-
+m4_pushdef([AT_TEST],
+[AT_BISON_OPTION_PUSHDEFS([%language "C++" %define api.namespace {$1}])
 AT_DATA_GRAMMAR([[input.y]],
 [[%language "C++"
-%defines
-%define namespace "]$1["
+%define api.namespace {]$1[}
 %union { int i; }
 %define global_tokens_and_yystype
+%locations
 
 %code {
   // YYSTYPE contains a namespace reference.
-  int yylex (YYSTYPE *lval) {
+  int yylex (YYSTYPE *lval, const ]$1[::parser::location_type*) {
     lval->i = 3;
     return 0;
   }
@@ -141,45 +390,197 @@ void
   std::cerr << "At " << loc << ": " << msg << std::endl;
 }
 
-int
-main (void)
-{
-  ]$1[::parser p;
-  return p.parse ();
-}
+]AT_MAIN_DEFINE[
 ]])
 
+
 AT_BISON_CHECK([[-o input.cc input.y]])
 
 m4_if([$#], [1],
 [AT_COMPILE_CXX([[input]], [[input.cc]])
 AT_PARSER_CHECK([[./input]])])
-
+AT_BISON_OPTION_POPDEFS
 ])
 
 AT_SETUP([[Relative namespace references]])
-AT_CHECK_NAMESPACE([[foo]])
-AT_CHECK_NAMESPACE([[foo::bar]])
-AT_CHECK_NAMESPACE([[foo::bar::baz]])
+AT_TEST([[foo]])
+AT_TEST([[foo::bar]])
+AT_TEST([[foo::bar::baz]])
 AT_CLEANUP
 
 AT_SETUP([[Absolute namespace references]])
-AT_CHECK_NAMESPACE([[::foo]])
-AT_CHECK_NAMESPACE([[::foo::bar]])
-AT_CHECK_NAMESPACE([[::foo::bar::baz]])
-AT_CHECK_NAMESPACE([[  ::foo]])
-AT_CHECK_NAMESPACE([[           ::foo::bar]])
-AT_CHECK_NAMESPACE([[  ::foo::bar::baz]])
+AT_TEST([[::foo]])
+AT_TEST([[::foo::bar]])
+AT_TEST([[::foo::bar::baz]])
+AT_TEST([[@tb@::foo]])
+AT_TEST([[  @tb@ ::foo::bar]])
+AT_TEST([[  ::foo::bar::baz]])
 AT_CLEANUP
 
 AT_SETUP([[Syntactically invalid namespace references]])
-AT_CHECK_NAMESPACE([[:foo:bar]], [[-]])
-AT_CHECK_NAMESPACE([[foo: :bar]], [[-]])
-# This one is interesting because `[3]' is encoded as `@<:@3@:>@', which
-# contains single occurrences of `:'.
-AT_CHECK_NAMESPACE([[foo[3]::bar::baz]], [[-]])
-AT_CHECK_NAMESPACE([[foo::bar,baz]], [[-]])
-AT_CHECK_NAMESPACE([[foo::bar::(baz]], [[-]])
+AT_TEST([[:foo:bar]], [[-]])
+AT_TEST([[foo: :bar]], [[-]])
+# This one is interesting because '[3]' is encoded as '@<:@3@:>@', which
+# contains single occurrences of ':'.
+AT_TEST([[foo[3]::bar::baz]], [[-]])
+AT_TEST([[foo::bar,baz]], [[-]])
+AT_TEST([[foo::bar::(baz /* Pacify Emacs ) */]], [[-]])
+AT_CLEANUP
+
+m4_popdef([AT_TEST])
+
+## -------------------------------------- ##
+## Syntax error discarding no lookahead.  ##
+## -------------------------------------- ##
+
+# After a syntax error, lalr1.cc used to not check whether there
+# actually is a lookahead before discarding the lookahead.  As a result,
+# it mistakenly invoked the destructor for the previous lookahead.
+
+AT_SETUP([[Syntax error discarding no lookahead]])
+
+AT_BISON_OPTION_PUSHDEFS([%skeleton "lalr1.cc"])
+
+AT_DATA_GRAMMAR([[input.yy]],
+[[%skeleton "lalr1.cc"
+
+%code {
+  #include <string>
+  int yylex (yy::parser::semantic_type *);
+  #define USE(Args)
+}
+
+%define parse.error verbose
+
+%nonassoc 'a' ;
+
+%destructor {
+  std::cerr << "Discarding 'a'." << std::endl;
+} 'a'
+
+%%
+
+start: error-reduce consistent-error 'a' { USE ($3); };
+
+error-reduce:
+  'a' 'a' consistent-error 'a' { USE (($1, $2, $4)); }
+| 'a' error { std::cerr << "Reducing 'a'." << std::endl; USE ($1); }
+;
+
+consistent-error:
+  'a'
+| /*empty*/ %prec 'a'
+;
+
+// Provide another context in which all rules are useful so that this
+// test case looks a little more realistic.
+start: 'b' consistent-error ;
+
+%%
+
+int
+yylex (yy::parser::semantic_type *)
+{
+  static char const *input = "aa";
+  return *input++;
+}
+
+void
+yy::parser::error (const std::string &m)
+{
+  std::cerr << m << std::endl;
+}
+
+]AT_MAIN_DEFINE[
+]])
+
+AT_BISON_CHECK([[-o input.cc input.yy]])
+AT_COMPILE_CXX([[input]])
+# This used to print "Discarding 'a'." again at the end.
+AT_PARSER_CHECK([[./input]], [[1]], [[]],
+[[syntax error
+Discarding 'a'.
+Reducing 'a'.
+]])
+
+AT_BISON_OPTION_POPDEFS
+AT_CLEANUP
+
+
+## --------------------------- ##
+## Syntax error as exception.  ##
+## --------------------------- ##
+
+AT_SETUP([[Syntax error as exception]])
+
+AT_BISON_OPTION_PUSHDEFS([%skeleton "lalr1.cc"])
+
+AT_DATA_GRAMMAR([[input.yy]],
+[[%skeleton "lalr1.cc"
+
+%code
+{
+  #include <cstdlib>
+  int yylex (yy::parser::semantic_type *);
+}
+
+%define api.value.type variant
+%define parse.error verbose
+%define parse.trace
+%%
+
+start:
+  thing
+| start thing
+;
+
+thing:
+  error   { std::cerr << "caught error" << std::endl; }
+| item
+;
+
+item:
+  'a'
+| 's'
+  {
+    throw yy::parser::syntax_error ("invalid expression");
+  }
+
+%%
+
+int
+yylex (yy::parser::semantic_type *)
+{
+  // 's': syntax error, 'l': lexical error.
+  static char const *input = "asal";
+  switch (int res = *input++)
+  {
+    case 'l':
+      throw yy::parser::syntax_error ("invalid character");
+    default:
+      return res;
+  }
+}
+
+void
+yy::parser::error (const std::string &m)
+{
+  std::cerr << "error: " << m << std::endl;
+}
+]AT_MAIN_DEFINE[
+]])
+
+AT_BISON_CHECK([[-o input.cc input.yy]])
+AT_COMPILE_CXX([[input]])
+
+AT_PARSER_CHECK([[./input]], [[0]], [[]],
+[[error: invalid expression
+caught error
+error: invalid character
+caught error
+]])
+
+AT_BISON_OPTION_POPDEFS
 AT_CLEANUP
 
 
@@ -187,16 +588,19 @@ AT_CLEANUP
 ## Exception safety.  ##
 ## ------------------ ##
 
-AT_SETUP([[Exception safety]])
+# AT_TEST([BISON-DIRECTIVES])
+# ---------------------------
+# Check that no object is leaked when exceptions are thrown.
+m4_pushdef([AT_TEST],
+[AT_SETUP([[Exception safety $1]])
 
-AT_BISON_OPTION_PUSHDEFS([%skeleton "lalr1.cc"])
+AT_BISON_OPTION_PUSHDEFS([%skeleton "lalr1.cc" $1])
 
 AT_DATA_GRAMMAR([[input.yy]],
 [[%skeleton "lalr1.cc"
-%defines // FIXME: Mandated in 2.6.
 %debug
 %error-verbose
-
+$1
 %code requires
 {
   #include <cassert>
@@ -209,14 +613,42 @@ AT_DATA_GRAMMAR([[input.yy]],
   /// A class that counts its number of instances.
   struct Object
   {
+    char val;
+
+    Object (char v)
+      : val (v)
+    {
+      Object::instances.push_back(this);
+      log (this, "Object::Object");
+    }
+
+    Object ()
+      : val ('?')
+    {
+      Object::instances.push_back(this);
+      log (this, "Object::Object");
+    }
+
+    Object& operator= (char v)
+    {
+      val = v;
+      return *this;
+    }
+
+    ~Object ()
+    {
+      Object::instances.remove (this);
+      log (this, "Object::~Object");
+    }
+
+    // Static part.
     typedef std::list<const Object*> objects;
     static objects instances;
-    char val;
 
     static bool
     empty ()
     {
-      return instances.empty();
+      return instances.empty ();
     }
 
     static void
@@ -239,19 +671,6 @@ AT_DATA_GRAMMAR([[input.yy]],
           std::cerr << " }" << std::endl;
         }
     }
-
-    Object (char v)
-      : val (v)
-    {
-      instances.push_back(this);
-      log (this, "Object::Object");
-    }
-
-    ~Object ()
-    {
-      instances.remove(this);
-      log (this, "Object::~Object");
-    }
   };
 }
 
@@ -265,17 +684,21 @@ AT_DATA_GRAMMAR([[input.yy]],
   static char const *input;
 }
 
-%union
+]AT_VARIANT_IF([[
+%printer
 {
-  Object *obj;
-}
+  yyo << &$$ << " '" << $$.val << '\'';
+  if ($$.val == 'p')
+    throw std::runtime_error ("printer");
+} <Object>;
 
-%initial-action
+%token <Object> 'a' 'E' 'e' 'p' 'R' 's' 'T'
+%type  <Object> list item
+]], [[
+%union
 {
-  if (strchr (input, 'i'))
-    throw std::runtime_error ("initial-action");
+  Object *obj;
 }
-
 %destructor { delete $$; } <obj>;
 %printer
 {
@@ -286,27 +709,35 @@ AT_DATA_GRAMMAR([[input.yy]],
 
 %token <obj> 'a' 'E' 'e' 'p' 'R' 's' 'T'
 %type  <obj> list item
+]])[
+
+%initial-action
+{
+  if (strchr (input, 'i'))
+    throw std::runtime_error ("initial-action");
+}
 
 %%
 
-start: list { delete $1; };
+start: list {]AT_VARIANT_IF([], [ delete $][1]; )[};
 
 list:
-  item       { $$ = $1; }
-| item list  { $$ = $1; delete $2; } // Right recursion to load the stack.
+  item       { $][$ = $][1; }
+  // Right recursion to load the stack.
+| item list  { $][$ = $][1; ]AT_VARIANT_IF([], [delete $][2]; )[}
 ;
 
 item:
-  'a'  { $$ = $1; }
-| 'e'  { YYUSE ($$); YYUSE($1); error (location_type(), "syntax error"); }
+  'a'  { $$][ = $][1; }
+| 'e'  { YYUSE ($][$); YYUSE($][1); error ("syntax error"); }
 // Not just 'E', otherwise we reduce when 'E' is the lookahead, and
 // then the stack is emptied, defeating the point of the test.
-| 'E' 'a' { YYUSE($1); $$ = $2; }
-| 'R'  { $$ = YY_NULL; delete $1; YYERROR; }
-| 'p'  { $$ = $1; }
-| 's'  { $$ = $1; throw std::runtime_error ("reduction"); }
-| 'T'  { $$ = YY_NULL; delete $1; YYABORT; }
-| error { $$ = YY_NULL; yyerrok; }
+| 'E' 'a' { YYUSE($][1); $][$ = $][2; }
+| 'R'  { $][$ = 0; ]AT_VARIANT_IF([], [delete $][1]; )[YYERROR; }
+| 'p'  { $][$ = $][1; }
+| 's'  { $][$ = $][1; throw std::runtime_error ("reduction"); }
+| 'T'  { $][$ = 0; ]AT_VARIANT_IF([], [delete $][1]; )[YYABORT; }
+| error { $][$ = 0; yyerrok; }
 ;
 %%
 
@@ -323,21 +754,20 @@ yylex (yy::parser::semantic_type *lvalp)
   // 'T': call YYABORT in the action
   switch (int res = *input++)
   {
-    case 'l':
-      throw std::runtime_error ("yylex");
-    default:
-      lvalp->obj = new Object (res);
-      // Fall through.
-    case 0:
-      return res;
+  case 'l':
+    throw std::runtime_error ("yylex");
+  default:
+    lvalp]AT_VARIANT_IF([->build (res)], [->obj = new Object (res)])[;
+    // Fall through.
+  case 0:
+    return res;
   }
 }
 
 /* A C++ error reporting function.  */
 void
-yy::parser::error (const location_type& l, const std::string& m)
+yy::parser::error (const std::string& m)
 {
-  YYUSE (l);
   throw std::runtime_error (m);
 }
 
@@ -350,7 +780,7 @@ main (int argc, const char *argv[])
       input = argv[1];
       break;
     case 3:
-      assert (!strcmp (argv[1], "--debug"));
+      assert (std::string(argv[1]) == "--debug");
       debug = 1;
       input = argv[2];
       break;
@@ -415,3 +845,56 @@ AT_PARSER_CHECK([[./input aaaaR]], [[0]])
 AT_BISON_OPTION_POPDEFS
 
 AT_CLEANUP
+])
+
+AT_TEST
+AT_TEST([%define api.value.type variant])
+
+m4_popdef([AT_TEST])
+
+## ------------------------------------ ##
+## C++ GLR parser identifier shadowing  ##
+## ------------------------------------ ##
+
+AT_SETUP([[C++ GLR parser identifier shadowing]])
+
+AT_DATA_GRAMMAR([input.yy], [
+%skeleton "glr.cc"
+
+%union
+{
+  int ival;
+}
+
+%token <ival> ZERO;
+
+%code
+{
+  int yylex (yy::parser::semantic_type *yylval);
+}
+
+%%
+exp: ZERO
+
+%%
+
+int yylex (yy::parser::semantic_type *yylval)
+{
+  // Note: this argument is unused, but named on purpose.  There used to be a
+  // bug with a macro that erroneously expanded this identifier to
+  // yystackp->yyval.
+  YYUSE (yylval);
+  return yy::parser::token::ZERO;
+}
+
+void yy::parser::error (std::string const&)
+{}
+
+int main()
+{}
+])
+
+AT_BISON_CHECK([[-o input.cc input.yy]])
+AT_COMPILE_CXX([[input]])
+
+AT_CLEANUP
index 794488ffab1a660a4c9c249662bb85a921baae76..a14f2c21d7f78b095318ae466138a0a4cbd84602 100644 (file)
 
 # _AT_DATA_CALC_Y($1, $2, $3, [BISON-DIRECTIVES])
 # -----------------------------------------------
-# Produce `calc.y' and, if %defines was specified, `calc-lex.c' or
-# `calc-lex.cc'.
+# Produce 'calc.y' and, if %defines was specified, 'calc-lex.c' or
+# 'calc-lex.cc'.
 #
 # Don't call this macro directly, because it contains some occurrences
-# of `$1' etc. which will be interpreted by m4.  So you should call it
+# of '$1' etc. which will be interpreted by m4.  So you should call it
 # with $1, $2, and $3 as arguments, which is what AT_DATA_CALC_Y does.
 #
 # When %defines is not passed, generate a single self-contained file.
@@ -46,12 +46,7 @@ m4_define([_AT_DATA_CALC_Y],
 
 m4_pushdef([AT_CALC_MAIN],
 [#include <assert.h>
-#if HAVE_UNISTD_H
-# include <unistd.h>
-#else
-# undef alarm
-# define alarm(seconds) /* empty */
-#endif
+#include <unistd.h>
 
 AT_SKEL_CC_IF([[
 /* A C++ ]AT_NAME_PREFIX[parse that simulates the C signature.  */
@@ -77,10 +72,12 @@ main (int argc, const char **argv)
   int count = 0;
   int status;
 
-  /* This used to be alarm (10), but that isn't enough time for
-     a July 1995 vintage DEC Alphastation 200 4/100 system,
-     according to Nelson H. F. Beebe.  100 seconds is enough.  */
-  alarm (100);
+  /* This used to be alarm (10), but that isn't enough time for a July
+     1995 vintage DEC Alphastation 200 4/100 system, according to
+     Nelson H. F. Beebe.  100 seconds was enough for regular users,
+     but the Hydra build farm, which is heavily loaded needs more.  */
+
+  alarm (200);
 
   if (argc == 2)
     input = fopen (argv[1], "r");
@@ -93,8 +90,7 @@ main (int argc, const char **argv)
       return 3;
     }
 
-]AT_SKEL_CC_IF([], [m4_bmatch([$4], [%debug],
-[  ]AT_NAME_PREFIX[debug = 1;])])[
+]AT_SKEL_CC_IF([], [AT_DEBUG_IF([  ]AT_NAME_PREFIX[debug = 1;])])[
   status = ]AT_NAME_PREFIX[parse (]AT_PARAM_IF([[&result, &count]])[);
   if (fclose (input))
     perror ("fclose");
@@ -138,7 +134,7 @@ unget_char (]AT_YYLEX_PRE_FORMALS[ int c)
 {
   ]AT_USE_LEX_ARGS[;
 ]AT_LOCATION_IF([
-  /* Wrong when C == `\n'. */
+  /* Wrong when C == '\n'. */
   AT_LOC = last_yylloc;
 ])[
   ungetc (c, input);
@@ -194,12 +190,12 @@ read_signed_integer (]AT_YYLEX_FORMALS[)
     {
       unget_char (]AT_YYLEX_PRE_ARGS[ c);
       ]AT_VAL[.ival = read_signed_integer (]AT_YYLEX_ARGS[);
-      return NUM;
+      return ]AT_TOKEN_PREFIX[NUM;
     }
 
   /* Return end-of-file.  */
   if (c == EOF)
-    return CALC_EOF;
+    return ]AT_TOKEN_PREFIX[CALC_EOF;
 
   /* Return single chars. */
   return c;
@@ -287,11 +283,11 @@ static int power (int base, int exponent);
 %token <ival> NUM "number"
 %type  <ival> exp
 
-%nonassoc '=' /* comparison            */
+%nonassoc '='   /* comparison          */
 %left '-' '+'
 %left '*' '/'
-%left NEG     /* negation--unary minus */
-%right '^'    /* exponentiation        */
+%precedence NEG /* negation--unary minus */
+%right '^'      /* exponentiation        */
 
 /* Grammar follows */
 %%
@@ -370,8 +366,8 @@ m4_popdef([AT_CALC_LEX])
 
 # AT_DATA_CALC_Y([BISON-OPTIONS])
 # -------------------------------
-# Produce `calc.y' and, if %defines was specified, `calc-lex.c' or
-# `calc-lex.cc'.
+# Produce 'calc.y' and, if %defines was specified, 'calc-lex.c' or
+# 'calc-lex.cc'.
 m4_define([AT_DATA_CALC_Y],
 [_AT_DATA_CALC_Y($[1], $[2], $[3], [$1])
 ])
@@ -380,9 +376,9 @@ m4_define([AT_DATA_CALC_Y],
 
 # _AT_CHECK_CALC(BISON-OPTIONS, INPUT, [NUM-STDERR-LINES])
 # --------------------------------------------------------
-# Run `calc' on INPUT and expect no STDOUT nor STDERR.
+# Run 'calc' on INPUT and expect no STDOUT nor STDERR.
 #
-# If BISON-OPTIONS contains `%debug' but not `%glr-parser', then
+# If BISON-OPTIONS contains '%debug' but not '%glr-parser', then
 #
 # NUM-STDERR-LINES is the number of expected lines on stderr.
 # Currently this is ignored, though, since the output format is fluctuating.
@@ -401,7 +397,7 @@ AT_PARSER_CHECK([./calc input], 0, [], [stderr])
 #                      [NUM-STDERR-LINES],
 #                      [VERBOSE-AND-LOCATED-ERROR-MESSAGE])
 # ---------------------------------------------------------
-# Run `calc' on INPUT, and expect a `syntax error' message.
+# Run 'calc' on INPUT, and expect a 'syntax error' message.
 #
 # If INPUT starts with a slash, it is used as absolute input file name,
 # otherwise as contents.
@@ -409,14 +405,14 @@ AT_PARSER_CHECK([./calc input], 0, [], [stderr])
 # NUM-STDERR-LINES is the number of expected lines on stderr.
 # Currently this is ignored, though, since the output format is fluctuating.
 #
-# If BISON-OPTIONS contains `%location', then make sure the ERROR-LOCATION
+# If BISON-OPTIONS contains '%location', then make sure the ERROR-LOCATION
 # is correctly output on stderr.
 #
-# If BISON-OPTIONS contains `%error-verbose', then make sure the
-# IF-YYERROR-VERBOSE message is properly output after `syntax error, '
+# If BISON-OPTIONS contains '%define parse.error verbose', then make sure the
+# IF-YYERROR-VERBOSE message is properly output after 'syntax error, '
 # on STDERR.
 #
-# If BISON-OPTIONS contains `%debug' but not `%glr', then NUM-STDERR-LINES
+# If BISON-OPTIONS contains '%debug' but not '%glr', then NUM-STDERR-LINES
 # is the number of expected lines on stderr.
 m4_define([_AT_CHECK_CALC_ERROR],
 [m4_bmatch([$3], [^/],
@@ -453,8 +449,8 @@ AT_DATA([[expout]],
 AT_YYERROR_SEES_LOC_IF([],
 [[sed 's/^[-0-9.]*: //' expout >at-expout
 mv at-expout expout]])
-# 4. If error-verbose is not used, strip the`, unexpected....' part.
-m4_bmatch([$1], [%error-verbose], [],
+# 4. If error-verbose is not used, strip the', unexpected....' part.
+m4_bmatch([$1], [%define parse.error verbose], [],
 [[sed 's/syntax error, .*$/syntax error/' expout >at-expout
 mv at-expout expout]])
 # 5. Check
@@ -462,18 +458,20 @@ AT_CHECK([cat stderr], 0, [expout])
 ])
 
 
-# AT_CHECK_SPACES([FILE])
-# -----------------------
+# AT_CHECK_SPACES([FILES])
+# ------------------------
 # Make sure we did not introduce bad spaces.  Checked here because all
 # the skeletons are (or should be) exercized here.
 m4_define([AT_CHECK_SPACES],
 [AT_CHECK([$PERL -ne '
   chomp;
-  print "$.: {$_}\n"
+  print "$ARGV:$.: {$_}\n"
     if (# No starting/ending empty lines.
         (eof || $. == 1) && /^\s*$/
-        # No trailing space.  FIXME: not ready for "maint".
-        # || /\s$/
+        # No trailing space.
+        || /\s$/
+        # No tabs.
+        || /\t/
         )' $1
 ])dnl
 ])
@@ -481,7 +479,7 @@ m4_define([AT_CHECK_SPACES],
 
 # AT_CHECK_CALC([BISON-OPTIONS])
 # ------------------------------
-# Start a testing chunk which compiles `calc' grammar with
+# Start a testing chunk which compiles 'calc' grammar with
 # BISON-OPTIONS, and performs several tests over the parser.
 m4_define([AT_CHECK_CALC],
 [m4_ifval([$2], [m4_fatal([$0: expected a single argument])])
@@ -493,8 +491,9 @@ AT_BISON_OPTION_PUSHDEFS([$1])
 
 AT_DATA_CALC_Y([$1])
 AT_FULL_COMPILE([calc], AT_DEFINES_IF([[lex], [main]]))
-AT_CHECK_SPACES([calc.AT_SKEL_CC_IF([cc], [c])])
-AT_DEFINES_IF([AT_CHECK_SPACES([calc.AT_SKEL_CC_IF([hh], [h])])])
+AT_CHECK_SPACES(m4_join([ ],
+                        [calc.AT_SKEL_CC_IF([cc], [c])],
+                        [AT_DEFINES_IF([calc.AT_SKEL_CC_IF([hh], [h])])]))
 
 # Test the priorities.
 _AT_CHECK_CALC([$1],
@@ -540,7 +539,7 @@ _AT_CHECK_CALC_ERROR([$1], [1], [/dev/null], [4],
 #   - (* * *): nothing to pop, a lot to discard
 #   - (1 + 2 * *): some to pop and discard
 #
-# - test the action associated to `error'
+# - test the action associated to 'error'
 #
 # - check the lookahead that triggers an error is not discarded
 #   when we enter error recovery.  Below, the lookahead causing the
@@ -589,7 +588,7 @@ AT_BANNER([[Simple LALR(1) Calculator.]])
 
 # AT_CHECK_CALC_LALR([BISON-OPTIONS])
 # -----------------------------------
-# Start a testing chunk which compiles `calc' grammar with
+# Start a testing chunk which compiles 'calc' grammar with
 # BISON-OPTIONS, and performs several tests over the parser.
 m4_define([AT_CHECK_CALC_LALR],
 [AT_CHECK_CALC($@)])
@@ -599,26 +598,26 @@ AT_CHECK_CALC_LALR()
 AT_CHECK_CALC_LALR([%defines])
 AT_CHECK_CALC_LALR([%locations])
 
-AT_CHECK_CALC_LALR([%name-prefix="calc"]) dnl test deprecated `='
+AT_CHECK_CALC_LALR([%name-prefix "calc"])
 AT_CHECK_CALC_LALR([%verbose])
 AT_CHECK_CALC_LALR([%yacc])
-AT_CHECK_CALC_LALR([%error-verbose])
+AT_CHECK_CALC_LALR([%define parse.error verbose])
 
 AT_CHECK_CALC_LALR([%define api.pure full %locations])
 AT_CHECK_CALC_LALR([%define api.push-pull both %define api.pure full %locations])
-AT_CHECK_CALC_LALR([%error-verbose %locations])
+AT_CHECK_CALC_LALR([%define parse.error verbose %locations])
 
-AT_CHECK_CALC_LALR([%error-verbose %locations %defines %name-prefix "calc" %verbose %yacc])
-AT_CHECK_CALC_LALR([%error-verbose %locations %defines %define api.prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_LALR([%define parse.error verbose %locations %defines %define api.prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_LALR([%define parse.error verbose %locations %defines %name-prefix "calc" %define api.token.prefix "TOK_" %verbose %yacc])
 
 AT_CHECK_CALC_LALR([%debug])
-AT_CHECK_CALC_LALR([%error-verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc])
-AT_CHECK_CALC_LALR([%error-verbose %debug %locations %defines %define api.prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_LALR([%define parse.error verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_LALR([%define parse.error verbose %debug %locations %defines %define api.prefix "calc" %verbose %yacc])
 
-AT_CHECK_CALC_LALR([%define api.pure full %verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc])
-AT_CHECK_CALC_LALR([%define api.push-pull both %define api.pure full %verbose %debug %locations %defines %define api.prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_LALR([%define api.pure full %define parse.error verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_LALR([%define api.push-pull both %define api.pure full %define parse.error verbose %debug %locations %defines %define api.prefix "calc" %verbose %yacc])
 
-AT_CHECK_CALC_LALR([%define api.pure %error-verbose %debug %locations %defines %define api.prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
+AT_CHECK_CALC_LALR([%define api.pure %define parse.error verbose %debug %locations %defines %define api.prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
 
 
 # ----------------------- #
@@ -629,7 +628,7 @@ AT_BANNER([[Simple GLR Calculator.]])
 
 # AT_CHECK_CALC_GLR([BISON-OPTIONS])
 # ----------------------------------
-# Start a testing chunk which compiles `calc' grammar with
+# Start a testing chunk which compiles 'calc' grammar with
 # BISON-OPTIONS and %glr-parser, and performs several tests over the parser.
 m4_define([AT_CHECK_CALC_GLR],
 [AT_CHECK_CALC([%glr-parser] $@)])
@@ -643,21 +642,21 @@ AT_CHECK_CALC_GLR([%name-prefix "calc"])
 AT_CHECK_CALC_GLR([%define api.prefix "calc"])
 AT_CHECK_CALC_GLR([%verbose])
 AT_CHECK_CALC_GLR([%yacc])
-AT_CHECK_CALC_GLR([%error-verbose])
+AT_CHECK_CALC_GLR([%define parse.error verbose])
 
 AT_CHECK_CALC_GLR([%define api.pure %locations])
-AT_CHECK_CALC_GLR([%error-verbose %locations])
+AT_CHECK_CALC_GLR([%define parse.error verbose %locations])
 
-AT_CHECK_CALC_GLR([%error-verbose %locations %defines %name-prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_GLR([%define parse.error verbose %locations %defines %name-prefix "calc" %verbose %yacc])
 
 AT_CHECK_CALC_GLR([%debug])
-AT_CHECK_CALC_GLR([%error-verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc])
-AT_CHECK_CALC_GLR([%error-verbose %debug %locations %defines %define api.prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_GLR([%define parse.error verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_GLR([%define parse.error verbose %debug %locations %defines %define api.prefix "calc" %define api.token.prefix "TOK_" %verbose %yacc])
 
-AT_CHECK_CALC_GLR([%define api.pure %error-verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_GLR([%define api.pure %define parse.error verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc])
 
-AT_CHECK_CALC_GLR([%define api.pure %error-verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
-AT_CHECK_CALC_GLR([%define api.pure %error-verbose %debug %locations %defines %define api.prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
+AT_CHECK_CALC_GLR([%define api.pure %define parse.error verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
+AT_CHECK_CALC_GLR([%define api.pure %define parse.error verbose %debug %locations %defines %define api.prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
 
 
 # ----------------------------- #
@@ -667,25 +666,30 @@ AT_CHECK_CALC_GLR([%define api.pure %error-verbose %debug %locations %defines %d
 AT_BANNER([[Simple LALR(1) C++ Calculator.]])
 
 # First let's try using %skeleton
-AT_CHECK_CALC([%skeleton "lalr1.cc" %defines %locations])
+AT_CHECK_CALC([%skeleton "lalr1.cc" %defines])
 
 # AT_CHECK_CALC_LALR1_CC([BISON-OPTIONS])
 # ---------------------------------------
-# Start a testing chunk which compiles `calc' grammar with
+# Start a testing chunk which compiles 'calc' grammar with
 # the C++ skeleton, and performs several tests over the parser.
 m4_define([AT_CHECK_CALC_LALR1_CC],
-[AT_CHECK_CALC([%language "C++" %defines %locations] $@)])
+[AT_CHECK_CALC([%language "C++"] $@)])
 
 AT_CHECK_CALC_LALR1_CC([])
-AT_CHECK_CALC_LALR1_CC([%define api.location.type Span])
-AT_CHECK_CALC_LALR1_CC([%error-verbose %name-prefix "calc" %verbose %yacc])
-AT_CHECK_CALC_LALR1_CC([%error-verbose %define api.prefix "calc" %verbose %yacc])
-AT_CHECK_CALC_LALR1_CC([%error-verbose %debug %name-prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_LALR1_CC([%locations])
+AT_CHECK_CALC_LALR1_CC([%locations %define api.location.type Span])
+AT_CHECK_CALC_LALR1_CC([%defines %locations %define parse.error verbose %name-prefix "calc" %verbose %yacc])
+
+AT_CHECK_CALC_LALR1_CC([%locations %define parse.error verbose %define api.prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_LALR1_CC([%locations %define parse.error verbose %debug %name-prefix "calc" %verbose %yacc])
+
+AT_CHECK_CALC_LALR1_CC([%locations %pure-parser %define parse.error verbose %debug %define api.prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_LALR1_CC([%locations %pure-parser %define parse.error verbose %debug %define api.prefix "calc" %define api.token.prefix "TOK_" %verbose %yacc])
 
-AT_CHECK_CALC_LALR1_CC([%pure-parser %error-verbose %debug %define api.prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_LALR1_CC([%defines %locations %pure-parser %define parse.error verbose %debug %name-prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
 
-AT_CHECK_CALC_LALR1_CC([%pure-parser %error-verbose %debug %name-prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
-AT_CHECK_CALC_LALR1_CC([%pure-parser %error-verbose %debug %define api.prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
+AT_CHECK_CALC_LALR1_CC([%pure-parser %define parse.error verbose %debug %define api.prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
+AT_CHECK_CALC_LALR1_CC([%defines %locations %pure-parser %define parse.error verbose %debug %define api.prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
 
 
 
@@ -696,24 +700,26 @@ AT_CHECK_CALC_LALR1_CC([%pure-parser %error-verbose %debug %define api.prefix "c
 AT_BANNER([[Simple GLR C++ Calculator.]])
 
 # Again, we try also using %skeleton.
-AT_CHECK_CALC([%skeleton "glr.cc" %defines %locations])
+AT_CHECK_CALC([%skeleton "glr.cc"])
 
 # AT_CHECK_CALC_GLR_CC([BISON-OPTIONS])
 # -------------------------------------
-# Start a testing chunk which compiles `calc' grammar with
+# Start a testing chunk which compiles 'calc' grammar with
 # the GLR C++ skeleton, and performs several tests over the parser.
 m4_define([AT_CHECK_CALC_GLR_CC],
-[AT_CHECK_CALC([%language "C++" %glr-parser %defines %locations] $@)])
+[AT_CHECK_CALC([%language "C++" %glr-parser] $@)])
 
 AT_CHECK_CALC_GLR_CC([])
-AT_CHECK_CALC_GLR_CC([%define api.location.type Span])
-AT_CHECK_CALC_GLR_CC([%error-verbose %name-prefix "calc" %verbose %yacc])
-AT_CHECK_CALC_GLR_CC([%error-verbose %define api.prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_GLR_CC([%locations])
+AT_CHECK_CALC_GLR_CC([%locations %define api.location.type Span])
+AT_CHECK_CALC_GLR_CC([%defines %define parse.error verbose %name-prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_GLR_CC([%define parse.error verbose %define api.prefix "calc" %verbose %yacc])
 
 AT_CHECK_CALC_GLR_CC([%debug])
-AT_CHECK_CALC_GLR_CC([%error-verbose %debug %name-prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_GLR_CC([%define parse.error verbose %debug %name-prefix "calc" %verbose %yacc])
 
-AT_CHECK_CALC_GLR_CC([%pure-parser %error-verbose %debug %name-prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_GLR_CC([%pure-parser %define parse.error verbose %debug %name-prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_GLR_CC([%pure-parser %define parse.error verbose %debug %name-prefix "calc" %define api.token.prefix "TOK_" %verbose %yacc])
 
-AT_CHECK_CALC_GLR_CC([%pure-parser %error-verbose %debug %name-prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
-AT_CHECK_CALC_GLR_CC([%pure-parser %error-verbose %debug %define api.prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
+AT_CHECK_CALC_GLR_CC([%locations %defines %pure-parser %define parse.error verbose %debug %name-prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
+AT_CHECK_CALC_GLR_CC([%locations %defines %pure-parser %define parse.error verbose %debug %define api.prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
index 09114a81b78877fe553816bb39283a6fe64d5aeb..2d67a35848cb7e739268ee4d600b4dcb23c94a48 100644 (file)
@@ -1,7 +1,6 @@
 # Exercising Bison on conflicts.                         -*- Autotest -*-
 
-# Copyright (C) 2002-2005, 2007, 2009-2013 Free Software Foundation,
-# Inc.
+# Copyright (C) 2002-2005, 2007-2013 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
 
 AT_BANNER([[Conflicts.]])
 
+## ------------------------- ##
+## Token declaration order.  ##
+## ------------------------- ##
+
+# This test checks that token are declared left to right when in a precedence
+# statement.
+
+AT_SETUP([Token declaration order])
+
+AT_BISON_OPTION_PUSHDEFS
+
+AT_DATA_GRAMMAR([[input.y]],
+[[%code {
+  #include <stdio.h>
+  ]AT_YYERROR_DECLARE[
+  ]AT_YYLEX_DECLARE[
+}
+%token A B C
+%token D
+%right E F G
+%right H I
+%right J
+%left  K
+%left  L M N
+%nonassoc O P Q
+%precedence R S T U
+%precedence V W
+%%
+exp: A
+%%
+]AT_YYERROR_DEFINE[
+]AT_YYLEX_DEFINE[
+int main (void)
+{
+  assert (A < B);
+  assert (B < C);
+  assert (C < D);
+  assert (D < E);
+  assert (E < F);
+  assert (F < G);
+  assert (G < H);
+  assert (H < I);
+  assert (I < J);
+  assert (J < K);
+  assert (K < L);
+  assert (L < M);
+  assert (M < N);
+  assert (N < O);
+  assert (O < P);
+  assert (P < Q);
+  assert (Q < R);
+  assert (R < S);
+  assert (S < T);
+  assert (T < U);
+  assert (U < V);
+  assert (V < W);
+  return 0;
+}
+]])
+
+AT_BISON_CHECK([-o input.c input.y])
+AT_COMPILE([input])
+
+AT_PARSER_CHECK([./input])
+
+AT_BISON_OPTION_POPDEFS
+
+AT_CLEANUP
+
+
+## --------------------------------------------------- ##
+## Token declaration order: literals vs. identifiers.  ##
+## --------------------------------------------------- ##
+
+# This test checks that when several tokens are declared by the same keyword,
+# some of them defined as a character ('a'), others as simple textual reference
+# (A), they are declared correctly left to right.
+# Previously, the following test would declare the states in the order 'o' 'p'
+# M N, instead of M N 'o' 'p'.
+
+AT_SETUP([Token declaration order: literals vs. identifiers])
+
+AT_DATA_GRAMMAR([[input.y]],
+[[%token 'a' 'b' C D
+%token E F 'g' 'h'
+%right 'i' 'j' K L
+%right M N 'o' 'p'
+%%
+exp: 'a'
+   | 'b'
+   | C
+   | D
+   | E
+   | F
+   | 'g'
+   | 'h'
+   | 'i'
+   | 'j'
+   | K
+   | L
+   | M
+   | N
+   | 'o'
+   | 'p'
+;
+%%
+]])
+
+AT_BISON_CHECK([[--report=all -o input.c input.y]], 0, [], [ignore])
+AT_CHECK([[cat input.output | sed -n '/^State 0$/,/^State 1$/p']], 0,
+[[State 0
+
+    0 $accept: . exp $end
+    1 exp: . 'a'
+    2    | . 'b'
+    3    | . C
+    4    | . D
+    5    | . E
+    6    | . F
+    7    | . 'g'
+    8    | . 'h'
+    9    | . 'i'
+   10    | . 'j'
+   11    | . K
+   12    | . L
+   13    | . M
+   14    | . N
+   15    | . 'o'
+   16    | . 'p'
+
+    'a'  shift, and go to state 1
+    'b'  shift, and go to state 2
+    C    shift, and go to state 3
+    D    shift, and go to state 4
+    E    shift, and go to state 5
+    F    shift, and go to state 6
+    'g'  shift, and go to state 7
+    'h'  shift, and go to state 8
+    'i'  shift, and go to state 9
+    'j'  shift, and go to state 10
+    K    shift, and go to state 11
+    L    shift, and go to state 12
+    M    shift, and go to state 13
+    N    shift, and go to state 14
+    'o'  shift, and go to state 15
+    'p'  shift, and go to state 16
+
+    exp  go to state 17
+
+
+State 1
+]])
+
+AT_CLEANUP
+
+
+## ------------------------------- ##
+## Useless associativity warning.  ##
+## ------------------------------- ##
+
+AT_SETUP([Useless associativity warning])
+
+AT_DATA([[input.y]],
+[[%nonassoc "="
+%left "+"
+%left "*"
+%precedence "("
+%%
+stmt:
+  exp
+| "var" "=" exp
+;
+
+exp:
+  exp "+" exp
+| exp "*" "num"
+| "(" exp ")"
+| "num"
+;
+]])
+
+AT_BISON_CHECK([-Wprecedence input.y], 0, [],
+[[input.y:1.11-13: warning: useless precedence and associativity for "=" [-Wprecedence]
+input.y:3.7-9: warning: useless associativity for "*", use %precedence [-Wprecedence]
+input.y:4.13-15: warning: useless precedence for "(" [-Wprecedence]
+]])
+
+AT_CLEANUP
+
+
+## ---------------------------- ##
+## Useless precedence warning.  ##
+## ---------------------------- ##
+
+AT_SETUP([Useless precedence warning])
+
+AT_DATA([[input.y]],
+[[%token A B
+%precedence Z
+%left X
+%precedence Y
+%left W
+%right V
+%nonassoc U
+%%
+a: b
+ | a U b
+ | f
+;
+b: c
+ | b V c
+;
+c: d
+ | c W d
+;
+d: A
+ | d X d
+ | d Y A
+;
+f: B
+ | f Z B
+;
+]])
+
+AT_BISON_CHECK([-Wprecedence -fcaret -o input.c input.y], 0, [],
+[[input.y:2.13: warning: useless precedence for Z [-Wprecedence]
+ %precedence Z
+             ^
+input.y:5.7: warning: useless precedence and associativity for W [-Wprecedence]
+ %left W
+       ^
+input.y:6.8: warning: useless precedence and associativity for V [-Wprecedence]
+ %right V
+        ^
+input.y:7.11: warning: useless precedence and associativity for U [-Wprecedence]
+ %nonassoc U
+           ^
+]])
+
+AT_CLEANUP
+
 
 ## ---------------- ##
 ## S/R in initial.  ##
@@ -38,11 +278,11 @@ e: 'e' | /* Nothing. */;
 ]])
 
 AT_BISON_CHECK([-o input.c input.y], 0, [],
-[[input.y:4.9: warning: rule useless in parser due to conflicts: e: /* empty */
+[[input.y:4.9: warning: rule useless in parser due to conflicts [-Wother]
 ]])
 
 AT_BISON_CHECK([-fcaret -o input.c input.y], 0, [],
-[[input.y:4.9: warning: rule useless in parser due to conflicts
+[[input.y:4.9: warning: rule useless in parser due to conflicts [-Wother]
  e: 'e' | /* Nothing. */;
          ^
 ]])
@@ -124,10 +364,10 @@ AT_NONASSOC_AND_EOF_CHECK([], [[incorrect]])
 
 # We must disable default reductions in inconsistent states in order to
 # have an explicit list of all expected tokens.
-AT_NONASSOC_AND_EOF_CHECK([[-Dlr.default-reductions=consistent]],
+AT_NONASSOC_AND_EOF_CHECK([[-Dlr.default-reduction=consistent]],
                           [[correct]])
 
-# lr.default-reductions=consistent happens to work for this test case.
+# lr.default-reduction=consistent happens to work for this test case.
 # However, for other grammars, lookahead sets can be merged for
 # different left contexts, so it is still possible to have an incorrect
 # expected list.  Canonical LR is almost a general solution (that is, it
@@ -148,11 +388,11 @@ AT_CLEANUP
 
 
 
-## -------------------------------------- ##
-## %error-verbose and consistent errors.  ##
-## -------------------------------------- ##
+## ------------------------------------------- ##
+## parse.error=verbose and consistent errors.  ##
+## ------------------------------------------- ##
 
-AT_SETUP([[%error-verbose and consistent errors]])
+AT_SETUP([[parse.error=verbose and consistent errors]])
 
 m4_pushdef([AT_CONSISTENT_ERRORS_CHECK], [
 
@@ -170,7 +410,6 @@ AT_SKEL_JAVA_IF([AT_DATA], [AT_DATA_GRAMMAR])([input.y],
 }]], [[
 
 %code {]AT_SKEL_CC_IF([[
-  #include <cassert>
   #include <string>]], [[
   #include <assert.h>
   #include <stdio.h>
@@ -183,7 +422,7 @@ AT_SKEL_JAVA_IF([AT_DATA], [AT_DATA_GRAMMAR])([input.y],
 
 ]$1[
 
-%error-verbose
+%define parse.error verbose
 
 %%
 
@@ -223,30 +462,9 @@ public Object getLVal ()
 
 /*-------.
 | main.  |
-`-------*/]AT_SKEL_JAVA_IF([[
-
-class input
-{
-  public static void main (String args[]) throws IOException
-  {
-    YYParser p = new YYParser ();
-    p.parse ();
-  }
-}]], [AT_SKEL_CC_IF([[
-
-int
-main (void)
-{
-  yy::parser parser;
-  return parser.parse ();
-}]], [[
-
-int
-main (void)
-{
-  return yyparse ();
-}]])])[
-]])
+`-------*/
+]AT_MAIN_DEFINE
+])
 
 AT_FULL_COMPILE([[input]])
 
@@ -318,12 +536,12 @@ AT_CONSISTENT_ERRORS_CHECK([[%define lr.type ielr
 
 # Even canonical LR doesn't foresee the error for 'a'!
 AT_CONSISTENT_ERRORS_CHECK([[%define lr.type ielr
-                             %define lr.default-reductions consistent]],
+                             %define lr.default-reduction consistent]],
                            [AT_PREVIOUS_STATE_GRAMMAR],
                            [AT_PREVIOUS_STATE_INPUT],
                            [[$end]], [[ab]])
 AT_CONSISTENT_ERRORS_CHECK([[%define lr.type ielr
-                             %define lr.default-reductions accepting]],
+                             %define lr.default-reduction accepting]],
                            [AT_PREVIOUS_STATE_GRAMMAR],
                            [AT_PREVIOUS_STATE_INPUT],
                            [[$end]], [[ab]])
@@ -378,7 +596,7 @@ error-reduce:
 ;
 
 consistent-reduction: /*empty*/ {
-  assert (yychar == ]AT_SKEL_CC_IF([[yyempty_]], [[YYEMPTY]])[);
+  assert (yychar == YYEMPTY);
   yylval = 0;
   yychar = 'b';
 } ;
@@ -402,19 +620,15 @@ AT_CONSISTENT_ERRORS_CHECK([[%glr-parser]],
                            [AT_USER_ACTION_GRAMMAR],
                            [AT_USER_ACTION_INPUT],
                            [['b']], [[none]])
-AT_CONSISTENT_ERRORS_CHECK([[%language "c++"]],
-                           [AT_USER_ACTION_GRAMMAR],
-                           [AT_USER_ACTION_INPUT],
-                           [['b']], [[none]])
-# No Java test because yychar cannot be manipulated by users.
+# No C++ or Java test because yychar cannot be manipulated by users.
 
-AT_CONSISTENT_ERRORS_CHECK([[%define lr.default-reductions consistent]],
+AT_CONSISTENT_ERRORS_CHECK([[%define lr.default-reduction consistent]],
                            [AT_USER_ACTION_GRAMMAR],
                            [AT_USER_ACTION_INPUT],
                            [['b']], [[none]])
 
 # Canonical LR doesn't foresee the error for 'a'!
-AT_CONSISTENT_ERRORS_CHECK([[%define lr.default-reductions accepting]],
+AT_CONSISTENT_ERRORS_CHECK([[%define lr.default-reduction accepting]],
                            [AT_USER_ACTION_GRAMMAR],
                            [AT_USER_ACTION_INPUT],
                            [[$end]], [[a]])
@@ -428,7 +642,7 @@ AT_CONSISTENT_ERRORS_CHECK([[%define parse.lac full]],
                            [AT_USER_ACTION_INPUT],
                            [['b']], [[none]])
 AT_CONSISTENT_ERRORS_CHECK([[%define parse.lac full
-                             %define lr.default-reductions accepting]],
+                             %define lr.default-reduction accepting]],
                            [AT_USER_ACTION_GRAMMAR],
                            [AT_USER_ACTION_INPUT],
                            [[$end]], [[none]])
@@ -498,19 +712,14 @@ reduce-nonassoc: %prec 'a';
 %%
 ]AT_YYERROR_DEFINE[
 ]AT_YYLEX_DEFINE(["aaa"])[
-
-int
-main (void)
-{
-  return yyparse ();
-}
-]])
+]AT_MAIN_DEFINE
+])
 AT_BISON_OPTION_POPDEFS
 
 # Show canonical LR's failure.
 AT_BISON_CHECK([[-Dlr.type=canonical-lr -o input.c input.y]],
                [[0]], [[]],
-[[input.y: conflicts: 2 shift/reduce
+[[input.y: warning: 2 shift/reduce conflicts [-Wconflicts-sr]
 ]])
 AT_COMPILE([[input]])
 AT_PARSER_CHECK([[./input]], [[1]], [[]],
@@ -520,7 +729,7 @@ AT_PARSER_CHECK([[./input]], [[1]], [[]],
 # It's corrected by LAC.
 AT_BISON_CHECK([[-Dlr.type=canonical-lr -Dparse.lac=full \
                  -o input.c input.y]], [[0]], [[]],
-[[input.y: conflicts: 2 shift/reduce
+[[input.y: warning: 2 shift/reduce conflicts [-Wconflicts-sr]
 ]])
 AT_COMPILE([[input]])
 AT_PARSER_CHECK([[./input]], [[1]], [[]],
@@ -530,7 +739,7 @@ AT_PARSER_CHECK([[./input]], [[1]], [[]],
 # IELR is sufficient when LAC is used.
 AT_BISON_CHECK([[-Dlr.type=ielr -Dparse.lac=full -o input.c input.y]],
                [[0]], [[]],
-[[input.y: conflicts: 2 shift/reduce
+[[input.y: warning: 2 shift/reduce conflicts [-Wconflicts-sr]
 ]])
 AT_COMPILE([[input]])
 AT_PARSER_CHECK([[./input]], [[1]], [[]],
@@ -554,8 +763,8 @@ exp: exp OP exp | NUM;
 ]])
 
 AT_BISON_CHECK([-o input.c --report=all input.y], 0, [],
-[input.y: conflicts: 1 shift/reduce
-])
+[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
+]])
 
 # Check the contents of the report.
 AT_CHECK([cat input.output], [],
@@ -747,6 +956,62 @@ State 5
 AT_CLEANUP
 
 
+## ---------------------- ##
+## %precedence suffices.  ##
+## ---------------------- ##
+
+AT_SETUP([%precedence suffices])
+
+AT_DATA([input.y],
+[[%precedence "then"
+%precedence "else"
+%%
+stmt:
+  "if" cond "then" stmt
+| "if" cond "then" stmt "else" stmt
+| "stmt"
+;
+
+cond:
+  "exp"
+;
+]])
+
+AT_BISON_CHECK([-o input.c input.y])
+
+AT_CLEANUP
+
+
+## ------------------------------ ##
+## %precedence does not suffice.  ##
+## ------------------------------ ##
+
+AT_SETUP([%precedence does not suffice])
+
+AT_DATA([input.y],
+[[%precedence "then"
+%precedence "else"
+%%
+stmt:
+  "if" cond "then" stmt
+| "if" cond "then" stmt "else" stmt
+| "stmt"
+;
+
+cond:
+  "exp"
+| cond "then" cond
+;
+]])
+
+AT_BISON_CHECK([-o input.c input.y], 0, [],
+[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
+input.y:12.3-18: warning: rule useless in parser due to conflicts [-Wother]
+]])
+
+AT_CLEANUP
+
+
 ## -------------------------------- ##
 ## Defaulted Conflicted Reduction.  ##
 ## -------------------------------- ##
@@ -757,13 +1022,13 @@ AT_CLEANUP
 #    $end           reduce using rule 3 (num)
 #    $end           [reduce using rule 4 (id)]
 #
-# But when `reduce 3' is the default action, we'd produce:
+# But when 'reduce 3' is the default action, we'd produce:
 #
 #    $end           [reduce using rule 4 (id)]
 #    $default    reduce using rule 3 (num)
 #
 # In this precise case (a reduction is masked by the default
-# reduction), we make the `reduce 3' explicit:
+# reduction), we make the 'reduce 3' explicit:
 #
 #    $end           reduce using rule 3 (num)
 #    $end           [reduce using rule 4 (id)]
@@ -784,8 +1049,8 @@ id : '0';
 ]])
 
 AT_BISON_CHECK([-o input.c --report=all input.y], 0, [],
-[[input.y: conflicts: 1 reduce/reduce
-input.y:4.6-8: warning: rule useless in parser due to conflicts: id: '0'
+[[input.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
+input.y:4.6-8: warning: rule useless in parser due to conflicts [-Wother]
 ]])
 
 # Check the contents of the report.
@@ -901,9 +1166,8 @@ exp: exp OP exp | NUM;
 ]])
 
 AT_BISON_CHECK([-o input.c input.y], 1, [],
-[input.y: conflicts: 1 shift/reduce
-input.y: error: expected 0 shift/reduce conflicts
-])
+[[input.y: error: shift/reduce conflicts: 1 found, 0 expected
+]])
 AT_CLEANUP
 
 
@@ -938,9 +1202,8 @@ exp: exp OP exp | NUM;
 ]])
 
 AT_BISON_CHECK([-o input.c input.y], 1, [],
-[input.y: conflicts: 1 shift/reduce
-input.y: error: expected 2 shift/reduce conflicts
-])
+[[input.y: error: shift/reduce conflicts: 1 found, 2 expected
+]])
 AT_CLEANUP
 
 
@@ -958,9 +1221,8 @@ a: 'a';
 ]])
 
 AT_BISON_CHECK([-o input.c input.y], 1, [],
-[input.y: conflicts: 1 reduce/reduce
-input.y: error: expected 0 reduce/reduce conflicts
-])
+[[input.y: error: reduce/reduce conflicts: 1 found, 0 expected
+]])
 AT_CLEANUP
 
 
@@ -1001,8 +1263,10 @@ e:   e '+' e
    ;
 ]])
 
-AT_BISON_CHECK([-o input.c input.y], 0, [],
-[[input.y: conflicts: 4 shift/reduce
+AT_BISON_CHECK([-Wall -o input.c input.y], 0, [],
+[[input.y: warning: 4 shift/reduce conflicts [-Wconflicts-sr]
+input.y:1.7-9: warning: useless precedence and associativity for '+' [-Wprecedence]
+input.y:2.7-9: warning: useless precedence and associativity for '*' [-Wprecedence]
 ]])
 AT_CLEANUP
 
@@ -1104,14 +1368,15 @@ reported_conflicts:
 ]])
 
 AT_BISON_CHECK([[--report=all input.y]], 0, [],
-[[input.y: conflicts: 1 shift/reduce, 1 reduce/reduce
-input.y:12.5-20: warning: rule useless in parser due to conflicts: resolved_conflict: 'a' unreachable1
-input.y:20.5-20: warning: rule useless in parser due to conflicts: unreachable1: 'a' unreachable2
-input.y:21.4: warning: rule useless in parser due to conflicts: unreachable1: /* empty */
-input.y:25.13: warning: rule useless in parser due to conflicts: unreachable2: /* empty */
-input.y:25.16: warning: rule useless in parser due to conflicts: unreachable2: /* empty */
-input.y:31.5-7: warning: rule useless in parser due to conflicts: reported_conflicts: 'a'
-input.y:32.4: warning: rule useless in parser due to conflicts: reported_conflicts: /* empty */
+[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
+input.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
+input.y:12.5-20: warning: rule useless in parser due to conflicts [-Wother]
+input.y:20.5-20: warning: rule useless in parser due to conflicts [-Wother]
+input.y:21.4: warning: rule useless in parser due to conflicts [-Wother]
+input.y:25.13: warning: rule useless in parser due to conflicts [-Wother]
+input.y:25.16: warning: rule useless in parser due to conflicts [-Wother]
+input.y:31.5-7: warning: rule useless in parser due to conflicts [-Wother]
+input.y:32.4: warning: rule useless in parser due to conflicts [-Wother]
 ]])
 
 AT_CHECK([[cat input.output]], 0,
@@ -1120,13 +1385,13 @@ AT_CHECK([[cat input.output]], 0,
     2 resolved_conflict: 'a' unreachable1
 
     4 unreachable1: 'a' unreachable2
-    5             | /* empty */
+    5             | %empty
 
-    6 unreachable2: /* empty */
-    7             | /* empty */
+    6 unreachable2: %empty
+    7             | %empty
 
     9 reported_conflicts: 'a'
-   10                   | /* empty */
+   10                   | %empty
 
 
 State 4 conflicts: 1 shift/reduce
@@ -1140,17 +1405,17 @@ Grammar
     1 start: resolved_conflict 'a' reported_conflicts 'a'
 
     2 resolved_conflict: 'a' unreachable1
-    3                  | /* empty */
+    3                  | %empty
 
     4 unreachable1: 'a' unreachable2
-    5             | /* empty */
+    5             | %empty
 
-    6 unreachable2: /* empty */
-    7             | /* empty */
+    6 unreachable2: %empty
+    7             | %empty
 
     8 reported_conflicts: 'a'
     9                   | 'a'
-   10                   | /* empty */
+   10                   | %empty
 
 
 Terminals, with rules where they appear
@@ -1251,16 +1516,17 @@ State 7
 ]])
 
 AT_DATA([[input-keep.y]],
-[[%define lr.keep-unreachable-states
+[[%define lr.keep-unreachable-state
 ]])
 AT_CHECK([[cat input.y >> input-keep.y]])
 
 AT_BISON_CHECK([[input-keep.y]], 0, [],
-[[input-keep.y: conflicts: 2 shift/reduce, 2 reduce/reduce
-input-keep.y:22.4: warning: rule useless in parser due to conflicts: unreachable1: /* empty */
-input-keep.y:26.16: warning: rule useless in parser due to conflicts: unreachable2: /* empty */
-input-keep.y:32.5-7: warning: rule useless in parser due to conflicts: reported_conflicts: 'a'
-input-keep.y:33.4: warning: rule useless in parser due to conflicts: reported_conflicts: /* empty */
+[[input-keep.y: warning: 2 shift/reduce conflicts [-Wconflicts-sr]
+input-keep.y: warning: 2 reduce/reduce conflicts [-Wconflicts-rr]
+input-keep.y:22.4: warning: rule useless in parser due to conflicts [-Wother]
+input-keep.y:26.16: warning: rule useless in parser due to conflicts [-Wother]
+input-keep.y:32.5-7: warning: rule useless in parser due to conflicts [-Wother]
+input-keep.y:33.4: warning: rule useless in parser due to conflicts [-Wother]
 ]])
 
 AT_CLEANUP
@@ -1415,9 +1681,40 @@ State 1
 AT_CLEANUP
 
 
-## --------------------------------- ##
-## -W versus %expect and %expect-rr  ##
-## --------------------------------- ##
+## -------------------- ##
+## %expect-rr non GLR.  ##
+## -------------------- ##
+
+AT_SETUP([[%expect-rr non GLR]])
+
+AT_DATA([[1.y]],
+[[%expect-rr 0
+%%
+exp: 'a'
+]])
+
+AT_BISON_CHECK([[1.y]], [[0]], [],
+[[1.y: warning: %expect-rr applies only to GLR parsers [-Wother]
+]])
+
+AT_DATA([[2.y]],
+[[%expect-rr 1
+%%
+exp: 'a' | 'a';
+]])
+
+AT_BISON_CHECK([[2.y]], [[0]], [],
+[[2.y: warning: %expect-rr applies only to GLR parsers [-Wother]
+2.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
+2.y:3.12-14: warning: rule useless in parser due to conflicts [-Wother]
+]])
+
+AT_CLEANUP
+
+
+## ---------------------------------- ##
+## -W versus %expect and %expect-rr.  ##
+## ---------------------------------- ##
 
 AT_SETUP([[-W versus %expect and %expect-rr]])
 
@@ -1443,17 +1740,27 @@ B: ;
 ]])
 
 AT_BISON_CHECK([[sr-rr.y]], [[0]], [[]],
-[[sr-rr.y: conflicts: 1 shift/reduce, 1 reduce/reduce
+[[sr-rr.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
+sr-rr.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
 ]])
 AT_BISON_CHECK([[-Wno-conflicts-sr sr-rr.y]], [[0]], [[]],
-[[sr-rr.y: conflicts: 1 reduce/reduce
+[[sr-rr.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
 ]])
 AT_BISON_CHECK([[-Wno-conflicts-rr sr-rr.y]], [[0]], [[]],
-[[sr-rr.y: conflicts: 1 shift/reduce
+[[sr-rr.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
 ]])
 
-[for gram in sr-rr sr rr; do
+[
+# This is piece of code is rather complex for a simple task: try every
+# combinaison of (0 or 1 real SR) x (0 or 1 real RR) x (don't %expect
+# or %expect 0, 1, or 2 SR) x (don't %expect-rr or %expect-rr 0, 1, or 2
+# RR).
+
+# Number and types of genuine conflicts in the grammar.
+for gram in sr-rr sr rr; do
+  # Number of expected s/r conflicts.
   for sr_exp_i in '' 0 1 2; do
+    # Number of expected r/r conflicts.
     for rr_exp_i in '' 0 1 2; do
       test -z "$sr_exp_i" && test -z "$rr_exp_i" && continue
 
@@ -1476,36 +1783,38 @@ AT_BISON_CHECK([[-Wno-conflicts-rr sr-rr.y]], [[0]], [[]],
       echo "$directives" > $file
       cat $gram.y >> $file
 
-      # Count actual conflicts.
-      conflicts=
-      sr_count=0
-      rr_count=0
-      if test $gram = sr || test $gram = sr-rr; then
-        conflicts="1 shift/reduce"
-        sr_count=1
-      fi
-      if test $gram = rr || test $gram = sr-rr; then
-        if test -n "$conflicts"; then
-          conflicts="$conflicts, "
-        fi
-        conflicts="${conflicts}1 reduce/reduce"
-        rr_count=1
-      fi
+      # Number of found conflicts.
+      case $gram in
+        (sr)    sr_count=1; rr_count=0;;
+        (rr)    sr_count=0; rr_count=1;;
+        (sr-rr) sr_count=1; rr_count=1;;
+      esac
+
+      # Update number of expected conflicts: if %expect is given then
+      # %expect-rr defaults to 0, and vice-versa.  Leave empty if
+      # nothing expected.
+      case $sr_exp_i:$rr_exp_i in
+        ?:) rr_exp_i=0;;
+        :?) sr_exp_i=0;;
+      esac
 
       # Run tests.
       if test $sr_count -eq $sr_exp && test $rr_count -eq $rr_exp; then
         ]AT_BISON_CHECK([[-Wnone $file]])[
         ]AT_BISON_CHECK([[-Werror $file]])[
       else
-        echo "$file: conflicts: $conflicts" > experr
-        if test $sr_count -ne $sr_exp; then
-          if test $sr_exp -ne 1; then s=s; else s= ; fi
-          echo "$file: error: expected $sr_exp shift/reduce conflict$s" >> experr
-        fi
-        if test $rr_count -ne $rr_exp; then
-          if test $rr_exp -ne 1; then s=s; else s= ; fi
-          echo "$file: error: expected $rr_exp reduce/reduce conflict$s" >> experr
-        fi
+        {
+          if test -z "$sr_exp_i" && test "$sr_count" -ne 0; then
+            echo "warning: $sr_count shift/reduce conflicts"
+          elif test "$sr_exp_i" -ne "$sr_count"; then
+            echo "error: shift/reduce conflicts: $sr_count found, $sr_exp_i expected"
+          fi
+          if test -z "$rr_exp_i" && test "$rr_count" -ne 0; then
+            echo "warning: $rr_count reduce/reduce conflicts"
+          elif test "$rr_exp_i" -ne "$rr_count"; then
+            echo "error: reduce/reduce conflicts: $rr_count found, $rr_exp_i expected"
+          fi
+        } | sed -e "s/^/$file: /" > experr
         ]AT_BISON_CHECK([[-Wnone $file]], [[1]], [[]], [[experr]])[
         ]AT_BISON_CHECK([[-Werror $file]], [[1]], [[]], [[experr]])[
       fi
index 693c4c3402789f52dcacda37e13a14a80fc25070..1772ac544937ae0278a8638707fc6446ea290b6e 100644 (file)
@@ -115,281 +115,281 @@ AT_TEST_EXISTING_GRAMMAR([[GNU AWK 3.1.0 Grammar]],
 ]],
 [[
 start
-       : opt_nls program opt_nls
-       ;
+        : opt_nls program opt_nls
+        ;
 
 program
-       : rule
-       | program rule
-       | error
-       | program error
-       | /* empty */
-       ;
+        : rule
+        | program rule
+        | error
+        | program error
+        | /* empty */
+        ;
 
 rule
-       : LEX_BEGIN {} action
-       | LEX_END {}   action
-       | LEX_BEGIN statement_term
-       | LEX_END statement_term
-       | pattern action
-       | action
-       | pattern statement_term
-       | function_prologue function_body
-       ;
+        : LEX_BEGIN {} action
+        | LEX_END {}   action
+        | LEX_BEGIN statement_term
+        | LEX_END statement_term
+        | pattern action
+        | action
+        | pattern statement_term
+        | function_prologue function_body
+        ;
 
 func_name
-       : NAME
-       | FUNC_CALL
-       | lex_builtin
-       ;
+        : NAME
+        | FUNC_CALL
+        | lex_builtin
+        ;
 
 lex_builtin
-       : LEX_BUILTIN
-       | LEX_LENGTH
-       ;
+        : LEX_BUILTIN
+        | LEX_LENGTH
+        ;
 
 function_prologue
-       : LEX_FUNCTION {} func_name '(' opt_param_list r_paren opt_nls
-       ;
+        : LEX_FUNCTION {} func_name '(' opt_param_list r_paren opt_nls
+        ;
 
 function_body
-       : l_brace statements r_brace opt_semi opt_nls
-       | l_brace r_brace opt_semi opt_nls
-       ;
+        : l_brace statements r_brace opt_semi opt_nls
+        | l_brace r_brace opt_semi opt_nls
+        ;
 
 pattern
-       : exp
-       | exp ',' exp
-       ;
+        : exp
+        | exp ',' exp
+        ;
 
 regexp
-       /*
-        * In this rule, want_regexp tells yylex that the next thing
-        * is a regexp so it should read up to the closing slash.
-        */
-       : '/' {} REGEXP '/'
-       ;
+        /*
+         * In this rule, want_regexp tells yylex that the next thing
+         * is a regexp so it should read up to the closing slash.
+         */
+        : '/' {} REGEXP '/'
+        ;
 
 action
-       : l_brace statements r_brace opt_semi opt_nls
-       | l_brace r_brace opt_semi opt_nls
-       ;
+        : l_brace statements r_brace opt_semi opt_nls
+        | l_brace r_brace opt_semi opt_nls
+        ;
 
 statements
-       : statement
-       | statements statement
-       | error
-       | statements error
-       ;
+        : statement
+        | statements statement
+        | error
+        | statements error
+        ;
 
 statement_term
-       : nls
-       | semi opt_nls
-       ;
+        : nls
+        | semi opt_nls
+        ;
 
 statement
-       : semi opt_nls
-       | l_brace r_brace
-       | l_brace statements r_brace
-       | if_statement
-       | LEX_WHILE '(' exp r_paren opt_nls statement
-       | LEX_DO opt_nls statement LEX_WHILE '(' exp r_paren opt_nls
-       | LEX_FOR '(' NAME LEX_IN NAME r_paren opt_nls statement
-       | LEX_FOR '(' opt_exp semi opt_nls exp semi opt_nls opt_exp r_paren opt_nls statement
-       | LEX_FOR '(' opt_exp semi opt_nls semi opt_nls opt_exp r_paren opt_nls statement
-       | LEX_BREAK statement_term
-       | LEX_CONTINUE statement_term
-       | print '(' expression_list r_paren output_redir statement_term
-       | print opt_rexpression_list output_redir statement_term
-       | LEX_NEXT statement_term
-       | LEX_NEXTFILE statement_term
-       | LEX_EXIT opt_exp statement_term
-       | LEX_RETURN {} opt_exp statement_term
-       | LEX_DELETE NAME '[' expression_list ']' statement_term
-       | LEX_DELETE NAME  statement_term
-       | exp statement_term
-       ;
+        : semi opt_nls
+        | l_brace r_brace
+        | l_brace statements r_brace
+        | if_statement
+        | LEX_WHILE '(' exp r_paren opt_nls statement
+        | LEX_DO opt_nls statement LEX_WHILE '(' exp r_paren opt_nls
+        | LEX_FOR '(' NAME LEX_IN NAME r_paren opt_nls statement
+        | LEX_FOR '(' opt_exp semi opt_nls exp semi opt_nls opt_exp r_paren opt_nls statement
+        | LEX_FOR '(' opt_exp semi opt_nls semi opt_nls opt_exp r_paren opt_nls statement
+        | LEX_BREAK statement_term
+        | LEX_CONTINUE statement_term
+        | print '(' expression_list r_paren output_redir statement_term
+        | print opt_rexpression_list output_redir statement_term
+        | LEX_NEXT statement_term
+        | LEX_NEXTFILE statement_term
+        | LEX_EXIT opt_exp statement_term
+        | LEX_RETURN {} opt_exp statement_term
+        | LEX_DELETE NAME '[' expression_list ']' statement_term
+        | LEX_DELETE NAME  statement_term
+        | exp statement_term
+        ;
 
 print
-       : LEX_PRINT
-       | LEX_PRINTF
-       ;
+        : LEX_PRINT
+        | LEX_PRINTF
+        ;
 
 if_statement
-       : LEX_IF '(' exp r_paren opt_nls statement
-       | LEX_IF '(' exp r_paren opt_nls statement
-            LEX_ELSE opt_nls statement
-       ;
+        : LEX_IF '(' exp r_paren opt_nls statement
+        | LEX_IF '(' exp r_paren opt_nls statement
+             LEX_ELSE opt_nls statement
+        ;
 
 nls
-       : NEWLINE
-       | nls NEWLINE
-       ;
+        : NEWLINE
+        | nls NEWLINE
+        ;
 
 opt_nls
-       : /* empty */
-       | nls
-       ;
+        : /* empty */
+        | nls
+        ;
 
 input_redir
-       : /* empty */
-       | '<' simp_exp
-       ;
+        : /* empty */
+        | '<' simp_exp
+        ;
 
 output_redir
-       : /* empty */
-       | '>' exp
-       | APPEND_OP exp
-       | '|' exp
-       | TWOWAYIO exp
-       ;
+        : /* empty */
+        | '>' exp
+        | APPEND_OP exp
+        | '|' exp
+        | TWOWAYIO exp
+        ;
 
 opt_param_list
-       : /* empty */
-       | param_list
-       ;
+        : /* empty */
+        | param_list
+        ;
 
 param_list
-       : NAME
-       | param_list comma NAME
-       | error
-       | param_list error
-       | param_list comma error
-       ;
+        : NAME
+        | param_list comma NAME
+        | error
+        | param_list error
+        | param_list comma error
+        ;
 
 /* optional expression, as in for loop */
 opt_exp
-       : /* empty */
-       | exp
-       ;
+        : /* empty */
+        | exp
+        ;
 
 opt_rexpression_list
-       : /* empty */
-       | rexpression_list
-       ;
+        : /* empty */
+        | rexpression_list
+        ;
 
 rexpression_list
-       : rexp
-       | rexpression_list comma rexp
-       | error
-       | rexpression_list error
-       | rexpression_list error rexp
-       | rexpression_list comma error
-       ;
+        : rexp
+        | rexpression_list comma rexp
+        | error
+        | rexpression_list error
+        | rexpression_list error rexp
+        | rexpression_list comma error
+        ;
 
 opt_expression_list
-       : /* empty */
-       | expression_list
-       ;
+        : /* empty */
+        | expression_list
+        ;
 
 expression_list
-       : exp
-       | expression_list comma exp
-       | error
-       | expression_list error
-       | expression_list error exp
-       | expression_list comma error
-       ;
+        : exp
+        | expression_list comma exp
+        | error
+        | expression_list error
+        | expression_list error exp
+        | expression_list comma error
+        ;
 
 /* Expressions, not including the comma operator.  */
-exp    : variable ASSIGNOP {} exp
-       | '(' expression_list r_paren LEX_IN NAME
-       | exp '|' LEX_GETLINE opt_variable
-       | exp TWOWAYIO LEX_GETLINE opt_variable
-       | LEX_GETLINE opt_variable input_redir
-       | exp LEX_AND exp
-       | exp LEX_OR exp
-       | exp MATCHOP exp
-       | regexp
-       | '!' regexp %prec UNARY
-       | exp LEX_IN NAME
-       | exp RELOP exp
-       | exp '<' exp
-       | exp '>' exp
-       | exp '?' exp ':' exp
-       | simp_exp
-       | exp simp_exp %prec CONCAT_OP
-       ;
+exp     : variable ASSIGNOP {} exp
+        | '(' expression_list r_paren LEX_IN NAME
+        | exp '|' LEX_GETLINE opt_variable
+        | exp TWOWAYIO LEX_GETLINE opt_variable
+        | LEX_GETLINE opt_variable input_redir
+        | exp LEX_AND exp
+        | exp LEX_OR exp
+        | exp MATCHOP exp
+        | regexp
+        | '!' regexp %prec UNARY
+        | exp LEX_IN NAME
+        | exp RELOP exp
+        | exp '<' exp
+        | exp '>' exp
+        | exp '?' exp ':' exp
+        | simp_exp
+        | exp simp_exp %prec CONCAT_OP
+        ;
 
 rexp
-       : variable ASSIGNOP {} rexp
-       | rexp LEX_AND rexp
-       | rexp LEX_OR rexp
-       | LEX_GETLINE opt_variable input_redir
-       | regexp
-       | '!' regexp %prec UNARY
-       | rexp MATCHOP rexp
-       | rexp LEX_IN NAME
-       | rexp RELOP rexp
-       | rexp '?' rexp ':' rexp
-       | simp_exp
-       | rexp simp_exp %prec CONCAT_OP
-       ;
+        : variable ASSIGNOP {} rexp
+        | rexp LEX_AND rexp
+        | rexp LEX_OR rexp
+        | LEX_GETLINE opt_variable input_redir
+        | regexp
+        | '!' regexp %prec UNARY
+        | rexp MATCHOP rexp
+        | rexp LEX_IN NAME
+        | rexp RELOP rexp
+        | rexp '?' rexp ':' rexp
+        | simp_exp
+        | rexp simp_exp %prec CONCAT_OP
+        ;
 
 simp_exp
-       : non_post_simp_exp
-       /* Binary operators in order of decreasing precedence.  */
-       | simp_exp '^' simp_exp
-       | simp_exp '*' simp_exp
-       | simp_exp '/' simp_exp
-       | simp_exp '%' simp_exp
-       | simp_exp '+' simp_exp
-       | simp_exp '-' simp_exp
-       | variable INCREMENT
-       | variable DECREMENT
-       ;
+        : non_post_simp_exp
+        /* Binary operators in order of decreasing precedence.  */
+        | simp_exp '^' simp_exp
+        | simp_exp '*' simp_exp
+        | simp_exp '/' simp_exp
+        | simp_exp '%' simp_exp
+        | simp_exp '+' simp_exp
+        | simp_exp '-' simp_exp
+        | variable INCREMENT
+        | variable DECREMENT
+        ;
 
 non_post_simp_exp
-       : '!' simp_exp %prec UNARY
-       | '(' exp r_paren
-       | LEX_BUILTIN
-         '(' opt_expression_list r_paren
-       | LEX_LENGTH '(' opt_expression_list r_paren
-       | LEX_LENGTH
-       | FUNC_CALL '(' opt_expression_list r_paren
-       | variable
-       | INCREMENT variable
-       | DECREMENT variable
-       | YNUMBER
-       | YSTRING
-       | '-' simp_exp    %prec UNARY
-       | '+' simp_exp    %prec UNARY
-       ;
+        : '!' simp_exp %prec UNARY
+        | '(' exp r_paren
+        | LEX_BUILTIN
+          '(' opt_expression_list r_paren
+        | LEX_LENGTH '(' opt_expression_list r_paren
+        | LEX_LENGTH
+        | FUNC_CALL '(' opt_expression_list r_paren
+        | variable
+        | INCREMENT variable
+        | DECREMENT variable
+        | YNUMBER
+        | YSTRING
+        | '-' simp_exp    %prec UNARY
+        | '+' simp_exp    %prec UNARY
+        ;
 
 opt_variable
-       : /* empty */
-       | variable
-       ;
+        : /* empty */
+        | variable
+        ;
 
 variable
-       : NAME
-       | NAME '[' expression_list ']'
-       | '$' non_post_simp_exp
-       ;
+        : NAME
+        | NAME '[' expression_list ']'
+        | '$' non_post_simp_exp
+        ;
 
 l_brace
-       : '{' opt_nls
-       ;
+        : '{' opt_nls
+        ;
 
 r_brace
-       : '}' opt_nls
-       ;
+        : '}' opt_nls
+        ;
 
 r_paren
-       : ')'
-       ;
+        : ')'
+        ;
 
 opt_semi
-       : /* empty */
-       | semi
-       ;
+        : /* empty */
+        | semi
+        ;
 
 semi
-       : ';'
-       ;
+        : ';'
+        ;
 
-comma  : ',' opt_nls
-       ;
+comma   : ',' opt_nls
+        ;
 ]],
 
 dnl INPUT
@@ -403,32 +403,88 @@ dnl parses it as:
 dnl
 dnl   getline $!(4*0);
 dnl
-dnl That is, they shift `*' immediately and make it part of the getline
+dnl That is, they shift '*' immediately and make it part of the getline
 dnl argument.
 dnl
 dnl The grammar below using LALR(1) parses it as a syntax error.  So does
 dnl GNU AWK 3.0.6, 3.1.0, and 3.1.1.  They reduce the full getline expression
-dnl before shifting `*' even though `*' is not a valid lookahead.
+dnl before shifting '*' even though '*' is not a valid lookahead.
 dnl
 dnl GNU AWK 3.1.2, 3.1.3, 3.1.4, and 3.1.5 parse it as:
 dnl
 dnl   (getline $!4)*0;
 dnl
 dnl That is, like the other versions of GNU AWK, they reduce the full getline
-dnl expression before shifting `*'.  However, because of a different LHS on the
-dnl getline rule, `*' actually is a valid lookahead.  Solaris /usr/xpg4/bin/awk
+dnl expression before shifting '*'.  However, because of a different LHS on the
+dnl getline rule, '*' actually is a valid lookahead.  Solaris /usr/xpg4/bin/awk
 dnl and the Open Group awk specification seem to agree:
 dnl
 dnl   http://www.opengroup.org/pubs/online/7908799/xcu/awk.html
 dnl
 dnl /bin/nawk and /bin/awk on Solaris 10 report it as a syntax error, but they
-dnl don't like even `print $!4;'.
+dnl don't like even 'print $!4;'.
 [[LEX_GETLINE, '$', '!', YNUMBER, '*', YNUMBER, ';']],
 
 dnl BISON-STDERR
 [AT_COND_CASE([[canonical LR]],
-[[input.y: conflicts: 265 shift/reduce]],
-[[input.y: conflicts: 65 shift/reduce]])[
+[[input.y:66.10: warning: empty rule without %empty [-Wempty-rule]
+input.y:169.8: warning: empty rule without %empty [-Wempty-rule]
+input.y:174.12: warning: empty rule without %empty [-Wempty-rule]
+input.y:179.13: warning: empty rule without %empty [-Wempty-rule]
+input.y:187.15: warning: empty rule without %empty [-Wempty-rule]
+input.y:201.8: warning: empty rule without %empty [-Wempty-rule]
+input.y:206.21: warning: empty rule without %empty [-Wempty-rule]
+input.y:220.20: warning: empty rule without %empty [-Wempty-rule]
+input.y:299.13: warning: empty rule without %empty [-Wempty-rule]
+input.y:322.9: warning: empty rule without %empty [-Wempty-rule]
+input.y: warning: 265 shift/reduce conflicts [-Wconflicts-sr]
+input.y:19.8-16: warning: useless associativity for FUNC_CALL, use %precedence [-Wprecedence]
+input.y:21.8-14: warning: useless associativity for YNUMBER, use %precedence [-Wprecedence]
+input.y:21.16-22: warning: useless associativity for YSTRING, use %precedence [-Wprecedence]
+input.y:22.14-22: warning: useless precedence and associativity for APPEND_OP [-Wprecedence]
+input.y:23.8-15: warning: useless associativity for ASSIGNOP, use %precedence [-Wprecedence]
+input.y:23.33-41: warning: useless associativity for CONCAT_OP, use %precedence [-Wprecedence]
+input.y:27.8-18: warning: useless precedence and associativity for LEX_GETLINE [-Wprecedence]
+input.y:28.8-13: warning: useless associativity for LEX_IN, use %precedence [-Wprecedence]
+input.y:29.23-31: warning: useless associativity for INCREMENT, use %precedence [-Wprecedence]
+input.y:29.33-41: warning: useless associativity for DECREMENT, use %precedence [-Wprecedence]
+input.y:30.8-18: warning: useless associativity for LEX_BUILTIN, use %precedence [-Wprecedence]
+input.y:30.20-29: warning: useless associativity for LEX_LENGTH, use %precedence [-Wprecedence]
+input.y:40.11-13: warning: useless precedence and associativity for ',' [-Wprecedence]
+input.y:47.8-10: warning: useless associativity for '!', use %precedence [-Wprecedence]
+input.y:47.12-16: warning: useless associativity for UNARY, use %precedence [-Wprecedence]
+input.y:50.7-9: warning: useless associativity for '$', use %precedence [-Wprecedence]
+input.y:51.7-9: warning: useless associativity for '(', use %precedence [-Wprecedence]
+input.y:51.11-13: warning: useless precedence and associativity for ')' [-Wprecedence]]],
+[[input.y:66.10: warning: empty rule without %empty [-Wempty-rule]
+input.y:169.8: warning: empty rule without %empty [-Wempty-rule]
+input.y:174.12: warning: empty rule without %empty [-Wempty-rule]
+input.y:179.13: warning: empty rule without %empty [-Wempty-rule]
+input.y:187.15: warning: empty rule without %empty [-Wempty-rule]
+input.y:201.8: warning: empty rule without %empty [-Wempty-rule]
+input.y:206.21: warning: empty rule without %empty [-Wempty-rule]
+input.y:220.20: warning: empty rule without %empty [-Wempty-rule]
+input.y:299.13: warning: empty rule without %empty [-Wempty-rule]
+input.y:322.9: warning: empty rule without %empty [-Wempty-rule]
+input.y: warning: 65 shift/reduce conflicts [-Wconflicts-sr]
+input.y:19.8-16: warning: useless associativity for FUNC_CALL, use %precedence [-Wprecedence]
+input.y:21.8-14: warning: useless associativity for YNUMBER, use %precedence [-Wprecedence]
+input.y:21.16-22: warning: useless associativity for YSTRING, use %precedence [-Wprecedence]
+input.y:22.14-22: warning: useless precedence and associativity for APPEND_OP [-Wprecedence]
+input.y:23.8-15: warning: useless associativity for ASSIGNOP, use %precedence [-Wprecedence]
+input.y:23.33-41: warning: useless associativity for CONCAT_OP, use %precedence [-Wprecedence]
+input.y:27.8-18: warning: useless precedence and associativity for LEX_GETLINE [-Wprecedence]
+input.y:28.8-13: warning: useless associativity for LEX_IN, use %precedence [-Wprecedence]
+input.y:29.23-31: warning: useless associativity for INCREMENT, use %precedence [-Wprecedence]
+input.y:29.33-41: warning: useless associativity for DECREMENT, use %precedence [-Wprecedence]
+input.y:30.8-18: warning: useless associativity for LEX_BUILTIN, use %precedence [-Wprecedence]
+input.y:30.20-29: warning: useless associativity for LEX_LENGTH, use %precedence [-Wprecedence]
+input.y:40.11-13: warning: useless precedence and associativity for ',' [-Wprecedence]
+input.y:47.8-10: warning: useless associativity for '!', use %precedence [-Wprecedence]
+input.y:47.12-16: warning: useless associativity for UNARY, use %precedence [-Wprecedence]
+input.y:50.7-9: warning: useless associativity for '$', use %precedence [-Wprecedence]
+input.y:51.7-9: warning: useless associativity for '(', use %precedence [-Wprecedence]
+input.y:51.11-13: warning: useless precedence and associativity for ')' [-Wprecedence]]])[
 ]],
 
 dnl LAST-STATE
@@ -783,33 +839,33 @@ dnl In the case of the syntax error, the parser recovers, so it returns 0.
 AT_TEST_EXISTING_GRAMMAR([[GNU Cim Grammar]],
 [[
 %token
-       HACTIVATE HAFTER /*HAND*/ HARRAY HAT
-       HBEFORE HBEGIN HBOOLEAN
-       HCHARACTER HCLASS /*HCOMMENT*/ HCONC
-       HDELAY HDO
-       HELSE HEND HEQ /*HEQV*/ HEXTERNAL
-       HFOR
-       HGE HGO HGOTO HGT
-       HHIDDEN
-       HIF /*HIMP*/ HIN HINNER HINSPECT HINTEGER HIS
-       HLABEL HLE HLONG HLT
-       HNAME HNE HNEW HNONE /*HNOT*/ HNOTEXT
-       /*HOR*/ HOTHERWISE
-       HPRIOR HPROCEDURE HPROTECTED
-       HQUA
-       HREACTIVATE HREAL HREF
-       HSHORT HSTEP HSWITCH
-       HTEXT HTHEN HTHIS HTO
-       HUNTIL
-       HVALUE HVAR HVIRTUAL
-       HWHEN HWHILE
-
-       HASSIGNVALUE HASSIGNREF
-       /*HDOT*/ HPAREXPSEPARATOR HLABELSEPARATOR HSTATEMENTSEPARATOR
-       HBEGPAR HENDPAR
-       HEQR HNER
-       HADD HSUB HMUL HDIV HINTDIV HEXP
-       HDOTDOTDOT
+        HACTIVATE HAFTER /*HAND*/ HARRAY HAT
+        HBEFORE HBEGIN HBOOLEAN
+        HCHARACTER HCLASS /*HCOMMENT*/ HCONC
+        HDELAY HDO
+        HELSE HEND HEQ /*HEQV*/ HEXTERNAL
+        HFOR
+        HGE HGO HGOTO HGT
+        HHIDDEN
+        HIF /*HIMP*/ HIN HINNER HINSPECT HINTEGER HIS
+        HLABEL HLE HLONG HLT
+        HNAME HNE HNEW HNONE /*HNOT*/ HNOTEXT
+        /*HOR*/ HOTHERWISE
+        HPRIOR HPROCEDURE HPROTECTED
+        HQUA
+        HREACTIVATE HREAL HREF
+        HSHORT HSTEP HSWITCH
+        HTEXT HTHEN HTHIS HTO
+        HUNTIL
+        HVALUE HVAR HVIRTUAL
+        HWHEN HWHILE
+
+        HASSIGNVALUE HASSIGNREF
+        /*HDOT*/ HPAREXPSEPARATOR HLABELSEPARATOR HSTATEMENTSEPARATOR
+        HBEGPAR HENDPAR
+        HEQR HNER
+        HADD HSUB HMUL HDIV HINTDIV HEXP
+        HDOTDOTDOT
 
 %token HIDENTIFIER
 %token HBOOLEANKONST HINTEGERKONST HCHARACTERKONST
@@ -829,7 +885,7 @@ AT_TEST_EXISTING_GRAMMAR([[GNU Cim Grammar]],
 
 %left HVALRELOPERATOR HREFRELOPERATOR HOBJRELOPERATOR
 
-%left  HCONC
+%left   HCONC
 
 %left HTERMOPERATOR
 %left UNEAR
@@ -845,522 +901,522 @@ AT_TEST_EXISTING_GRAMMAR([[GNU Cim Grammar]],
 [[
 /* GRAMATIKK FOR PROGRAM MODULES */
 MAIN_MODULE     :       {}
-                       MODULS
-               |       error HSTATEMENTSEPARATOR MBEE_DECLSTMS
-               ;
-EXT_DECLARATION        :       HEXTERNAL
-                       MBEE_TYPE
-                       HPROCEDURE
-                               {}
-                       EXT_LIST
-               |
-                       HEXTERNAL
-                       HIDENTIFIER
-                       HPROCEDURE
-                               {}
-                       HIDENTIFIER {}
-                       EXTERNAL_KIND_ITEM
-               |       HEXTERNAL
-                       HCLASS
-                               {}
-                       EXT_LIST
-
-               ;
-EXTERNAL_KIND_ITEM:    EXT_IDENT
-                       HOBJRELOPERATOR
-                               {}
-                       MBEE_TYPE HPROCEDURE
-                       HIDENTIFIER
-                               {}
-                       HEADING EMPTY_BLOCK
-                               {}
-/*             |
-                       EXT_IDENT
-                               {}
-                       MBEE_REST_EXT_LIST
-               ;
-MBEE_REST_EXT_LIST:    /* EMPTY
-               |       HPAREXPSEPARATOR EXT_KIND_LIST
-               ;
-EXT_KIND_LIST  :       EXT_KIND_ITEM
-               |       EXT_KIND_LIST HPAREXPSEPARATOR EXT_KIND_ITEM
-               ;
-EXT_KIND_ITEM  :       HIDENTIFIER
-                       EXT_IDENT
-                               {}*/
-               ;
-EMPTY_BLOCK    :       /*EMPT*/
-               |       HBEGIN HEND
-               ;
-EXT_LIST       :       EXT_ITEM
-               |       EXT_LIST HPAREXPSEPARATOR EXT_ITEM
-               ;
-EXT_ITEM       :       HIDENTIFIER
-                       EXT_IDENT
-               ;
-EXT_IDENT      :       /* EMPTY */
-               |       HVALRELOPERATOR {}
-                       HTEXTKONST
-               ;
+                        MODULS
+                |       error HSTATEMENTSEPARATOR MBEE_DECLSTMS
+                ;
+EXT_DECLARATION :       HEXTERNAL
+                        MBEE_TYPE
+                        HPROCEDURE
+                                {}
+                        EXT_LIST
+                |
+                        HEXTERNAL
+                        HIDENTIFIER
+                        HPROCEDURE
+                                {}
+                        HIDENTIFIER {}
+                        EXTERNAL_KIND_ITEM
+                |       HEXTERNAL
+                        HCLASS
+                                {}
+                        EXT_LIST
+
+                ;
+EXTERNAL_KIND_ITEM:     EXT_IDENT
+                        HOBJRELOPERATOR
+                                {}
+                        MBEE_TYPE HPROCEDURE
+                        HIDENTIFIER
+                                {}
+                        HEADING EMPTY_BLOCK
+                                {}
+/*              |
+                        EXT_IDENT
+                                {}
+                        MBEE_REST_EXT_LIST
+                ;
+MBEE_REST_EXT_LIST:     /* EMPTY
+                |       HPAREXPSEPARATOR EXT_KIND_LIST
+                ;
+EXT_KIND_LIST   :       EXT_KIND_ITEM
+                |       EXT_KIND_LIST HPAREXPSEPARATOR EXT_KIND_ITEM
+                ;
+EXT_KIND_ITEM   :       HIDENTIFIER
+                        EXT_IDENT
+                                {}*/
+                ;
+EMPTY_BLOCK     :       /*EMPT*/
+                |       HBEGIN HEND
+                ;
+EXT_LIST        :       EXT_ITEM
+                |       EXT_LIST HPAREXPSEPARATOR EXT_ITEM
+                ;
+EXT_ITEM        :       HIDENTIFIER
+                        EXT_IDENT
+                ;
+EXT_IDENT       :       /* EMPTY */
+                |       HVALRELOPERATOR {}
+                        HTEXTKONST
+                ;
 /* GRAMATIKK FOR TYPER */
 NO_TYPE         :       /*EMPT*/
-               ;
+                ;
 MBEE_TYPE       :       NO_TYPE
-               |       TYPE
-               ;
+                |       TYPE
+                ;
 TYPE            :       HREF HBEGPAR
-                       HIDENTIFIER
-                               {}
-                       HENDPAR
-               |       HTEXT
-               |       HBOOLEAN
-               |       HCHARACTER
-               |       HSHORT HINTEGER
-               |       HINTEGER
-               |       HREAL
-               |       HLONG HREAL
-               ;
+                        HIDENTIFIER
+                                {}
+                        HENDPAR
+                |       HTEXT
+                |       HBOOLEAN
+                |       HCHARACTER
+                |       HSHORT HINTEGER
+                |       HINTEGER
+                |       HREAL
+                |       HLONG HREAL
+                ;
 
 /* GRAMATIKK FOR DEL AV SETNINGER */
 MBEE_ELSE_PART  :       /*EMPT*/
-/*             |       HELSE
-                       HIF
-                       EXPRESSION
-                       HTHEN   {}
-                       BLOCK   {}
-                       MBEE_ELSE_PART          {}*/
-               |       HELSE   {}
-                       BLOCK
-               ;
+/*              |       HELSE
+                        HIF
+                        EXPRESSION
+                        HTHEN   {}
+                        BLOCK   {}
+                        MBEE_ELSE_PART          {}*/
+                |       HELSE   {}
+                        BLOCK
+                ;
 FOR_LIST        :       FOR_LIST_ELEMENT
-               |       FOR_LIST_ELEMENT
-                       HPAREXPSEPARATOR
-                       FOR_LIST
-               ;
+                |       FOR_LIST_ELEMENT
+                        HPAREXPSEPARATOR
+                        FOR_LIST
+                ;
 FOR_LIST_ELEMENT:       EXPRESSION
-                       MBEE_F_L_EL_R_PT
-               ;
+                        MBEE_F_L_EL_R_PT
+                ;
 MBEE_F_L_EL_R_PT:       /*EMPT*/
-               |       HWHILE
-                       EXPRESSION
-               |       HSTEP
-                       EXPRESSION
-                       HUNTIL
-                       EXPRESSION
-               ;
+                |       HWHILE
+                        EXPRESSION
+                |       HSTEP
+                        EXPRESSION
+                        HUNTIL
+                        EXPRESSION
+                ;
 GOTO            :       HGO
-                       HTO
-               |       HGOTO
-               ;
+                        HTO
+                |       HGOTO
+                ;
 CONN_STATE_R_PT :       WHEN_CLAUSE_LIST
-               |       HDO   {}
-                       BLOCK
-               ;
+                |       HDO   {}
+                        BLOCK
+                ;
 WHEN_CLAUSE_LIST:       HWHEN
-                       HIDENTIFIER
-                       HDO    {}
-                       BLOCK
-               |       WHEN_CLAUSE_LIST
-                       HWHEN
-                       HIDENTIFIER
-                       HDO    {}
-                       BLOCK
-               ;
+                        HIDENTIFIER
+                        HDO    {}
+                        BLOCK
+                |       WHEN_CLAUSE_LIST
+                        HWHEN
+                        HIDENTIFIER
+                        HDO    {}
+                        BLOCK
+                ;
 MBEE_OTWI_CLAUS :       /*EMPT*/
-               |       HOTHERWISE {}
-
-                       BLOCK
-               ;
-ACTIVATOR      :       HACTIVATE
-               |       HREACTIVATE
-               ;
-SCHEDULE       :       /*EMPT*/
-               |       ATDELAY EXPRESSION      {}
-                       PRIOR
-               |       BEFOREAFTER             {}
-                       EXPRESSION
-               ;
-ATDELAY                :       HAT
-               |       HDELAY
-               ;
-BEFOREAFTER    :       HBEFORE
-               |       HAFTER
-               ;
-PRIOR          :       /*EMPT*/
-               |       HPRIOR
-               ;
+                |       HOTHERWISE {}
+
+                        BLOCK
+                ;
+ACTIVATOR       :       HACTIVATE
+                |       HREACTIVATE
+                ;
+SCHEDULE        :       /*EMPT*/
+                |       ATDELAY EXPRESSION      {}
+                        PRIOR
+                |       BEFOREAFTER             {}
+                        EXPRESSION
+                ;
+ATDELAY         :       HAT
+                |       HDELAY
+                ;
+BEFOREAFTER     :       HBEFORE
+                |       HAFTER
+                ;
+PRIOR           :       /*EMPT*/
+                |       HPRIOR
+                ;
 /* GRAMATIKK FOR SETNINGER OG DEKLARASJONER */
 MODULSTATEMENT  :       HWHILE
-                       EXPRESSION
-                       HDO     {}
-                       BLOCK
-               |       HIF
-                       EXPRESSION
-                       HTHEN   {}
-                       BLOCK   {}
-                       MBEE_ELSE_PART
-               |       HFOR
-                       HIDENTIFIER
-                       HASSIGN {}
-                       FOR_LIST
-                       HDO     {}
-                       BLOCK
-               |       GOTO
-                       EXPRESSION
-               |       HINSPECT
-                       EXPRESSION              {}
-                       CONN_STATE_R_PT
-                               {}
-                       MBEE_OTWI_CLAUS
-               |       HINNER
-               |       HIDENTIFIER
-                       HLABELSEPARATOR
-                               {}
-                       DECLSTATEMENT
-               |       EXPRESSION_SIMP
-                       HBEGIN
-                               {}
-                       IMPORT_SPEC_MODULE
-                               {}
-                       MBEE_DECLSTMS
-                       HEND
-               |       EXPRESSION_SIMP HBEGIN error HSTATEMENTSEPARATOR
-                       MBEE_DECLSTMS HEND
-               |       EXPRESSION_SIMP HBEGIN error HEND
-               |       EXPRESSION_SIMP
-               |       ACTIVATOR EXPRESSION SCHEDULE
-               |       HBEGIN
-                               {}
-                       MBEE_DECLSTMS
-                       HEND
-               |       MBEE_TYPE HPROCEDURE
-                       HIDENTIFIER
-                               {}
-                       HEADING BLOCK
-               |       HIDENTIFIER
-                       HCLASS
-                       NO_TYPE
-                               {}
-                       IMPORT_SPEC_MODULE
-                       HIDENTIFIER
-                               {}
-                       HEADING
-                       BLOCK
-               |       HCLASS
-                       NO_TYPE
-                       HIDENTIFIER
-                               {}
-                       HEADING
-                       BLOCK
-               |       EXT_DECLARATION
-               |       /*EMPT*/
-               ;
+                        EXPRESSION
+                        HDO     {}
+                        BLOCK
+                |       HIF
+                        EXPRESSION
+                        HTHEN   {}
+                        BLOCK   {}
+                        MBEE_ELSE_PART
+                |       HFOR
+                        HIDENTIFIER
+                        HASSIGN {}
+                        FOR_LIST
+                        HDO     {}
+                        BLOCK
+                |       GOTO
+                        EXPRESSION
+                |       HINSPECT
+                        EXPRESSION              {}
+                        CONN_STATE_R_PT
+                                {}
+                        MBEE_OTWI_CLAUS
+                |       HINNER
+                |       HIDENTIFIER
+                        HLABELSEPARATOR
+                                {}
+                        DECLSTATEMENT
+                |       EXPRESSION_SIMP
+                        HBEGIN
+                                {}
+                        IMPORT_SPEC_MODULE
+                                {}
+                        MBEE_DECLSTMS
+                        HEND
+                |       EXPRESSION_SIMP HBEGIN error HSTATEMENTSEPARATOR
+                        MBEE_DECLSTMS HEND
+                |       EXPRESSION_SIMP HBEGIN error HEND
+                |       EXPRESSION_SIMP
+                |       ACTIVATOR EXPRESSION SCHEDULE
+                |       HBEGIN
+                                {}
+                        MBEE_DECLSTMS
+                        HEND
+                |       MBEE_TYPE HPROCEDURE
+                        HIDENTIFIER
+                                {}
+                        HEADING BLOCK
+                |       HIDENTIFIER
+                        HCLASS
+                        NO_TYPE
+                                {}
+                        IMPORT_SPEC_MODULE
+                        HIDENTIFIER
+                                {}
+                        HEADING
+                        BLOCK
+                |       HCLASS
+                        NO_TYPE
+                        HIDENTIFIER
+                                {}
+                        HEADING
+                        BLOCK
+                |       EXT_DECLARATION
+                |       /*EMPT*/
+                ;
 IMPORT_SPEC_MODULE:
-               ;
-DECLSTATEMENT  :       MODULSTATEMENT
-               |       TYPE
-                       HIDENTIFIER
-                       MBEE_CONSTANT
-                       HPAREXPSEPARATOR
-                               {}
-                       IDENTIFIER_LISTC
-               |       TYPE
-                       HIDENTIFIER
-                       MBEE_CONSTANT
-               |       MBEE_TYPE
-                       HARRAY  {}
-                       ARR_SEGMENT_LIST
-               |       HSWITCH
-                       HIDENTIFIER
-                       HASSIGN {}
-                       SWITCH_LIST
-               ;
+                ;
+DECLSTATEMENT   :       MODULSTATEMENT
+                |       TYPE
+                        HIDENTIFIER
+                        MBEE_CONSTANT
+                        HPAREXPSEPARATOR
+                                {}
+                        IDENTIFIER_LISTC
+                |       TYPE
+                        HIDENTIFIER
+                        MBEE_CONSTANT
+                |       MBEE_TYPE
+                        HARRAY  {}
+                        ARR_SEGMENT_LIST
+                |       HSWITCH
+                        HIDENTIFIER
+                        HASSIGN {}
+                        SWITCH_LIST
+                ;
 BLOCK           :       DECLSTATEMENT
-               |       HBEGIN MBEE_DECLSTMS HEND
-               |       HBEGIN error HSTATEMENTSEPARATOR MBEE_DECLSTMS HEND
-               |       HBEGIN error HEND
-               ;
+                |       HBEGIN MBEE_DECLSTMS HEND
+                |       HBEGIN error HSTATEMENTSEPARATOR MBEE_DECLSTMS HEND
+                |       HBEGIN error HEND
+                ;
 MBEE_DECLSTMS   :       MBEE_DECLSTMSU
-               ;
+                ;
 MBEE_DECLSTMSU  :       DECLSTATEMENT
-               |       MBEE_DECLSTMSU
-                       HSTATEMENTSEPARATOR
-                       DECLSTATEMENT
-               ;
-MODULS         :       MODULSTATEMENT
-               |       MODULS HSTATEMENTSEPARATOR MODULSTATEMENT
-               ;
+                |       MBEE_DECLSTMSU
+                        HSTATEMENTSEPARATOR
+                        DECLSTATEMENT
+                ;
+MODULS          :       MODULSTATEMENT
+                |       MODULS HSTATEMENTSEPARATOR MODULSTATEMENT
+                ;
 /* GRAMATIKK FOR DEL AV DEKLARASJONER */
 ARR_SEGMENT_LIST:       ARR_SEGMENT
-               |       ARR_SEGMENT_LIST
-                       HPAREXPSEPARATOR
-                       ARR_SEGMENT
-               ;
-ARR_SEGMENT    :       ARRAY_SEGMENT
-                       HBEGPAR
-                       BAUND_PAIR_LIST HENDPAR
-               ;
+                |       ARR_SEGMENT_LIST
+                        HPAREXPSEPARATOR
+                        ARR_SEGMENT
+                ;
+ARR_SEGMENT     :       ARRAY_SEGMENT
+                        HBEGPAR
+                        BAUND_PAIR_LIST HENDPAR
+                ;
 ARRAY_SEGMENT   :       ARRAY_SEGMENT_EL        {}
 
-               |       ARRAY_SEGMENT_EL
-                       HPAREXPSEPARATOR
-                       ARRAY_SEGMENT
-               ;
+                |       ARRAY_SEGMENT_EL
+                        HPAREXPSEPARATOR
+                        ARRAY_SEGMENT
+                ;
 ARRAY_SEGMENT_EL:       HIDENTIFIER
-               ;
+                ;
 BAUND_PAIR_LIST :       BAUND_PAIR
-               |       BAUND_PAIR
-                       HPAREXPSEPARATOR
-                       BAUND_PAIR_LIST
-               ;
+                |       BAUND_PAIR
+                        HPAREXPSEPARATOR
+                        BAUND_PAIR_LIST
+                ;
 BAUND_PAIR      :       EXPRESSION
-                       HLABELSEPARATOR
-                       EXPRESSION
-               ;
+                        HLABELSEPARATOR
+                        EXPRESSION
+                ;
 SWITCH_LIST     :       EXPRESSION
-               |       EXPRESSION
-                       HPAREXPSEPARATOR
-                       SWITCH_LIST
-               ;
+                |       EXPRESSION
+                        HPAREXPSEPARATOR
+                        SWITCH_LIST
+                ;
 HEADING         :       MBEE_FMAL_PAR_P HSTATEMENTSEPARATOR {}
-                       MBEE_MODE_PART  {}
-                       MBEE_SPEC_PART  {}
-                       MBEE_PROT_PART  {}
-                       MBEE_VIRT_PART
-               ;
+                        MBEE_MODE_PART  {}
+                        MBEE_SPEC_PART  {}
+                        MBEE_PROT_PART  {}
+                        MBEE_VIRT_PART
+                ;
 MBEE_FMAL_PAR_P :       /*EMPT*/
-               |       FMAL_PAR_PART
-               ;
+                |       FMAL_PAR_PART
+                ;
 FMAL_PAR_PART   :       HBEGPAR NO_TYPE
-                       MBEE_LISTV HENDPAR
-               ;
+                        MBEE_LISTV HENDPAR
+                ;
 MBEE_LISTV      :       /*EMPT*/
-               |       LISTV
-               ;
+                |       LISTV
+                ;
 LISTV           :       HIDENTIFIER
-               |       FPP_CATEG HDOTDOTDOT
-               |       HIDENTIFIER     {}
-                       HPAREXPSEPARATOR LISTV
-               |       FPP_SPEC
-               |       FPP_SPEC
-                       HPAREXPSEPARATOR LISTV
-               ;
+                |       FPP_CATEG HDOTDOTDOT
+                |       HIDENTIFIER     {}
+                        HPAREXPSEPARATOR LISTV
+                |       FPP_SPEC
+                |       FPP_SPEC
+                        HPAREXPSEPARATOR LISTV
+                ;
 FPP_HEADING     :       HBEGPAR NO_TYPE
-                       FPP_MBEE_LISTV HENDPAR
-               ;
+                        FPP_MBEE_LISTV HENDPAR
+                ;
 FPP_MBEE_LISTV  :       /*EMPT*/
-               |       FPP_LISTV
-               ;
-FPP_LISTV       :      FPP_CATEG HDOTDOTDOT
-               |       FPP_SPEC
-               |       FPP_SPEC
-                       HPAREXPSEPARATOR LISTV
-               ;
+                |       FPP_LISTV
+                ;
+FPP_LISTV       :       FPP_CATEG HDOTDOTDOT
+                |       FPP_SPEC
+                |       FPP_SPEC
+                        HPAREXPSEPARATOR LISTV
+                ;
 FPP_SPEC        :       FPP_CATEG SPECIFIER HIDENTIFIER
-               |       FPP_CATEG FPP_PROC_DECL_IN_SPEC
-               ;
+                |       FPP_CATEG FPP_PROC_DECL_IN_SPEC
+                ;
 FPP_CATEG       :       HNAME HLABELSEPARATOR
-               |       HVALUE HLABELSEPARATOR
-               |       HVAR HLABELSEPARATOR
-               |       /*EMPT*/
-               ;
-FPP_PROC_DECL_IN_SPEC: MBEE_TYPE HPROCEDURE
-                       HIDENTIFIER
-                                       {}
-                       FPP_HEADING {} { /* Yes, two "final" actions. */ }
-               ;
+                |       HVALUE HLABELSEPARATOR
+                |       HVAR HLABELSEPARATOR
+                |       /*EMPT*/
+                ;
+FPP_PROC_DECL_IN_SPEC:  MBEE_TYPE HPROCEDURE
+                        HIDENTIFIER
+                                        {}
+                        FPP_HEADING {} { /* Yes, two "final" actions. */ }
+                ;
 IDENTIFIER_LISTV:       HIDENTIFIER
-               |       HDOTDOTDOT
-               |       HIDENTIFIER     {}
-                       HPAREXPSEPARATOR IDENTIFIER_LISTV
-               ;
+                |       HDOTDOTDOT
+                |       HIDENTIFIER     {}
+                        HPAREXPSEPARATOR IDENTIFIER_LISTV
+                ;
 MBEE_MODE_PART  :       /*EMPT*/
-               |       MODE_PART
-               ;
+                |       MODE_PART
+                ;
 MODE_PART       :       NAME_PART
-               |       VALUE_PART
-               |       VAR_PART
-               |       NAME_PART VALUE_PART
-               |       VALUE_PART NAME_PART
-               |       NAME_PART VAR_PART
-               |       VAR_PART NAME_PART
-               |       VALUE_PART VAR_PART
-               |       VAR_PART VALUE_PART
-               |       VAR_PART NAME_PART VALUE_PART
-               |       NAME_PART VAR_PART VALUE_PART
-               |       NAME_PART VALUE_PART VAR_PART
-               |       VAR_PART VALUE_PART NAME_PART
-               |       VALUE_PART VAR_PART NAME_PART
-               |       VALUE_PART NAME_PART VAR_PART
-               ;
+                |       VALUE_PART
+                |       VAR_PART
+                |       NAME_PART VALUE_PART
+                |       VALUE_PART NAME_PART
+                |       NAME_PART VAR_PART
+                |       VAR_PART NAME_PART
+                |       VALUE_PART VAR_PART
+                |       VAR_PART VALUE_PART
+                |       VAR_PART NAME_PART VALUE_PART
+                |       NAME_PART VAR_PART VALUE_PART
+                |       NAME_PART VALUE_PART VAR_PART
+                |       VAR_PART VALUE_PART NAME_PART
+                |       VALUE_PART VAR_PART NAME_PART
+                |       VALUE_PART NAME_PART VAR_PART
+                ;
 NAME_PART       :       HNAME           {}
-                       IDENTIFIER_LISTV
-                       HSTATEMENTSEPARATOR
-               ;
+                        IDENTIFIER_LISTV
+                        HSTATEMENTSEPARATOR
+                ;
 VAR_PART        :       HVAR            {}
-                       IDENTIFIER_LISTV
-                       HSTATEMENTSEPARATOR
-               ;
+                        IDENTIFIER_LISTV
+                        HSTATEMENTSEPARATOR
+                ;
 VALUE_PART      :       HVALUE          {}
-                       IDENTIFIER_LISTV HSTATEMENTSEPARATOR
-               ;
+                        IDENTIFIER_LISTV HSTATEMENTSEPARATOR
+                ;
 MBEE_SPEC_PART  :       /*EMPT*/
-               |       SPEC_PART
-               ;
+                |       SPEC_PART
+                ;
 SPEC_PART       :       ONE_SPEC
-               |       SPEC_PART ONE_SPEC
-               ;
-ONE_SPEC       :       SPECIFIER IDENTIFIER_LIST HSTATEMENTSEPARATOR
-               |       NO_TYPE HPROCEDURE HIDENTIFIER HOBJRELOPERATOR
-                         {}
-                       PROC_DECL_IN_SPEC HSTATEMENTSEPARATOR
-               |       FPP_PROC_DECL_IN_SPEC HSTATEMENTSEPARATOR
-               |       MBEE_TYPE HPROCEDURE HIDENTIFIER HSTATEMENTSEPARATOR
-               |       MBEE_TYPE HPROCEDURE HIDENTIFIER HPAREXPSEPARATOR
-                       IDENTIFIER_LIST HSTATEMENTSEPARATOR
-               ;
+                |       SPEC_PART ONE_SPEC
+                ;
+ONE_SPEC        :       SPECIFIER IDENTIFIER_LIST HSTATEMENTSEPARATOR
+                |       NO_TYPE HPROCEDURE HIDENTIFIER HOBJRELOPERATOR
+                          {}
+                        PROC_DECL_IN_SPEC HSTATEMENTSEPARATOR
+                |       FPP_PROC_DECL_IN_SPEC HSTATEMENTSEPARATOR
+                |       MBEE_TYPE HPROCEDURE HIDENTIFIER HSTATEMENTSEPARATOR
+                |       MBEE_TYPE HPROCEDURE HIDENTIFIER HPAREXPSEPARATOR
+                        IDENTIFIER_LIST HSTATEMENTSEPARATOR
+                ;
 SPECIFIER       :       TYPE
-               |       MBEE_TYPE
-                       HARRAY
-               |       HLABEL
-               |       HSWITCH
-               ;
-PROC_DECL_IN_SPEC:     MBEE_TYPE HPROCEDURE
-                       HIDENTIFIER
-                                       {}
-                       HEADING
-                                       {}
-                       MBEE_BEGIN_END
-               ;
-MBEE_BEGIN_END :       /* EMPTY */
-               |       HBEGIN HEND
-               ;
+                |       MBEE_TYPE
+                        HARRAY
+                |       HLABEL
+                |       HSWITCH
+                ;
+PROC_DECL_IN_SPEC:      MBEE_TYPE HPROCEDURE
+                        HIDENTIFIER
+                                        {}
+                        HEADING
+                                        {}
+                        MBEE_BEGIN_END
+                ;
+MBEE_BEGIN_END  :       /* EMPTY */
+                |       HBEGIN HEND
+                ;
 MBEE_PROT_PART  :       /*EMPT*/
-               |       PROTECTION_PART
-               ;
+                |       PROTECTION_PART
+                ;
 PROTECTION_PART :       PROT_SPECIFIER IDENTIFIER_LIST
-                       HSTATEMENTSEPARATOR
-               |       PROTECTION_PART  PROT_SPECIFIER
-                       IDENTIFIER_LIST HSTATEMENTSEPARATOR
-               ;
+                        HSTATEMENTSEPARATOR
+                |       PROTECTION_PART  PROT_SPECIFIER
+                        IDENTIFIER_LIST HSTATEMENTSEPARATOR
+                ;
 PROT_SPECIFIER  :       HHIDDEN
-               |       HPROTECTED
-               |       HHIDDEN
-                       HPROTECTED
-               |       HPROTECTED
-                       HHIDDEN
-               ;
+                |       HPROTECTED
+                |       HHIDDEN
+                        HPROTECTED
+                |       HPROTECTED
+                        HHIDDEN
+                ;
 MBEE_VIRT_PART  :       /*EMPT*/
-               |       VIRTUAL_PART
-               ;
+                |       VIRTUAL_PART
+                ;
 VIRTUAL_PART    :       HVIRTUAL
-                       HLABELSEPARATOR
-                       MBEE_SPEC_PART
-               ;
+                        HLABELSEPARATOR
+                        MBEE_SPEC_PART
+                ;
 IDENTIFIER_LIST :       HIDENTIFIER
-               |       IDENTIFIER_LIST HPAREXPSEPARATOR
-                       HIDENTIFIER
-               ;
+                |       IDENTIFIER_LIST HPAREXPSEPARATOR
+                        HIDENTIFIER
+                ;
 IDENTIFIER_LISTC:       HIDENTIFIER
-                       MBEE_CONSTANT
-               |       IDENTIFIER_LISTC HPAREXPSEPARATOR
-                       HIDENTIFIER
-                       MBEE_CONSTANT
-               ;
-MBEE_CONSTANT  :       /* EMPTY */
-               |       HVALRELOPERATOR
-                               {}
-                       EXPRESSION
-               ;
+                        MBEE_CONSTANT
+                |       IDENTIFIER_LISTC HPAREXPSEPARATOR
+                        HIDENTIFIER
+                        MBEE_CONSTANT
+                ;
+MBEE_CONSTANT   :       /* EMPTY */
+                |       HVALRELOPERATOR
+                                {}
+                        EXPRESSION
+                ;
 
 /* GRAMATIKK FOR UTTRYKK */
 EXPRESSION      :       EXPRESSION_SIMP
-               |       HIF
-                       EXPRESSION
-                       HTHEN
-                       EXPRESSION
-                       HELSE
-                       EXPRESSION
-               ;
-EXPRESSION_SIMP :      EXPRESSION_SIMP
-                       HASSIGN
-                       EXPRESSION
-               |
-
-                       EXPRESSION_SIMP
-                       HCONC
-                       EXPRESSION_SIMP
-               |       EXPRESSION_SIMP HOR
-                       HELSE
-                       EXPRESSION_SIMP
-                       %prec HORELSE
-               |       EXPRESSION_SIMP HAND
-                       HTHEN
-                       EXPRESSION_SIMP
-                       %prec HANDTHEN
-               |       EXPRESSION_SIMP
-                       HEQV EXPRESSION_SIMP
-               |       EXPRESSION_SIMP
-                       HIMP EXPRESSION_SIMP
-               |       EXPRESSION_SIMP
-                       HOR EXPRESSION_SIMP
-               |       EXPRESSION_SIMP
-                       HAND EXPRESSION_SIMP
-               |       HNOT EXPRESSION_SIMP
-               |       EXPRESSION_SIMP
-                       HVALRELOPERATOR
-                       EXPRESSION_SIMP
-               |       EXPRESSION_SIMP
-                       HREFRELOPERATOR
-                       EXPRESSION_SIMP
-               |       EXPRESSION_SIMP
-                       HOBJRELOPERATOR
-                       EXPRESSION_SIMP
-               |       HTERMOPERATOR
-                       EXPRESSION_SIMP %prec UNEAR
-               |       EXPRESSION_SIMP
-                       HTERMOPERATOR
-                       EXPRESSION_SIMP
-               |       EXPRESSION_SIMP
-                       HFACTOROPERATOR
-                       EXPRESSION_SIMP
-               |       EXPRESSION_SIMP
-                       HPRIMARYOPERATOR
-                       EXPRESSION_SIMP
-               |       HBEGPAR
-                       EXPRESSION HENDPAR
-               |       HTEXTKONST
-               |       HCHARACTERKONST
-               |       HREALKONST
-               |       HINTEGERKONST
-               |       HBOOLEANKONST
-               |       HNONE
-               |       HIDENTIFIER
-                               {}
-                       MBEE_ARG_R_PT
-               |       HTHIS HIDENTIFIER
-               |       HNEW
-                       HIDENTIFIER
-                       ARG_R_PT
-               |       EXPRESSION_SIMP
-                       HDOT
-                       EXPRESSION_SIMP
-               |       EXPRESSION_SIMP
-                       HQUA HIDENTIFIER
-               ;
+                |       HIF
+                        EXPRESSION
+                        HTHEN
+                        EXPRESSION
+                        HELSE
+                        EXPRESSION
+                ;
+EXPRESSION_SIMP :       EXPRESSION_SIMP
+                        HASSIGN
+                        EXPRESSION
+                |
+
+                        EXPRESSION_SIMP
+                        HCONC
+                        EXPRESSION_SIMP
+                |       EXPRESSION_SIMP HOR
+                        HELSE
+                        EXPRESSION_SIMP
+                        %prec HORELSE
+                |       EXPRESSION_SIMP HAND
+                        HTHEN
+                        EXPRESSION_SIMP
+                        %prec HANDTHEN
+                |       EXPRESSION_SIMP
+                        HEQV EXPRESSION_SIMP
+                |       EXPRESSION_SIMP
+                        HIMP EXPRESSION_SIMP
+                |       EXPRESSION_SIMP
+                        HOR EXPRESSION_SIMP
+                |       EXPRESSION_SIMP
+                        HAND EXPRESSION_SIMP
+                |       HNOT EXPRESSION_SIMP
+                |       EXPRESSION_SIMP
+                        HVALRELOPERATOR
+                        EXPRESSION_SIMP
+                |       EXPRESSION_SIMP
+                        HREFRELOPERATOR
+                        EXPRESSION_SIMP
+                |       EXPRESSION_SIMP
+                        HOBJRELOPERATOR
+                        EXPRESSION_SIMP
+                |       HTERMOPERATOR
+                        EXPRESSION_SIMP %prec UNEAR
+                |       EXPRESSION_SIMP
+                        HTERMOPERATOR
+                        EXPRESSION_SIMP
+                |       EXPRESSION_SIMP
+                        HFACTOROPERATOR
+                        EXPRESSION_SIMP
+                |       EXPRESSION_SIMP
+                        HPRIMARYOPERATOR
+                        EXPRESSION_SIMP
+                |       HBEGPAR
+                        EXPRESSION HENDPAR
+                |       HTEXTKONST
+                |       HCHARACTERKONST
+                |       HREALKONST
+                |       HINTEGERKONST
+                |       HBOOLEANKONST
+                |       HNONE
+                |       HIDENTIFIER
+                                {}
+                        MBEE_ARG_R_PT
+                |       HTHIS HIDENTIFIER
+                |       HNEW
+                        HIDENTIFIER
+                        ARG_R_PT
+                |       EXPRESSION_SIMP
+                        HDOT
+                        EXPRESSION_SIMP
+                |       EXPRESSION_SIMP
+                        HQUA HIDENTIFIER
+                ;
 ARG_R_PT        :       /*EMPTY*/
-               |       HBEGPAR
-                       ARGUMENT_LIST HENDPAR
-               ;
+                |       HBEGPAR
+                        ARGUMENT_LIST HENDPAR
+                ;
 MBEE_ARG_R_PT   :       /*EMPTY*/
-               |       HBEGPAR
-                       ARGUMENT_LIST HENDPAR
-               ;
+                |       HBEGPAR
+                        ARGUMENT_LIST HENDPAR
+                ;
 ARGUMENT_LIST   :       EXPRESSION
-               |       EXPRESSION
-                       HPAREXPSEPARATOR
-                       ARGUMENT_LIST
-               ;
+                |       EXPRESSION
+                        HPAREXPSEPARATOR
+                        ARGUMENT_LIST
+                ;
 ]],
 
 dnl INPUT
@@ -1368,8 +1424,66 @@ dnl INPUT
 
 dnl BISON-STDERR
 [AT_COND_CASE([[canonical LR]],
-[[input.y: conflicts: 1876 shift/reduce, 144 reduce/reduce]],
-[[input.y: conflicts: 78 shift/reduce, 10 reduce/reduce]])[
+[[input.y:128.12: warning: empty rule without %empty [-Wempty-rule]
+input.y:137.10: warning: empty rule without %empty [-Wempty-rule]
+input.y:142.8: warning: empty rule without %empty [-Wempty-rule]
+input.y:161.15: warning: empty rule without %empty [-Wempty-rule]
+input.y:179.17: warning: empty rule without %empty [-Wempty-rule]
+input.y:205.16: warning: empty rule without %empty [-Wempty-rule]
+input.y:213.9: warning: empty rule without %empty [-Wempty-rule]
+input.y:225.6: warning: empty rule without %empty [-Wempty-rule]
+input.y:292.18: warning: empty rule without %empty [-Wempty-rule]
+input.y:294.19: warning: empty rule without %empty [-Wempty-rule]
+input.y:367.16: warning: empty rule without %empty [-Wempty-rule]
+input.y:373.11: warning: empty rule without %empty [-Wempty-rule]
+input.y:387.15: warning: empty rule without %empty [-Wempty-rule]
+input.y:401.18: warning: empty rule without %empty [-Wempty-rule]
+input.y:413.15: warning: empty rule without %empty [-Wempty-rule]
+input.y:443.15: warning: empty rule without %empty [-Wempty-rule]
+input.y:471.15: warning: empty rule without %empty [-Wempty-rule]
+input.y:474.15: warning: empty rule without %empty [-Wempty-rule]
+input.y:489.15: warning: empty rule without %empty [-Wempty-rule]
+input.y:506.14: warning: empty rule without %empty [-Wempty-rule]
+input.y:587.9: warning: empty rule without %empty [-Wempty-rule]
+input.y:591.14: warning: empty rule without %empty [-Wempty-rule]
+input.y: warning: 1876 shift/reduce conflicts [-Wconflicts-sr]
+input.y: warning: 144 reduce/reduce conflicts [-Wconflicts-rr]
+input.y:32.9-12: warning: useless associativity for HQUA, use %precedence [-Wprecedence]
+input.y:53.8-14: warning: useless associativity for HASSIGN, use %precedence [-Wprecedence]
+input.y:54.9-15: warning: useless associativity for HORELSE, use %precedence [-Wprecedence]
+input.y:55.9-16: warning: useless associativity for HANDTHEN, use %precedence [-Wprecedence]
+input.y:61.9-12: warning: useless associativity for HNOT, use %precedence [-Wprecedence]
+input.y:68.7-11: warning: useless associativity for UNEAR, use %precedence [-Wprecedence]]],
+[[input.y:128.12: warning: empty rule without %empty [-Wempty-rule]
+input.y:137.10: warning: empty rule without %empty [-Wempty-rule]
+input.y:142.8: warning: empty rule without %empty [-Wempty-rule]
+input.y:161.15: warning: empty rule without %empty [-Wempty-rule]
+input.y:179.17: warning: empty rule without %empty [-Wempty-rule]
+input.y:205.16: warning: empty rule without %empty [-Wempty-rule]
+input.y:213.9: warning: empty rule without %empty [-Wempty-rule]
+input.y:225.6: warning: empty rule without %empty [-Wempty-rule]
+input.y:292.18: warning: empty rule without %empty [-Wempty-rule]
+input.y:294.19: warning: empty rule without %empty [-Wempty-rule]
+input.y:367.16: warning: empty rule without %empty [-Wempty-rule]
+input.y:373.11: warning: empty rule without %empty [-Wempty-rule]
+input.y:387.15: warning: empty rule without %empty [-Wempty-rule]
+input.y:401.18: warning: empty rule without %empty [-Wempty-rule]
+input.y:413.15: warning: empty rule without %empty [-Wempty-rule]
+input.y:443.15: warning: empty rule without %empty [-Wempty-rule]
+input.y:471.15: warning: empty rule without %empty [-Wempty-rule]
+input.y:474.15: warning: empty rule without %empty [-Wempty-rule]
+input.y:489.15: warning: empty rule without %empty [-Wempty-rule]
+input.y:506.14: warning: empty rule without %empty [-Wempty-rule]
+input.y:587.9: warning: empty rule without %empty [-Wempty-rule]
+input.y:591.14: warning: empty rule without %empty [-Wempty-rule]
+input.y: warning: 78 shift/reduce conflicts [-Wconflicts-sr]
+input.y: warning: 10 reduce/reduce conflicts [-Wconflicts-rr]
+input.y:32.9-12: warning: useless associativity for HQUA, use %precedence [-Wprecedence]
+input.y:53.8-14: warning: useless associativity for HASSIGN, use %precedence [-Wprecedence]
+input.y:54.9-15: warning: useless associativity for HORELSE, use %precedence [-Wprecedence]
+input.y:55.9-16: warning: useless associativity for HANDTHEN, use %precedence [-Wprecedence]
+input.y:61.9-12: warning: useless associativity for HNOT, use %precedence [-Wprecedence]
+input.y:68.7-11: warning: useless associativity for UNEAR, use %precedence [-Wprecedence]]])[
 ]],
 
 dnl LAST-STATE
@@ -1535,7 +1649,7 @@ box "foo" above ljust == box ("foo" above ljust)
 
 %left LEFT RIGHT
 /* Give attributes that take an optional expression a higher
-precedence than left and right, so that eg `line chop left'
+precedence than left and right, so that eg 'line chop left'
 parses properly. */
 %left CHOP SOLID DASHED DOTTED UP DOWN FILL COLORED OUTLINED
 %left LABEL
@@ -1548,7 +1662,7 @@ parses properly. */
 /* these need to be lower than '-' */
 %left HEIGHT RADIUS WIDTH DIAMETER FROM TO AT THICKNESS
 
-/* these must have higher precedence than CHOP so that `label %prec CHOP'
+/* these must have higher precedence than CHOP so that 'label %prec CHOP'
 works */
 %left DOT_N DOT_E DOT_W DOT_S DOT_NE DOT_SE DOT_NW DOT_SW DOT_C
 %left DOT_START DOT_END TOP BOTTOM LEFT_CORNER RIGHT_CORNER
@@ -1570,367 +1684,367 @@ works */
 ]],
 [[
 top:
-       optional_separator
-       | element_list
-       ;
+        optional_separator
+        | element_list
+        ;
 
 element_list:
-       optional_separator middle_element_list optional_separator
-       ;
+        optional_separator middle_element_list optional_separator
+        ;
 
 middle_element_list:
-       element
-       | middle_element_list separator element
-       ;
+        element
+        | middle_element_list separator element
+        ;
 
 optional_separator:
-       /* empty */
-       | separator
-       ;
+        /* empty */
+        | separator
+        ;
 
 separator:
-       ';'
-       | separator ';'
-       ;
+        ';'
+        | separator ';'
+        ;
 
 placeless_element:
-       VARIABLE '=' any_expr
-       | VARIABLE ':' '=' any_expr
-       | UP
-       | DOWN
-       | LEFT
-       | RIGHT
-       | COMMAND_LINE
-       | COMMAND print_args
-       | PRINT print_args
-       | SH
-               {}
-         DELIMITED
-       | COPY TEXT
-       | COPY TEXT THROUGH
-               {}
-         DELIMITED
-               {}
-         until
-       | COPY THROUGH
-               {}
-         DELIMITED
-               {}
-         until
-       | FOR VARIABLE '=' expr TO expr optional_by DO
-               {}
-         DELIMITED
-       | simple_if
-       | simple_if ELSE
-               {}
-         DELIMITED
-       | reset_variables
-       | RESET
-       ;
+        VARIABLE '=' any_expr
+        | VARIABLE ':' '=' any_expr
+        | UP
+        | DOWN
+        | LEFT
+        | RIGHT
+        | COMMAND_LINE
+        | COMMAND print_args
+        | PRINT print_args
+        | SH
+                {}
+          DELIMITED
+        | COPY TEXT
+        | COPY TEXT THROUGH
+                {}
+          DELIMITED
+                {}
+          until
+        | COPY THROUGH
+                {}
+          DELIMITED
+                {}
+          until
+        | FOR VARIABLE '=' expr TO expr optional_by DO
+                {}
+          DELIMITED
+        | simple_if
+        | simple_if ELSE
+                {}
+          DELIMITED
+        | reset_variables
+        | RESET
+        ;
 
 reset_variables:
-       RESET VARIABLE
-       | reset_variables VARIABLE
-       | reset_variables ',' VARIABLE
-       ;
+        RESET VARIABLE
+        | reset_variables VARIABLE
+        | reset_variables ',' VARIABLE
+        ;
 
 print_args:
-       print_arg
-       | print_args print_arg
-       ;
+        print_arg
+        | print_args print_arg
+        ;
 
 print_arg:
-       expr                                                    %prec ','
-       | text
-       | position                                              %prec ','
-       ;
+        expr                                                    %prec ','
+        | text
+        | position                                              %prec ','
+        ;
 
 simple_if:
-       IF any_expr THEN
-               {}
-       DELIMITED
-       ;
+        IF any_expr THEN
+                {}
+        DELIMITED
+        ;
 
 until:
-       /* empty */
-       | UNTIL TEXT
-       ;
+        /* empty */
+        | UNTIL TEXT
+        ;
 
 any_expr:
-       expr
-       | text_expr
-       ;
+        expr
+        | text_expr
+        ;
 
 text_expr:
-       text EQUALEQUAL text
-       | text NOTEQUAL text
-       | text_expr ANDAND text_expr
-       | text_expr ANDAND expr
-       | expr ANDAND text_expr
-       | text_expr OROR text_expr
-       | text_expr OROR expr
-       | expr OROR text_expr
-       | '!' text_expr
-       ;
+        text EQUALEQUAL text
+        | text NOTEQUAL text
+        | text_expr ANDAND text_expr
+        | text_expr ANDAND expr
+        | expr ANDAND text_expr
+        | text_expr OROR text_expr
+        | text_expr OROR expr
+        | expr OROR text_expr
+        | '!' text_expr
+        ;
 
 optional_by:
-       /* empty */
-       | BY expr
-       | BY '*' expr
-       ;
+        /* empty */
+        | BY expr
+        | BY '*' expr
+        ;
 
 element:
-       object_spec
-       | LABEL ':' optional_separator element
-       | LABEL ':' optional_separator position_not_place
-       | LABEL ':' optional_separator place
-       | '{' {} element_list '}'
-               {}
-         optional_element
-       | placeless_element
-       ;
+        object_spec
+        | LABEL ':' optional_separator element
+        | LABEL ':' optional_separator position_not_place
+        | LABEL ':' optional_separator place
+        | '{' {} element_list '}'
+                {}
+          optional_element
+        | placeless_element
+        ;
 
 optional_element:
-       /* empty */
-       | element
-       ;
+        /* empty */
+        | element
+        ;
 
 object_spec:
-       BOX
-       | CIRCLE
-       | ELLIPSE
-       | ARC
-       | LINE
-       | ARROW
-       | MOVE
-       | SPLINE
-       | text                                                  %prec TEXT
-       | PLOT expr
-       | PLOT expr text
-       | '['
-               {}
-         element_list ']'
-       | object_spec HEIGHT expr
-       | object_spec RADIUS expr
-       | object_spec WIDTH expr
-       | object_spec DIAMETER expr
-       | object_spec expr                                      %prec HEIGHT
-       | object_spec UP
-       | object_spec UP expr
-       | object_spec DOWN
-       | object_spec DOWN expr
-       | object_spec RIGHT
-       | object_spec RIGHT expr
-       | object_spec LEFT
-       | object_spec LEFT expr
-       | object_spec FROM position
-       | object_spec TO position
-       | object_spec AT position
-       | object_spec WITH path
-       | object_spec WITH position                             %prec ','
-       | object_spec BY expr_pair
-       | object_spec THEN
-       | object_spec SOLID
-       | object_spec DOTTED
-       | object_spec DOTTED expr
-       | object_spec DASHED
-       | object_spec DASHED expr
-       | object_spec FILL
-       | object_spec FILL expr
-       | object_spec SHADED text
-       | object_spec COLORED text
-       | object_spec OUTLINED text
-       | object_spec CHOP
-       | object_spec CHOP expr
-       | object_spec SAME
-       | object_spec INVISIBLE
-       | object_spec LEFT_ARROW_HEAD
-       | object_spec RIGHT_ARROW_HEAD
-       | object_spec DOUBLE_ARROW_HEAD
-       | object_spec CW
-       | object_spec CCW
-       | object_spec text                                      %prec TEXT
-       | object_spec LJUST
-       | object_spec RJUST
-       | object_spec ABOVE
-       | object_spec BELOW
-       | object_spec THICKNESS expr
-       | object_spec ALIGNED
-       ;
+        BOX
+        | CIRCLE
+        | ELLIPSE
+        | ARC
+        | LINE
+        | ARROW
+        | MOVE
+        | SPLINE
+        | text                                                  %prec TEXT
+        | PLOT expr
+        | PLOT expr text
+        | '['
+                {}
+          element_list ']'
+        | object_spec HEIGHT expr
+        | object_spec RADIUS expr
+        | object_spec WIDTH expr
+        | object_spec DIAMETER expr
+        | object_spec expr                                      %prec HEIGHT
+        | object_spec UP
+        | object_spec UP expr
+        | object_spec DOWN
+        | object_spec DOWN expr
+        | object_spec RIGHT
+        | object_spec RIGHT expr
+        | object_spec LEFT
+        | object_spec LEFT expr
+        | object_spec FROM position
+        | object_spec TO position
+        | object_spec AT position
+        | object_spec WITH path
+        | object_spec WITH position                             %prec ','
+        | object_spec BY expr_pair
+        | object_spec THEN
+        | object_spec SOLID
+        | object_spec DOTTED
+        | object_spec DOTTED expr
+        | object_spec DASHED
+        | object_spec DASHED expr
+        | object_spec FILL
+        | object_spec FILL expr
+        | object_spec SHADED text
+        | object_spec COLORED text
+        | object_spec OUTLINED text
+        | object_spec CHOP
+        | object_spec CHOP expr
+        | object_spec SAME
+        | object_spec INVISIBLE
+        | object_spec LEFT_ARROW_HEAD
+        | object_spec RIGHT_ARROW_HEAD
+        | object_spec DOUBLE_ARROW_HEAD
+        | object_spec CW
+        | object_spec CCW
+        | object_spec text                                      %prec TEXT
+        | object_spec LJUST
+        | object_spec RJUST
+        | object_spec ABOVE
+        | object_spec BELOW
+        | object_spec THICKNESS expr
+        | object_spec ALIGNED
+        ;
 
 text:
-       TEXT
-       | SPRINTF '(' TEXT sprintf_args ')'
-       ;
+        TEXT
+        | SPRINTF '(' TEXT sprintf_args ')'
+        ;
 
 sprintf_args:
-       /* empty */
-       | sprintf_args ',' expr
-       ;
+        /* empty */
+        | sprintf_args ',' expr
+        ;
 
 position:
-       position_not_place
-       | place
-       ;
+        position_not_place
+        | place
+        ;
 
 position_not_place:
-       expr_pair
-       | position '+' expr_pair
-       | position '-' expr_pair
-       | '(' position ',' position ')'
-       | expr between position AND position
-       | expr '<' position ',' position '>'
-       ;
+        expr_pair
+        | position '+' expr_pair
+        | position '-' expr_pair
+        | '(' position ',' position ')'
+        | expr between position AND position
+        | expr '<' position ',' position '>'
+        ;
 
 between:
-       BETWEEN
-       | OF THE WAY BETWEEN
-       ;
+        BETWEEN
+        | OF THE WAY BETWEEN
+        ;
 
 expr_pair:
-       expr ',' expr
-       | '(' expr_pair ')'
-       ;
+        expr ',' expr
+        | '(' expr_pair ')'
+        ;
 
 place:
-       /* line at A left == line (at A) left */
-       label                                                   %prec CHOP
-       | label corner
-       | corner label
-       | corner OF label
-       | HERE
-       ;
+        /* line at A left == line (at A) left */
+        label                                                   %prec CHOP
+        | label corner
+        | corner label
+        | corner OF label
+        | HERE
+        ;
 
 label:
-       LABEL
-       | nth_primitive
-       | label '.' LABEL
-       ;
+        LABEL
+        | nth_primitive
+        | label '.' LABEL
+        ;
 
 ordinal:
-       ORDINAL
-       | '`' any_expr TH
-       ;
+        ORDINAL
+        | '`' any_expr TH
+        ;
 
 optional_ordinal_last:
-       LAST
-       | ordinal LAST
-       ;
+        LAST
+        | ordinal LAST
+        ;
 
 nth_primitive:
-       ordinal object_type
-       | optional_ordinal_last object_type
-       ;
+        ordinal object_type
+        | optional_ordinal_last object_type
+        ;
 
 object_type:
-       BOX
-       | CIRCLE
-       | ELLIPSE
-       | ARC
-       | LINE
-       | ARROW
-       | SPLINE
-       | '[' ']'
-       | TEXT
-       ;
+        BOX
+        | CIRCLE
+        | ELLIPSE
+        | ARC
+        | LINE
+        | ARROW
+        | SPLINE
+        | '[' ']'
+        | TEXT
+        ;
 
 label_path:
-       '.' LABEL
-       | label_path '.' LABEL
-       ;
+        '.' LABEL
+        | label_path '.' LABEL
+        ;
 
 relative_path:
-       corner                                                  %prec CHOP
-       /* give this a lower precedence than LEFT and RIGHT so that
-          [A: box] with .A left == [A: box] with (.A left) */
-       | label_path                                            %prec TEXT
-       | label_path corner
-       ;
+        corner                                                  %prec CHOP
+        /* give this a lower precedence than LEFT and RIGHT so that
+           [A: box] with .A left == [A: box] with (.A left) */
+        | label_path                                            %prec TEXT
+        | label_path corner
+        ;
 
 path:
-       relative_path
-       | '(' relative_path ',' relative_path ')'
-               {}
-       /* The rest of these rules are a compatibility sop. */
-       | ORDINAL LAST object_type relative_path
-       | LAST object_type relative_path
-       | ORDINAL object_type relative_path
-       | LABEL relative_path
-       ;
+        relative_path
+        | '(' relative_path ',' relative_path ')'
+                {}
+        /* The rest of these rules are a compatibility sop. */
+        | ORDINAL LAST object_type relative_path
+        | LAST object_type relative_path
+        | ORDINAL object_type relative_path
+        | LABEL relative_path
+        ;
 
 corner:
-       DOT_N
-       | DOT_E
-       | DOT_W
-       | DOT_S
-       | DOT_NE
-       | DOT_SE
-       | DOT_NW
-       | DOT_SW
-       | DOT_C
-       | DOT_START
-       | DOT_END
-       | TOP
-       | BOTTOM
-       | LEFT
-       | RIGHT
-       | UPPER LEFT
-       | LOWER LEFT
-       | UPPER RIGHT
-       | LOWER RIGHT
-       | LEFT_CORNER
-       | RIGHT_CORNER
-       | UPPER LEFT_CORNER
-       | LOWER LEFT_CORNER
-       | UPPER RIGHT_CORNER
-       | LOWER RIGHT_CORNER
-       | NORTH
-       | SOUTH
-       | EAST
-       | WEST
-       | CENTER
-       | START
-       | END
-       ;
+        DOT_N
+        | DOT_E
+        | DOT_W
+        | DOT_S
+        | DOT_NE
+        | DOT_SE
+        | DOT_NW
+        | DOT_SW
+        | DOT_C
+        | DOT_START
+        | DOT_END
+        | TOP
+        | BOTTOM
+        | LEFT
+        | RIGHT
+        | UPPER LEFT
+        | LOWER LEFT
+        | UPPER RIGHT
+        | LOWER RIGHT
+        | LEFT_CORNER
+        | RIGHT_CORNER
+        | UPPER LEFT_CORNER
+        | LOWER LEFT_CORNER
+        | UPPER RIGHT_CORNER
+        | LOWER RIGHT_CORNER
+        | NORTH
+        | SOUTH
+        | EAST
+        | WEST
+        | CENTER
+        | START
+        | END
+        ;
 
 expr:
-       VARIABLE
-       | NUMBER
-       | place DOT_X
-       | place DOT_Y
-       | place DOT_HT
-       | place DOT_WID
-       | place DOT_RAD
-       | expr '+' expr
-       | expr '-' expr
-       | expr '*' expr
-       | expr '/' expr
-       | expr '%' expr
-       | expr '^' expr
-       | '-' expr                                              %prec '!'
-       | '(' any_expr ')'
-       | SIN '(' any_expr ')'
-       | COS '(' any_expr ')'
-       | ATAN2 '(' any_expr ',' any_expr ')'
-       | LOG '(' any_expr ')'
-       | EXP '(' any_expr ')'
-       | SQRT '(' any_expr ')'
-       | K_MAX '(' any_expr ',' any_expr ')'
-       | K_MIN '(' any_expr ',' any_expr ')'
-       | INT '(' any_expr ')'
-       | RAND '(' any_expr ')'
-       | RAND '(' ')'
-       | SRAND '(' any_expr ')'
-       | expr '<' expr
-       | expr LESSEQUAL expr
-       | expr '>' expr
-       | expr GREATEREQUAL expr
-       | expr EQUALEQUAL expr
-       | expr NOTEQUAL expr
-       | expr ANDAND expr
-       | expr OROR expr
-       | '!' expr
-       ;
+        VARIABLE
+        | NUMBER
+        | place DOT_X
+        | place DOT_Y
+        | place DOT_HT
+        | place DOT_WID
+        | place DOT_RAD
+        | expr '+' expr
+        | expr '-' expr
+        | expr '*' expr
+        | expr '/' expr
+        | expr '%' expr
+        | expr '^' expr
+        | '-' expr                                              %prec '!'
+        | '(' any_expr ')'
+        | SIN '(' any_expr ')'
+        | COS '(' any_expr ')'
+        | ATAN2 '(' any_expr ',' any_expr ')'
+        | LOG '(' any_expr ')'
+        | EXP '(' any_expr ')'
+        | SQRT '(' any_expr ')'
+        | K_MAX '(' any_expr ',' any_expr ')'
+        | K_MIN '(' any_expr ',' any_expr ')'
+        | INT '(' any_expr ')'
+        | RAND '(' any_expr ')'
+        | RAND '(' ')'
+        | SRAND '(' any_expr ')'
+        | expr '<' expr
+        | expr LESSEQUAL expr
+        | expr '>' expr
+        | expr GREATEREQUAL expr
+        | expr EQUALEQUAL expr
+        | expr NOTEQUAL expr
+        | expr ANDAND expr
+        | expr OROR expr
+        | '!' expr
+        ;
 ]],
 
 dnl INPUT
@@ -1951,7 +2065,93 @@ dnl without being followed by "of".)
 [[VARIABLE, '=', LABEL, LEFT, DOT_X]],
 
 dnl BISON-STDERR
-[[input.y:470.11-48: warning: rule useless in parser due to conflicts: path: ORDINAL LAST object_type relative_path
+[[input.y:202.19: warning: empty rule without %empty [-Wempty-rule]
+input.y:270.6: warning: empty rule without %empty [-Wempty-rule]
+input.y:292.12: warning: empty rule without %empty [-Wempty-rule]
+input.y:309.17: warning: empty rule without %empty [-Wempty-rule]
+input.y:382.13: warning: empty rule without %empty [-Wempty-rule]
+input.y:471.11-48: warning: rule useless in parser due to conflicts [-Wother]
+input.y:19.8-12: warning: useless associativity for LABEL, use %precedence [-Wprecedence]
+input.y:20.8-15: warning: useless associativity for VARIABLE, use %precedence [-Wprecedence]
+input.y:21.8-13: warning: useless associativity for NUMBER, use %precedence [-Wprecedence]
+input.y:22.8-11: warning: useless associativity for TEXT, use %precedence [-Wprecedence]
+input.y:25.8-14: warning: useless associativity for ORDINAL, use %precedence [-Wprecedence]
+input.y:30.8-11: warning: useless associativity for LAST, use %precedence [-Wprecedence]
+input.y:31.8-9: warning: useless associativity for UP, use %precedence [-Wprecedence]
+input.y:32.8-11: warning: useless associativity for DOWN, use %precedence [-Wprecedence]
+input.y:35.8-10: warning: useless associativity for BOX, use %precedence [-Wprecedence]
+input.y:36.8-13: warning: useless associativity for CIRCLE, use %precedence [-Wprecedence]
+input.y:37.8-14: warning: useless associativity for ELLIPSE, use %precedence [-Wprecedence]
+input.y:38.8-10: warning: useless associativity for ARC, use %precedence [-Wprecedence]
+input.y:39.8-11: warning: useless associativity for LINE, use %precedence [-Wprecedence]
+input.y:40.8-12: warning: useless associativity for ARROW, use %precedence [-Wprecedence]
+input.y:42.8-13: warning: useless associativity for SPLINE, use %precedence [-Wprecedence]
+input.y:43.8-13: warning: useless associativity for HEIGHT, use %precedence [-Wprecedence]
+input.y:44.8-13: warning: useless associativity for RADIUS, use %precedence [-Wprecedence]
+input.y:45.8-12: warning: useless associativity for WIDTH, use %precedence [-Wprecedence]
+input.y:46.8-15: warning: useless associativity for DIAMETER, use %precedence [-Wprecedence]
+input.y:47.8-11: warning: useless associativity for FROM, use %precedence [-Wprecedence]
+input.y:48.8-9: warning: useless associativity for TO, use %precedence [-Wprecedence]
+input.y:49.8-9: warning: useless associativity for AT, use %precedence [-Wprecedence]
+input.y:53.8-12: warning: useless precedence and associativity for SOLID [-Wprecedence]
+input.y:54.8-13: warning: useless associativity for DOTTED, use %precedence [-Wprecedence]
+input.y:55.8-13: warning: useless associativity for DASHED, use %precedence [-Wprecedence]
+input.y:56.8-11: warning: useless associativity for CHOP, use %precedence [-Wprecedence]
+input.y:59.8-12: warning: useless precedence and associativity for LJUST [-Wprecedence]
+input.y:60.8-12: warning: useless precedence and associativity for RJUST [-Wprecedence]
+input.y:61.8-12: warning: useless precedence and associativity for ABOVE [-Wprecedence]
+input.y:62.8-12: warning: useless precedence and associativity for BELOW [-Wprecedence]
+input.y:63.8-9: warning: useless associativity for OF, use %precedence [-Wprecedence]
+input.y:66.8-14: warning: useless associativity for BETWEEN, use %precedence [-Wprecedence]
+input.y:67.8-10: warning: useless associativity for AND, use %precedence [-Wprecedence]
+input.y:68.8-11: warning: useless associativity for HERE, use %precedence [-Wprecedence]
+input.y:69.8-12: warning: useless associativity for DOT_N, use %precedence [-Wprecedence]
+input.y:70.8-12: warning: useless associativity for DOT_E, use %precedence [-Wprecedence]
+input.y:71.8-12: warning: useless associativity for DOT_W, use %precedence [-Wprecedence]
+input.y:72.8-12: warning: useless associativity for DOT_S, use %precedence [-Wprecedence]
+input.y:73.8-13: warning: useless associativity for DOT_NE, use %precedence [-Wprecedence]
+input.y:74.8-13: warning: useless associativity for DOT_SE, use %precedence [-Wprecedence]
+input.y:75.8-13: warning: useless associativity for DOT_NW, use %precedence [-Wprecedence]
+input.y:76.8-13: warning: useless associativity for DOT_SW, use %precedence [-Wprecedence]
+input.y:77.8-12: warning: useless associativity for DOT_C, use %precedence [-Wprecedence]
+input.y:78.8-16: warning: useless associativity for DOT_START, use %precedence [-Wprecedence]
+input.y:79.8-14: warning: useless associativity for DOT_END, use %precedence [-Wprecedence]
+input.y:85.8-10: warning: useless associativity for SIN, use %precedence [-Wprecedence]
+input.y:86.8-10: warning: useless associativity for COS, use %precedence [-Wprecedence]
+input.y:87.8-12: warning: useless associativity for ATAN2, use %precedence [-Wprecedence]
+input.y:88.8-10: warning: useless associativity for LOG, use %precedence [-Wprecedence]
+input.y:89.8-10: warning: useless associativity for EXP, use %precedence [-Wprecedence]
+input.y:90.8-11: warning: useless associativity for SQRT, use %precedence [-Wprecedence]
+input.y:91.8-12: warning: useless associativity for K_MAX, use %precedence [-Wprecedence]
+input.y:92.8-12: warning: useless associativity for K_MIN, use %precedence [-Wprecedence]
+input.y:93.8-10: warning: useless associativity for INT, use %precedence [-Wprecedence]
+input.y:94.8-11: warning: useless associativity for RAND, use %precedence [-Wprecedence]
+input.y:95.8-12: warning: useless associativity for SRAND, use %precedence [-Wprecedence]
+input.y:98.8-10: warning: useless associativity for TOP, use %precedence [-Wprecedence]
+input.y:99.8-13: warning: useless associativity for BOTTOM, use %precedence [-Wprecedence]
+input.y:100.8-12: warning: useless associativity for UPPER, use %precedence [-Wprecedence]
+input.y:101.8-12: warning: useless associativity for LOWER, use %precedence [-Wprecedence]
+input.y:116.8-18: warning: useless associativity for LEFT_CORNER, use %precedence [-Wprecedence]
+input.y:117.8-19: warning: useless associativity for RIGHT_CORNER, use %precedence [-Wprecedence]
+input.y:118.8-12: warning: useless associativity for NORTH, use %precedence [-Wprecedence]
+input.y:119.8-12: warning: useless associativity for SOUTH, use %precedence [-Wprecedence]
+input.y:120.8-11: warning: useless associativity for EAST, use %precedence [-Wprecedence]
+input.y:121.8-11: warning: useless associativity for WEST, use %precedence [-Wprecedence]
+input.y:122.8-13: warning: useless associativity for CENTER, use %precedence [-Wprecedence]
+input.y:123.8-10: warning: useless associativity for END, use %precedence [-Wprecedence]
+input.y:124.8-12: warning: useless associativity for START, use %precedence [-Wprecedence]
+input.y:127.8-11: warning: useless associativity for PLOT, use %precedence [-Wprecedence]
+input.y:128.8-16: warning: useless associativity for THICKNESS, use %precedence [-Wprecedence]
+input.y:129.8-11: warning: useless associativity for FILL, use %precedence [-Wprecedence]
+input.y:130.8-14: warning: useless precedence and associativity for COLORED [-Wprecedence]
+input.y:131.8-15: warning: useless precedence and associativity for OUTLINED [-Wprecedence]
+input.y:134.8-14: warning: useless associativity for SPRINTF, use %precedence [-Wprecedence]
+input.y:137.7-9: warning: useless associativity for '.', use %precedence [-Wprecedence]
+input.y:156.23-25: warning: useless associativity for '(', use %precedence [-Wprecedence]
+input.y:157.20-22: warning: useless associativity for '`', use %precedence [-Wprecedence]
+input.y:159.48-50: warning: useless associativity for '@<:@', use %precedence [-Wprecedence]
+input.y:170.7-9: warning: useless associativity for ',', use %precedence [-Wprecedence]
+input.y:181.8-10: warning: useless associativity for '!', use %precedence [-Wprecedence]
 ]],
 
 dnl LAST-STATE
index 868c84109e62c73c2274feb7b2a04aa35fbb6615..711ab7ec597fc6d588ba0527f4ab85330a30c5c0 100644 (file)
@@ -88,8 +88,8 @@ yylex (void)
 AT_BISON_OPTION_POPDEFS
 
 AT_BISON_CHECK([[-o glr-regr1.c glr-regr1.y]], 0, [],
-[glr-regr1.y: conflicts: 1 shift/reduce
-])
+[[glr-regr1.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
+]])
 AT_COMPILE([glr-regr1])
 AT_PARSER_CHECK([[./glr-regr1 BPBPB]], 0,
 [[E -> 'B'
@@ -208,8 +208,8 @@ main (int argc, char **argv)
 AT_BISON_OPTION_POPDEFS
 
 AT_BISON_CHECK([[-o glr-regr2a.c glr-regr2a.y]], 0, [],
-[glr-regr2a.y: conflicts: 2 shift/reduce
-])
+[[glr-regr2a.y: warning: 2 shift/reduce conflicts [-Wconflicts-sr]
+]])
 AT_COMPILE([glr-regr2a])
 
 AT_DATA([input1.txt],
@@ -326,7 +326,7 @@ int yylex (void)
 }
 
 int
-main(int argc, char* argv[])
+main (int argc, char* argv[])
 {
   int res;
   input = stdin;
@@ -341,8 +341,9 @@ main(int argc, char* argv[])
 AT_BISON_OPTION_POPDEFS
 
 AT_BISON_CHECK([[-o glr-regr3.c glr-regr3.y]], 0, [],
-[glr-regr3.y: conflicts: 1 shift/reduce, 1 reduce/reduce
-])
+[[glr-regr3.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
+glr-regr3.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
+]])
 AT_COMPILE([glr-regr3])
 
 AT_DATA([input.txt],
@@ -436,8 +437,8 @@ merge (YYSTYPE s1, YYSTYPE s2)
 AT_BISON_OPTION_POPDEFS
 
 AT_BISON_CHECK([[-o glr-regr4.c glr-regr4.y]], 0, [],
-[glr-regr4.y: conflicts: 1 reduce/reduce
-])
+[[glr-regr4.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
+]])
 AT_COMPILE([glr-regr4])
 
 AT_PARSER_CHECK([[./glr-regr4]], 0,
@@ -487,20 +488,16 @@ start:
 %%
 ]AT_YYERROR_DEFINE[
 ]AT_YYLEX_DEFINE(["a"])[
-int
-main (void)
-{
-  return yyparse () != 1;
-}
+]AT_MAIN_DEFINE[
 ]])
 AT_BISON_OPTION_POPDEFS
 
 AT_BISON_CHECK([[-o glr-regr5.c glr-regr5.y]], 0, [],
-[glr-regr5.y: conflicts: 1 reduce/reduce
-])
+[[glr-regr5.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
+]])
 AT_COMPILE([glr-regr5])
 
-AT_PARSER_CHECK([[./glr-regr5]], 0, [],
+AT_PARSER_CHECK([[./glr-regr5]], 1, [],
 [syntax is ambiguous
 ])
 
@@ -539,20 +536,16 @@ start: 'a' | 'a' ;
 %%
 ]AT_YYERROR_DEFINE[
 ]AT_YYLEX_DEFINE(["a"])[
-int
-main (void)
-{
-  return yyparse () != 1;
-}
+]AT_MAIN_DEFINE[
 ]])
 AT_BISON_OPTION_POPDEFS
 
 AT_BISON_CHECK([[-o glr-regr6.c glr-regr6.y]], 0, [],
-[glr-regr6.y: conflicts: 1 reduce/reduce
-])
+[[glr-regr6.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
+]])
 AT_COMPILE([glr-regr6])
 
-AT_PARSER_CHECK([[./glr-regr6]], 0,
+AT_PARSER_CHECK([[./glr-regr6]], 1,
 [Destructor called.
 ],
 [syntax is ambiguous
@@ -637,8 +630,8 @@ main (void)
 AT_BISON_OPTION_POPDEFS
 
 AT_BISON_CHECK([[-o glr-regr7.c glr-regr7.y]], 0, [],
-[glr-regr7.y: conflicts: 2 reduce/reduce
-])
+[[glr-regr7.y: warning: 2 reduce/reduce conflicts [-Wconflicts-rr]
+]])
 AT_COMPILE([glr-regr7])
 
 AT_PARSER_CHECK([[./glr-regr7]], 2, [],
@@ -650,7 +643,7 @@ AT_CLEANUP
 
 ## ------------------------------------------------------------------------- ##
 ## Incorrect default location for empty right-hand sides.  Adapted from bug  ##
-## report by Claudia Hermann.                                               ##
+## report by Claudia Hermann.                                                ##
 ## See http://lists.gnu.org/archive/html/bug-bison/2005-10/msg00069.html and ##
 ## http://lists.gnu.org/archive/html/bug-bison/2005-10/msg00072.html         ##
 ## ------------------------------------------------------------------------- ##
@@ -676,25 +669,25 @@ AT_DATA_GRAMMAR([glr-regr8.y],
 %%
 
 
-PortClause     : T_PORT InterfaceDeclaration T_PORT
-               { printf("%d/%d - %d/%d - %d/%d\n",
-                        @1.first_column, @1.last_column,
-                        @2.first_column, @2.last_column,
-                        @3.first_column, @3.last_column); }
-       ;
+PortClause      : T_PORT InterfaceDeclaration T_PORT
+                { printf("%d/%d - %d/%d - %d/%d\n",
+                         @1.first_column, @1.last_column,
+                         @2.first_column, @2.last_column,
+                         @3.first_column, @3.last_column); }
+        ;
 
-InterfaceDeclaration   : OptConstantWord       %dprec 1
-       | OptSignalWord %dprec 2
-       ;
+InterfaceDeclaration    : OptConstantWord       %dprec 1
+        | OptSignalWord %dprec 2
+        ;
 
-OptConstantWord        : /* empty */
-       | T_CONSTANT
-       ;
+OptConstantWord : /* empty */
+        | T_CONSTANT
+        ;
 
-OptSignalWord  : /* empty */
-               { printf("empty: %d/%d\n", @$.first_column, @$.last_column); }
-       | T_SIGNAL
-       ;
+OptSignalWord   : /* empty */
+                { printf("empty: %d/%d\n", @$.first_column, @$.last_column); }
+        | T_SIGNAL
+        ;
 
 %%
 
@@ -721,18 +714,13 @@ int yylex (void)
     }
 }
 
-int
-main (void)
-{
-  yyparse();
-  return 0;
-}
+]AT_MAIN_DEFINE[
 ]])
 AT_BISON_OPTION_POPDEFS
 
 AT_BISON_CHECK([[-o glr-regr8.c glr-regr8.y]], 0, [],
-[glr-regr8.y: conflicts: 1 reduce/reduce
-])
+[[glr-regr8.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
+]])
 AT_COMPILE([glr-regr8])
 
 AT_PARSER_CHECK([[./glr-regr8]], 0,
@@ -811,8 +799,8 @@ main (void)
 AT_BISON_OPTION_POPDEFS
 
 AT_BISON_CHECK([[-o glr-regr9.c glr-regr9.y]], 0, [],
-[glr-regr9.y: conflicts: 1 reduce/reduce
-])
+[[glr-regr9.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
+]])
 AT_COMPILE([glr-regr9])
 
 AT_PARSER_CHECK([[./glr-regr9]], 0, [],
@@ -867,8 +855,8 @@ main (void)
 AT_BISON_OPTION_POPDEFS
 
 AT_BISON_CHECK([[-o glr-regr10.c glr-regr10.y]], 0, [],
-[glr-regr10.y: conflicts: 1 reduce/reduce
-])
+[[glr-regr10.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
+]])
 AT_COMPILE([glr-regr10])
 
 AT_PARSER_CHECK([[./glr-regr10]], 0, [], [])
@@ -925,8 +913,8 @@ main (void)
 AT_BISON_OPTION_POPDEFS
 
 AT_BISON_CHECK([[-o glr-regr11.c glr-regr11.y]], 0, [],
-[glr-regr11.y: conflicts: 1 reduce/reduce
-])
+[[glr-regr11.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
+]])
 AT_COMPILE([glr-regr11])
 
 AT_PARSER_CHECK([[./glr-regr11]], 0, [], [])
@@ -1027,17 +1015,17 @@ main (void)
   int exit_status = yyparse ();
   if (parent_rhs_before_value)
     {
-      fprintf (stderr, "`parent_rhs_before' destructor not called.\n");
+      fprintf (stderr, "'parent_rhs_before' destructor not called.\n");
       exit_status = 1;
     }
   if (merged_value)
     {
-      fprintf (stderr, "`merged' destructor not called.\n");
+      fprintf (stderr, "'merged' destructor not called.\n");
       exit_status = 1;
     }
   if (parent_rhs_after_value)
     {
-      fprintf (stderr, "`PARENT_RHS_AFTER' destructor not called.\n");
+      fprintf (stderr, "'PARENT_RHS_AFTER' destructor not called.\n");
       exit_status = 1;
     }
   return exit_status;
@@ -1046,8 +1034,9 @@ main (void)
 AT_BISON_OPTION_POPDEFS
 
 AT_BISON_CHECK([[-o glr-regr12.c glr-regr12.y]], 0, [],
-[glr-regr12.y: conflicts: 1 shift/reduce, 1 reduce/reduce
-])
+[[glr-regr12.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
+glr-regr12.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
+]])
 AT_COMPILE([glr-regr12])
 
 AT_PARSER_CHECK([[./glr-regr12]], 0, [], [])
@@ -1056,7 +1045,7 @@ AT_CLEANUP
 
 
 ## ------------------------------------------------------------------------- ##
-## Incorrect lookahead during deterministic GLR.  See                       ##
+## Incorrect lookahead during deterministic GLR.  See                        ##
 ## <http://lists.gnu.org/archive/html/help-bison/2005-07/msg00017.html> and  ##
 ## <http://lists.gnu.org/archive/html/bison-patches/2006-01/msg00060.html>.  ##
 ## ------------------------------------------------------------------------- ##
@@ -1144,10 +1133,10 @@ print_lookahead (char const *reduction)
     {
       printf ("'%c', yylval='", yychar);
       if (yylval.value > ' ')
-       printf ("%c", yylval.value);
+        printf ("%c", yylval.value);
       printf ("', yylloc=(%d,%d),(%d,%d)",
-             yylloc.first_line, yylloc.first_column,
-             yylloc.last_line, yylloc.last_column);
+              yylloc.first_line, yylloc.first_column,
+              yylloc.last_line, yylloc.last_column);
     }
   printf ("\n");
 }
@@ -1244,7 +1233,7 @@ merge:
   | conflict defstate_look 'a' nonconflict2 'b' defstate_shift %dprec 2 {
     USE ($3); USE ($5);
     print_lookahead ("merge <- conflict defstate_look 'a' nonconflict2 'b'"
-                     " defstate_shift");
+                      " defstate_shift");
   }
   ;
 
@@ -1291,7 +1280,7 @@ alt1:
     USE ($1);
     if (yychar != 'd' && yychar != YYEOF)
       {
-       fprintf (stderr, "Incorrect lookahead during stack explosion.\n");
+        fprintf (stderr, "Incorrect lookahead during stack explosion.\n");
       }
   }
   ;
@@ -1300,7 +1289,7 @@ alt2:
     USE ($1);
     if (yychar != 'd' && yychar != YYEOF)
       {
-       fprintf (stderr, "Incorrect lookahead during stack explosion.\n");
+        fprintf (stderr, "Incorrect lookahead during stack explosion.\n");
       }
   }
   ;
@@ -1309,7 +1298,7 @@ alt3:
     USE ($1);
     if (yychar != 'd' && yychar != YYEOF)
       {
-       fprintf (stderr, "Incorrect lookahead during stack explosion.\n");
+        fprintf (stderr, "Incorrect lookahead during stack explosion.\n");
       }
   }
   ;
@@ -1317,8 +1306,8 @@ no_look:
   {
     if (yychar != YYEMPTY)
       {
-       fprintf (stderr,
-                "Found lookahead where shouldn't during stack explosion.\n");
+        fprintf (stderr,
+                 "Found lookahead where shouldn't during stack explosion.\n");
       }
   }
   ;
@@ -1350,10 +1339,10 @@ print_lookahead (char const *reduction)
     {
       printf ("'%c', yylval='", yychar);
       if (yylval.value > ' ')
-       printf ("%c", yylval.value);
+        printf ("%c", yylval.value);
       printf ("', yylloc=(%d,%d),(%d,%d)",
-             yylloc.first_line, yylloc.first_column,
-             yylloc.last_line, yylloc.last_column);
+              yylloc.first_line, yylloc.first_column,
+              yylloc.last_line, yylloc.last_column);
     }
   printf ("\n");
 }
@@ -1376,8 +1365,8 @@ main (void)
 AT_BISON_OPTION_POPDEFS
 
 AT_BISON_CHECK([[-o glr-regr14.c glr-regr14.y]], 0, [],
-[glr-regr14.y: conflicts: 3 reduce/reduce
-])
+[[glr-regr14.y: warning: 3 reduce/reduce conflicts [-Wconflicts-rr]
+]])
 AT_COMPILE([glr-regr14])
 
 AT_PARSER_CHECK([[./glr-regr14]], 0,
@@ -1460,7 +1449,7 @@ main (void)
   int exit_status = yyparse () != 1;
   if (parent_rhs_before_value)
     {
-      fprintf (stderr, "`parent_rhs_before' destructor not called.\n");
+      fprintf (stderr, "'parent_rhs_before' destructor not called.\n");
       exit_status = 1;
     }
   return exit_status;
@@ -1469,8 +1458,8 @@ main (void)
 AT_BISON_OPTION_POPDEFS
 
 AT_BISON_CHECK([[-o glr-regr15.c glr-regr15.y]], 0, [],
-[glr-regr15.y: conflicts: 2 reduce/reduce
-])
+[[glr-regr15.y: warning: 2 reduce/reduce conflicts [-Wconflicts-rr]
+]])
 AT_COMPILE([glr-regr15])
 
 AT_PARSER_CHECK([[./glr-regr15]], 0, [],
@@ -1529,8 +1518,8 @@ main (void)
 AT_BISON_OPTION_POPDEFS
 
 AT_BISON_CHECK([[-o glr-regr16.c glr-regr16.y]], 0, [],
-[glr-regr16.y: conflicts: 1 reduce/reduce
-])
+[[glr-regr16.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
+]])
 AT_COMPILE([glr-regr16])
 
 AT_PARSER_CHECK([[./glr-regr16]], 0, [],
@@ -1598,20 +1587,16 @@ yylex (YYSTYPE *lvalp, YYLTYPE *llocp)
   return input[toknum++];
 }
 
-int
-main (void)
-{
-  return yyparse () != 1;
-}
+]AT_MAIN_DEFINE[
 ]])
 AT_BISON_OPTION_POPDEFS
 
 AT_BISON_CHECK([[-o glr-regr17.c glr-regr17.y]], 0, [],
-[glr-regr17.y: conflicts: 3 reduce/reduce
-])
+[[glr-regr17.y: warning: 3 reduce/reduce conflicts [-Wconflicts-rr]
+]])
 AT_COMPILE([glr-regr17])
 
-AT_PARSER_CHECK([[./glr-regr17]], 0, [],
+AT_PARSER_CHECK([[./glr-regr17]], 1, [],
 [1.1-2.2: syntax is ambiguous
 ])
 
@@ -1653,20 +1638,16 @@ sym3: %merge<merge> { $$ = 0; } ;
 %%
 ]AT_YYERROR_DEFINE[
 ]AT_YYLEX_DEFINE[
-int
-main (void)
-{
-  return yyparse ();
-}
+]AT_MAIN_DEFINE[
 ]])
 AT_BISON_OPTION_POPDEFS
 
 AT_BISON_CHECK([[-o glr-regr18.c glr-regr18.y]], 1, [],
-[glr-regr18.y:26.18-24: error: result type clash on merge function 'merge': <type2> != <type1>
-glr-regr18.y:25.18-24:     previous declaration
-glr-regr18.y:27.13-19: error: result type clash on merge function 'merge': <type3> != <type2>
-glr-regr18.y:26.18-24:     previous declaration
-])
+[[glr-regr18.y:28.18-24: error: result type clash on merge function 'merge': <type2> != <type1>
+glr-regr18.y:27.18-24:     previous declaration
+glr-regr18.y:29.13-19: error: result type clash on merge function 'merge': <type3> != <type2>
+glr-regr18.y:28.18-24:     previous declaration
+]])
 
 AT_CLEANUP
 
@@ -1677,7 +1658,7 @@ AT_CLEANUP
 
 AT_SETUP([Ambiguity reports])
 
-AT_BISON_OPTION_PUSHDEFS
+AT_BISON_OPTION_PUSHDEFS([%debug])
 AT_DATA_GRAMMAR([input.y],
 [[
 %{
@@ -1700,21 +1681,16 @@ d: /* nada.  */;
 %%
 ]AT_YYERROR_DEFINE[
 ]AT_YYLEX_DEFINE(["abc"])[
-int
-main (void)
-{
-  yydebug = 1;
-  return !!yyparse ();
-}
+]AT_MAIN_DEFINE[
 ]])
 AT_BISON_OPTION_POPDEFS
 
 AT_BISON_CHECK([[-o input.c input.y]], 0, [],
-[input.y: conflicts: 1 reduce/reduce
-])
+[[input.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
+]])
 AT_COMPILE([input])
 
-AT_PARSER_CHECK([[./input]], 1, [],
+AT_PARSER_CHECK([[./input --debug]], 1, [],
 [Starting parse
 Entering state 0
 Reading a token: Next token is token 'a' ()
@@ -1723,14 +1699,14 @@ Entering state 1
 Reading a token: Next token is token 'b' ()
 Shifting token 'b' ()
 Entering state 3
-Reducing stack 0 by rule 3 (line 25):
+Reducing stack 0 by rule 3 (line 27):
    $1 = token 'b' ()
 -> $$ = nterm b ()
 Entering state 4
 Reading a token: Next token is token 'c' ()
 Shifting token 'c' ()
 Entering state 6
-Reducing stack 0 by rule 4 (line 26):
+Reducing stack 0 by rule 4 (line 28):
 -> $$ = nterm d ()
 Entering state 7
 Reading a token: Now at end of input.
index 73f0df7945ad8bf40af9a2a22295fe16658c8887..11b8c917035c14549da451c507c3dc31e1b4e0c0 100644 (file)
@@ -41,7 +41,7 @@ AT_DATA_GRAMMAR([$1.y],
 ]AT_YYLEX_DECLARE_EXTERN[
 %}
 %%
-dummy:;
+dummy: /* empty */;
 %%
 #include <$1.h>
 ])
@@ -68,30 +68,21 @@ AT_TEST_CPP_GUARD_H([9foo],        [%glr-parser])
 
 AT_SETUP([export YYLTYPE])
 
+AT_BISON_OPTION_PUSHDEFS([%name-prefix "my_"])
 AT_DATA_GRAMMAR([input.y],
-[%locations
+[[%locations
 
 %name-prefix "my_"
 %{
 #include <stdio.h>
 #include <stdlib.h>
 
-static int
-my_lex (void)
-{
-  return EOF;
-}
-
-static void
-my_error (const char *msg)
-{
-  fprintf (stderr, "%s\n", msg);
-}
-
+]AT_YYERROR_DEFINE[
+]AT_YYLEX_DEFINE[
 %}
 %%
-exp:;
-])
+exp: /* empty */;
+]])
 
 AT_BISON_CHECK([--defines -o input.c input.y])
 
@@ -102,11 +93,7 @@ YYLTYPE *my_llocp = &my_lloc;
 
 int my_parse (void);
 
-int
-main (void)
-{
-  return my_parse ();
-}
+]AT_MAIN_DEFINE[
 ]])
 
 # Link and execute, just to make sure everything is fine (and in
@@ -115,7 +102,7 @@ AT_COMPILE([caller.o])
 AT_COMPILE([input.o])
 AT_COMPILE([caller], [caller.o input.o])
 AT_PARSER_CHECK([./caller])
-
+AT_BISON_OPTION_POPDEFS
 AT_CLEANUP
 
 ## ----------------- ##
@@ -229,16 +216,13 @@ AT_TEST([x8], [%define api.pure %define api.push-pull both])
 # C++ output relies on namespaces and still uses yy a lot.
 #
 # Check there is no 'YY' left.
-# Ignore comments, YYChar (template parameter), YYPARSE_PARAM
-# (obsolete), YYPUSH_MORE(_DEFINED)?  (constant definition),
-# YY_\w+_INCLUDED (header guards).
-#
+# Ignore comments, YYChar (template parameter), YYPUSH_MORE(_DEFINED)?
+# (constant definition), YY_\w+_INCLUDED (header guards).
 # YYDEBUG (not renamed) can be read, but not changed.
 AT_CHECK([[$PERL -n -0777 -e '
   s{/\*.*?\*/}{}gs;
   s{//.*}{}g;
   s{\b(YYChar
-      |YYPARSE_PARAM
       |YYPUSH_MORE(_DEFINED)?
       |YY_\w+_INCLUDED
       |YY_NULL
index 3f9a62d77ee544aac2e64d88a5abbf612b91099b..322bbe8775b00ceeaf11010c7381597e5e54fb1b 100644 (file)
@@ -20,6 +20,29 @@ AT_BANNER([[Input Processing.]])
 # Mostly test that we are robust to mistakes.
 
 
+## ----------------- ##
+## Invalid options.  ##
+## ----------------- ##
+
+AT_SETUP([Invalid options])
+
+AT_DATA([input.y],
+[[%%
+exp: '0'
+]])
+
+# We used to accept these, as -f, --report and others were sharing
+# their code with -W.
+AT_BISON_CHECK([-ferror=caret input.y], [1], [], [ignore])
+AT_BISON_CHECK([--report=error=itemsets input.y], [1], [], [ignore])
+
+# We used to accept any character after "-Werror", instead of ensuring
+# this is "=".
+AT_BISON_CHECK([-Werror?all input.y], [1], [], [ignore])
+
+AT_CLEANUP
+
+
 ## ---------------- ##
 ## Invalid inputs.  ##
 ## ---------------- ##
@@ -85,13 +108,17 @@ AT_SETUP([Invalid $n and @n])
 
 AT_DATA([input.y],
 [[%%
-exp: { $$ = $1 ; };
-exp: { @$ = @1 ; };
+exp: %empty { $$ = $1 ; };
+exp: %empty { @$ = @1 ; };
 ]])
 
-AT_BISON_CHECK([input.y], [1], [],
-[[input.y:2.13-14: error: integer out of range: '$1'
-input.y:3.13-14: error: integer out of range: '@1'
+AT_BISON_CHECK([-fcaret input.y], [1], [],
+[[input.y:2.20-21: error: integer out of range: '$1'
+ exp: %empty { $$ = $1 ; };
+                    ^^
+input.y:3.20-21: error: integer out of range: '@1'
+ exp: %empty { @$ = @1 ; };
+                    ^^
 ]])
 
 AT_CLEANUP
@@ -110,16 +137,26 @@ AT_DATA([input.y],
 %%
 exp: foo { $$; } foo { $2; } foo
    | foo
-   | /* Empty. */
+   | %empty
    ;
 ]])
 
-AT_BISON_CHECK([input.y], [1], [],
+AT_BISON_CHECK([-fcaret input.y], [1], [],
 [[input.y:5.12-13: error: $$ for the midrule at $2 of 'exp' has no declared type
+ exp: foo { $$; } foo { $2; } foo
+            ^^
 input.y:5.24-25: error: $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
+ exp: foo { $$; } foo { $2; } foo
+                        ^^
+input.y:5.6-32: warning: type clash on default action: <bar> != <> [-Wother]
+ exp: foo { $$; } foo { $2; } foo
+      ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+input.y:6.6-8: warning: type clash on default action: <bar> != <> [-Wother]
+    | foo
+      ^^^
+input.y:7.6-11: warning: empty rule for typed nonterminal, and no action [-Wother]
+    | %empty
+      ^^^^^^
 ]])
 
 AT_CLEANUP
@@ -129,7 +166,6 @@ AT_CLEANUP
 # --------------------------------
 # 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;
@@ -137,15 +173,11 @@ m4_define([_AT_UNUSED_VALUES_DECLARATIONS],
 
 
 # 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, [
@@ -160,7 +192,7 @@ start:
 ;
 
 a: INT | INT { } INT { } INT { };
-b: INT | /* empty */;
+b: INT | %empty;
 c: INT | INT { $]1[; } INT { $<integer>2; } INT { $<integer>4; };
 d: INT | INT { } INT { $]1[; } INT { $<integer>2; };
 e: INT | INT { } INT {  } INT { $]1[; };
@@ -176,103 +208,103 @@ _AT_UNUSED_VALUES_DECLARATIONS])
 
 AT_BISON_CHECK(m4_ifval($2, [--warnings=midrule-values ])[-fcaret input.y],
                [0], [],
-[[input.y:11.10-32: warning: unset value: $][$
+[[input.y:11.10-32: warning: unset value: $][$ [-Wother]
  a: INT | INT { } INT { } INT { };
           ^^^^^^^^^^^^^^^^^^^^^^^
-input.y:11.10-12: warning: unused value: $][1
+input.y:11.10-12: warning: unused value: $][1 [-Wother]
  a: INT | INT { } INT { } INT { };
           ^^^
-input.y:11.18-20: warning: unused value: $][3
+input.y:11.18-20: warning: unused value: $][3 [-Wother]
  a: INT | INT { } INT { } INT { };
                   ^^^
-input.y:11.26-28: warning: unused value: $][5
+input.y:11.26-28: warning: unused value: $][5 [-Wother]
  a: INT | INT { } INT { } INT { };
                           ^^^
-input.y:12.9: warning: empty rule for typed nonterminal, and no action
- b: INT | /* empty */;
-         ^
-]]m4_ifval($2, [[[input.y:13.14-20: warning: unset value: $][$
+input.y:12.10-15: warning: empty rule for typed nonterminal, and no action [-Wother]
+ b: INT | %empty;
+          ^^^^^^
+]]m4_ifval($2, [[[input.y:13.14-20: warning: unset value: $][$ [-Wmidrule-values]
  c: INT | INT { $][1; } INT { $<integer>2; } INT { $<integer>4; };
               ^^^^^^^
-input.y:13.26-41: warning: unset value: $][$
+input.y:13.26-41: warning: unset value: $][$ [-Wmidrule-values]
  c: INT | INT { $][1; } INT { $<integer>2; } INT { $<integer>4; };
                           ^^^^^^^^^^^^^^^^
-]]])[[input.y:13.10-62: warning: unset value: $][$
+]]])[[input.y:13.10-62: warning: unset value: $][$ [-Wother]
  c: INT | INT { $][1; } INT { $<integer>2; } INT { $<integer>4; };
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-input.y:13.22-24: warning: unused value: $][3
+input.y:13.22-24: warning: unused value: $][3 [-Wother]
  c: INT | INT { $][1; } INT { $<integer>2; } INT { $<integer>4; };
                       ^^^
-input.y:13.43-45: warning: unused value: $][5
+input.y:13.43-45: warning: unused value: $][5 [-Wother]
  c: INT | INT { $][1; } INT { $<integer>2; } INT { $<integer>4; };
                                            ^^^
-]]m4_ifval($2, [[[input.y:14.14-16: warning: unset value: $][$
+]]m4_ifval($2, [[[input.y:14.14-16: warning: unset value: $][$ [-Wmidrule-values]
  d: INT | INT { } INT { $][1; } INT { $<integer>2; };
               ^^^
-]]])[[input.y:14.10-49: warning: unset value: $][$
+]]])[[input.y:14.10-49: warning: unset value: $][$ [-Wother]
  d: INT | INT { } INT { $][1; } INT { $<integer>2; };
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-input.y:14.18-20: warning: unused value: $][3
+input.y:14.18-20: warning: unused value: $][3 [-Wother]
  d: INT | INT { } INT { $][1; } INT { $<integer>2; };
                   ^^^
-input.y:14.30-32: warning: unused value: $][5
+input.y:14.30-32: warning: unused value: $][5 [-Wother]
  d: INT | INT { } INT { $][1; } INT { $<integer>2; };
                               ^^^
-input.y:15.10-37: warning: unset value: $][$
+input.y:15.10-37: warning: unset value: $][$ [-Wother]
  e: INT | INT { } INT {  } INT { $][1; };
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-input.y:15.18-20: warning: unused value: $][3
+input.y:15.18-20: warning: unused value: $][3 [-Wother]
  e: INT | INT { } INT {  } INT { $][1; };
                   ^^^
-input.y:15.27-29: warning: unused value: $][5
+input.y:15.27-29: warning: unused value: $][5 [-Wother]
  e: INT | INT { } INT {  } INT { $][1; };
                            ^^^
-input.y:17.10-58: warning: unset value: $][$
+input.y:17.10-58: warning: unset value: $][$ [-Wother]
  g: INT | INT { $<integer>$; } INT { $<integer>$; } INT { };
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-input.y:17.10-12: warning: unused value: $][1
+input.y:17.10-12: warning: unused value: $][1 [-Wother]
  g: INT | INT { $<integer>$; } INT { $<integer>$; } INT { };
           ^^^
-]]m4_ifval($2, [[[input.y:17.14-29: warning: unused value: $][2
+]]m4_ifval($2, [[[input.y:17.14-29: warning: unused value: $][2 [-Wmidrule-values]
  g: INT | INT { $<integer>$; } INT { $<integer>$; } INT { };
               ^^^^^^^^^^^^^^^^
-]]])[[input.y:17.31-33: warning: unused value: $][3
+]]])[[input.y:17.31-33: warning: unused value: $][3 [-Wother]
  g: INT | INT { $<integer>$; } INT { $<integer>$; } INT { };
                                ^^^
-]]m4_ifval($2, [[[input.y:17.35-50: warning: unused value: $][4
+]]m4_ifval($2, [[[input.y:17.35-50: warning: unused value: $][4 [-Wmidrule-values]
  g: INT | INT { $<integer>$; } INT { $<integer>$; } INT { };
                                    ^^^^^^^^^^^^^^^^
-]]])[[input.y:17.52-54: warning: unused value: $][5
+]]])[[input.y:17.52-54: warning: unused value: $][5 [-Wother]
  g: INT | INT { $<integer>$; } INT { $<integer>$; } INT { };
                                                     ^^^
-input.y:18.10-72: warning: unset value: $][$
+input.y:18.10-72: warning: unset value: $][$ [-Wother]
  h: INT | INT { $<integer>$; } INT { $<integer>$ = $<integer>2; } INT { };
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-input.y:18.10-12: warning: unused value: $][1
+input.y:18.10-12: warning: unused value: $][1 [-Wother]
  h: INT | INT { $<integer>$; } INT { $<integer>$ = $<integer>2; } INT { };
           ^^^
-input.y:18.31-33: warning: unused value: $][3
+input.y:18.31-33: warning: unused value: $][3 [-Wother]
  h: INT | INT { $<integer>$; } INT { $<integer>$ = $<integer>2; } INT { };
                                ^^^
-]]m4_ifval($2, [[[input.y:18.35-64: warning: unused value: $][4
+]]m4_ifval($2, [[[input.y:18.35-64: warning: unused value: $][4 [-Wmidrule-values]
  h: INT | INT { $<integer>$; } INT { $<integer>$ = $<integer>2; } INT { };
                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-]]])[[input.y:18.66-68: warning: unused value: $][5
+]]])[[input.y:18.66-68: warning: unused value: $][5 [-Wother]
  h: INT | INT { $<integer>$; } INT { $<integer>$ = $<integer>2; } INT { };
                                                                   ^^^
-]]m4_ifval($2, [[[input.y:20.18-37: warning: unused value: $][3
+]]m4_ifval($2, [[[input.y:20.18-37: warning: unused value: $][3 [-Wmidrule-values]
  j: INT | INT INT { $<integer>$ = 1; } { $][$ = $][1 + $][2; };
                   ^^^^^^^^^^^^^^^^^^^^
-]]])[[input.y:21.10-68: warning: unset value: $][$
+]]])[[input.y:21.10-68: warning: unset value: $][$ [-Wother]
  k: INT | INT INT { $<integer>$; } { $<integer>$ = $<integer>3; } { };
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-input.y:21.10-12: warning: unused value: $][1
+input.y:21.10-12: warning: unused value: $][1 [-Wother]
  k: INT | INT INT { $<integer>$; } { $<integer>$ = $<integer>3; } { };
           ^^^
-input.y:21.14-16: warning: unused value: $][2
+input.y:21.14-16: warning: unused value: $][2 [-Wother]
  k: INT | INT INT { $<integer>$; } { $<integer>$ = $<integer>3; } { };
               ^^^
-]]m4_ifval($2, [[[input.y:21.35-64: warning: unused value: $][4
+]]m4_ifval($2, [[[input.y:21.35-64: warning: unused value: $][4 [-Wmidrule-values]
  k: INT | INT INT { $<integer>$; } { $<integer>$ = $<integer>3; } { };
                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 ]]]))
@@ -319,7 +351,7 @@ AT_DATA([[input.y]],
 
 %%
 
-start: ;
+start: %empty;
 
 %destructor { destroy ($$); } <*>;
 %printer { print ($$); } <*>;
@@ -328,31 +360,79 @@ start: ;
 %printer { print ($$); } <>;
 ]])
 
-AT_BISON_CHECK([input.y], [1], [],
-[[input.y:1.13-29: error: redeclaration for default tagged %destructor
+AT_BISON_CHECK([-fcaret input.y], [1], [],
+[[input.y:1.13-29: error: %destructor redeclaration for <*>
+ %destructor { destroy ($$); } <*> <*>
+             ^^^^^^^^^^^^^^^^^
 input.y:1.13-29:     previous declaration
-input.y:2.10-24: error: redeclaration for default tagged %printer
+ %destructor { destroy ($$); } <*> <*>
+             ^^^^^^^^^^^^^^^^^
+input.y:2.10-24: error: %printer redeclaration for <*>
+ %printer { print ($$); } <*> <*>
+          ^^^^^^^^^^^^^^^
 input.y:2.10-24:     previous declaration
-input.y:4.13-29: error: redeclaration for default tagged %destructor
+ %printer { print ($$); } <*> <*>
+          ^^^^^^^^^^^^^^^
+input.y:4.13-29: error: %destructor redeclaration for <*>
+ %destructor { destroy ($$); } <*>
+             ^^^^^^^^^^^^^^^^^
 input.y:1.13-29:     previous declaration
-input.y:5.10-24: error: redeclaration for default tagged %printer
+ %destructor { destroy ($$); } <*> <*>
+             ^^^^^^^^^^^^^^^^^
+input.y:5.10-24: error: %printer redeclaration for <*>
+ %printer { print ($$); } <*>
+          ^^^^^^^^^^^^^^^
 input.y:2.10-24:     previous declaration
-input.y:7.13-29: error: redeclaration for default tagless %destructor
+ %printer { print ($$); } <*> <*>
+          ^^^^^^^^^^^^^^^
+input.y:7.13-29: error: %destructor redeclaration for <>
+ %destructor { destroy ($$); } <> <>
+             ^^^^^^^^^^^^^^^^^
 input.y:7.13-29:     previous declaration
-input.y:8.10-24: error: redeclaration for default tagless %printer
+ %destructor { destroy ($$); } <> <>
+             ^^^^^^^^^^^^^^^^^
+input.y:8.10-24: error: %printer redeclaration for <>
+ %printer { print ($$); } <> <>
+          ^^^^^^^^^^^^^^^
 input.y:8.10-24:     previous declaration
-input.y:10.13-29: error: redeclaration for default tagless %destructor
+ %printer { print ($$); } <> <>
+          ^^^^^^^^^^^^^^^
+input.y:10.13-29: error: %destructor redeclaration for <>
+ %destructor { destroy ($$); } <>
+             ^^^^^^^^^^^^^^^^^
 input.y:7.13-29:      previous declaration
-input.y:11.10-24: error: redeclaration for default tagless %printer
+ %destructor { destroy ($$); } <> <>
+             ^^^^^^^^^^^^^^^^^
+input.y:11.10-24: error: %printer redeclaration for <>
+ %printer { print ($$); } <>
+          ^^^^^^^^^^^^^^^
 input.y:8.10-24:      previous declaration
-input.y:17.13-29: error: redeclaration for default tagged %destructor
+ %printer { print ($$); } <> <>
+          ^^^^^^^^^^^^^^^
+input.y:17.13-29: error: %destructor redeclaration for <*>
+ %destructor { destroy ($$); } <*>;
+             ^^^^^^^^^^^^^^^^^
 input.y:4.13-29:      previous declaration
-input.y:18.10-24: error: redeclaration for default tagged %printer
+ %destructor { destroy ($$); } <*>
+             ^^^^^^^^^^^^^^^^^
+input.y:18.10-24: error: %printer redeclaration for <*>
+ %printer { print ($$); } <*>;
+          ^^^^^^^^^^^^^^^
 input.y:5.10-24:      previous declaration
-input.y:20.13-29: error: redeclaration for default tagless %destructor
+ %printer { print ($$); } <*>
+          ^^^^^^^^^^^^^^^
+input.y:20.13-29: error: %destructor redeclaration for <>
+ %destructor { destroy ($$); } <>;
+             ^^^^^^^^^^^^^^^^^
 input.y:10.13-29:     previous declaration
-input.y:21.10-24: error: redeclaration for default tagless %printer
+ %destructor { destroy ($$); } <>
+             ^^^^^^^^^^^^^^^^^
+input.y:21.10-24: error: %printer redeclaration for <>
+ %printer { print ($$); } <>;
+          ^^^^^^^^^^^^^^^
 input.y:11.10-24:     previous declaration
+ %printer { print ($$); } <>
+          ^^^^^^^^^^^^^^^
 ]])
 
 AT_CLEANUP
@@ -373,7 +453,7 @@ AT_DATA([[input.y]],
 
 %%
 
-start: ;
+start: %empty;
 
 %destructor { destroy ($$); } <field2> <field1>;
 %printer { print ($$); } <field2> <field1>;
@@ -388,19 +468,144 @@ input.y:5.10-24: error: %printer redeclaration for <field2>
 input.y:2.10-24:     previous declaration
 input.y:5.10-24: error: %printer redeclaration for <field2>
 input.y:5.10-24:     previous declaration
-input.y:11.13-29: error: %destructor redeclaration for <field1>
-input.y:4.13-29:      previous declaration
 input.y:11.13-29: error: %destructor redeclaration for <field2>
 input.y:1.13-29:      previous declaration
-input.y:12.10-24: error: %printer redeclaration for <field1>
-input.y:2.10-24:      previous declaration
+input.y:11.13-29: error: %destructor redeclaration for <field1>
+input.y:4.13-29:      previous declaration
 input.y:12.10-24: error: %printer redeclaration for <field2>
 input.y:5.10-24:      previous declaration
+input.y:12.10-24: error: %printer redeclaration for <field1>
+input.y:2.10-24:      previous declaration
+]])
+
+AT_CLEANUP
+
+## ------------------- ##
+## Undefined symbols.  ##
+## ------------------- ##
+
+AT_SETUP([Undefined symbols])
+
+AT_DATA([[input.y]],
+[[%printer {} foo baz
+%destructor {} bar
+%type <foo> qux
+%%
+exp: bar;
+]])
+
+AT_BISON_CHECK([-fcaret input.y], [1], [],
+[[input.y:2.16-18: error: symbol bar is used, but is not defined as a token and has no rules
+ %destructor {} bar
+                ^^^
+input.y:1.17-19: warning: symbol baz is used, but is not defined as a token and has no rules [-Wother]
+ %printer {} foo baz
+                 ^^^
+input.y:1.13-15: warning: symbol foo is used, but is not defined as a token and has no rules [-Wother]
+ %printer {} foo baz
+             ^^^
+input.y:3.13-15: warning: symbol qux is used, but is not defined as a token and has no rules [-Wother]
+ %type <foo> qux
+             ^^^
 ]])
 
 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 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.  ##
 ## ---------------------------------------- ##
@@ -418,10 +623,16 @@ end: { } ;
 tagged: { } ;
 ]])
 
-AT_BISON_CHECK([input.y], [0], [],
-[[input.y:6.8-45: warning: unset value: $$
-input.y:6.12-14: warning: unused value: $2
-input.y:7.6-8: warning: unset value: $$
+AT_BISON_CHECK([-fcaret input.y], [0], [],
+[[input.y:6.8-45: warning: unset value: $$ [-Wother]
+ start: end end tagged tagged { $<tag>1; $3; } ;
+        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+input.y:6.12-14: warning: unused value: $2 [-Wother]
+ start: end end tagged tagged { $<tag>1; $3; } ;
+            ^^^
+input.y:7.6-8: warning: unset value: $$ [-Wother]
+ end: { } ;
+      ^^^
 ]])
 
 AT_DATA([[input.y]],
@@ -436,8 +647,8 @@ tagged: { } ;
 ]])
 
 AT_BISON_CHECK([input.y], [0], [],
-[[input.y:6.23-28: warning: unused value: $4
-input.y:8.9-11: warning: unset value: $$
+[[input.y:6.23-28: warning: unused value: $4 [-Wother]
+input.y:8.9-11: warning: unset value: $$ [-Wother]
 ]])
 
 AT_CLEANUP
@@ -459,10 +670,16 @@ start: end end { $1; } ;
 end: { }  ;
 ]])
 
-AT_BISON_CHECK([input.y], [0], [],
-[[input.y:6.8-22: warning: unset value: $$
-input.y:6.12-14: warning: unused value: $2
-input.y:7.6-8: warning: unset value: $$
+AT_BISON_CHECK([-fcaret input.y], [0], [],
+[[input.y:6.8-22: warning: unset value: $$ [-Wother]
+ start: end end { $1; } ;
+        ^^^^^^^^^^^^^^^
+input.y:6.12-14: warning: unused value: $2 [-Wother]
+ start: end end { $1; } ;
+            ^^^
+input.y:7.6-8: warning: unset value: $$ [-Wother]
+ end: { }  ;
+      ^^^
 ]])
 
 AT_CLEANUP
@@ -491,15 +708,31 @@ AT_DATA([input.y],
 exp: foo;
 ]])
 
-AT_BISON_CHECK([input.y], [1], [],
+AT_BISON_CHECK([-fcaret input.y], [1], [],
 [[input.y:8.7-11: error: %type redeclaration for foo
+ %type <baz>       "foo"
+       ^^^^^
 input.y:3.7-11:     previous declaration
+ %type <bar>       foo
+       ^^^^^
 input.y:10.13-17: error: %destructor redeclaration for foo
+ %destructor {baz} "foo"
+             ^^^^^
 input.y:5.13-17:      previous declaration
+ %destructor {bar} foo
+             ^^^^^
 input.y:9.10-14: error: %printer redeclaration for foo
+ %printer {baz}    "foo"
+          ^^^^^
 input.y:4.10-14:     previous declaration
+ %printer {bar}    foo
+          ^^^^^
 input.y:11.1-5: error: %left redeclaration for foo
+ %left             "foo"
+ ^^^^^
 input.y:6.1-5:      previous declaration
+ %left             foo
+ ^^^^^
 ]])
 
 AT_CLEANUP
@@ -525,8 +758,10 @@ AT_BISON_CHECK([input.y], [1], [],
 AT_DATA([input.y],
 [{}
 ])
-AT_BISON_CHECK([input.y], [1], [],
+AT_BISON_CHECK([-fcaret  input.y], [1], [],
 [[input.y:1.1-2: error: syntax error, unexpected {...}
+ {}
+ ^^
 ]])
 
 
@@ -614,7 +849,7 @@ exp: '@<:@' '\1' two '$' '@' '{' oline output.or.oline.opt
 
 two: '\x000000000000000000000000000000000000000000000000000000000000000000002';
 oline: '@' 'o' 'l' 'i' 'n' 'e' '@' '_' '_' 'o' 'l' 'i' 'n' 'e' '_' '_';
-output.or.oline.opt: ;|oline;;|output;;;
+output.or.oline.opt: %empty;|oline;;|output;;;
 output: '#' 'o' 'u' 't' 'p' 'u' 't' ' ';
 %%
 /* Exercise M4 quoting: '@:>@@:>@', @<:@, 2.  */
@@ -640,19 +875,14 @@ yylex (void)
 }
 ]])
 
-# Pacify Emacs' font-lock-mode: "
+# Pacify Emacs'font-lock-mode: "
 
 AT_DATA([main.c],
 [[typedef int value;
 #include "input.h"
 
 int yyparse (void);
-
-int
-main (void)
-{
-  return yyparse ();
-}
+]AT_MAIN_DEFINE[
 ]])
 AT_BISON_OPTION_POPDEFS
 
@@ -701,7 +931,7 @@ m4_define([AT_CHECK_REQUIRE],
 AT_DATA_GRAMMAR([input.y],
 [[%require "$1";
 %%
-empty_file:;
+empty_file: %empty;
 ]])
 AT_BISON_CHECK([-o input.c input.y], $2, [], ignore)
 AT_CLEANUP
@@ -719,8 +949,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"
@@ -763,15 +993,15 @@ without_period: "WITHOUT.PERIOD";
 AT_BISON_OPTION_POPDEFS
 
 # 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
+AT_BISON_CHECK([--yacc -Wno-error input.y], [], [],
+[[input.y:9.8-16: warning: POSIX Yacc forbids dashes in symbol names: WITH-DASH [-Wyacc]
+input.y:20.8-16: warning: 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:20.8-16: warning: POSIX Yacc forbids dashes in symbol names: with-dash [-Wyacc]
 ]])
 
 # Dashes are fine for GNU Bison.
@@ -844,10 +1074,10 @@ AT_CLEANUP
 
 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
@@ -859,7 +1089,7 @@ AT_DATA([input.y],
 
 %%
 
-start: ;
+start: %empty;
 
 // Used to report a syntax error because it didn't see any kind of symbol
 // identifier.
@@ -871,15 +1101,6 @@ start: ;
 %destructor { free ($$)
 ]])
 
-AT_BISON_CHECK([-o input.c input.y], 1, [],
-[[input.y:1.10-2.0: error: missing '"' at end of line
-input.y:4.10-5.0: error: missing "'" at end of line
-input.y:14.11-15.0: error: missing "'" at end of line
-input.y:16.11-17.0: error: missing '"' at end of line
-input.y:19.13-20.0: error: missing '}' at end of file
-input.y:20.1: error: syntax error, unexpected end of file
-]])
-
 AT_BISON_CHECK([-fcaret -o input.c input.y], 1, [],
 [[input.y:1.10-2.0: error: missing '"' at end of line
  %token A "a
@@ -908,12 +1129,12 @@ AT_CLEANUP
 
 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],
 [[%%
-false_start: ;
+false_start: %empty;
 start: false_start ;
 %start start;
 ]])
@@ -934,7 +1155,7 @@ AT_SETUP([%prec takes a token])
 AT_DATA([input.y],
 [[%%
 start: PREC %prec PREC ;
-PREC: ;
+PREC: %empty;
 ]])
 
 AT_BISON_CHECK([input.y], [1], [],
@@ -958,7 +1179,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
@@ -976,7 +1197,7 @@ AT_DATA([input-c.y],
 %code bad {}
 %code format {}
 %%
-start: ;
+start: %empty;
 ]])
 AT_BISON_CHECK([[input-c.y]], [[1]], [],
 [[input-c.y:1.7: error: %code qualifier 'q' is not used
@@ -990,7 +1211,7 @@ AT_DATA([input-c-glr.y],
 %code bad {}
  %code bad {}
 %%
-start: ;
+start: %empty;
 ]])
 AT_BISON_CHECK([[input-c-glr.y]], [[1]], [],
 [[input-c-glr.y:1.7: error: %code qualifier 'q' is not used
@@ -1003,7 +1224,7 @@ AT_DATA([input-c++.y],
 %code bad {}
  %code q {}
 %%
-start: ;
+start: %empty;
 ]])
 AT_BISON_CHECK([[input-c++.y]], [[1]], [],
 [[input-c++.y:1.7: error: %code qualifier 'q' is not used
@@ -1016,7 +1237,7 @@ AT_DATA([input-c++-glr.y],
 %code q {}
 %code q {}
 %%
-start: ;
+start: %empty;
 ]])
 AT_BISON_CHECK([[input-c++-glr.y]], [[1]], [],
 [[input-c++-glr.y:1.7-9: error: %code qualifier 'bad' is not used
@@ -1029,7 +1250,7 @@ AT_DATA([special-char-@@.y],
 %code q {}
 %code q {}
 %%
-start: ;
+start: %empty;
 ]])
 AT_BISON_CHECK([[special-char-@@.y]], [[1]], [],
 [[special-char-@@.y:1.7-9: error: %code qualifier 'bad' is not used
@@ -1042,7 +1263,7 @@ AT_DATA([special-char-@:>@.y],
 %code q {}
 %code q {}
 %%
-start: ;
+start: %empty;
 ]])
 AT_BISON_CHECK([[special-char-@:>@.y]], [[1]], [],
 [[special-char-@:>@.y:1.7-9: error: %code qualifier 'bad' is not used
@@ -1066,7 +1287,7 @@ AT_DATA([input-redefined.y],
 %define special1 "@:>@"
 %define special2 "@<:@"
 %%
-start: ;
+start: %empty;
 ]])
 
 AT_BISON_CHECK([[input-redefined.y]], [[1]], [],
@@ -1079,7 +1300,7 @@ input-redefined.y:2.9-11:      previous definition
 AT_DATA([input-unused.y],
 [[%define var "value"
 %%
-start: ;
+start: %empty;
 ]])
 
 AT_BISON_CHECK([[input-unused.y]], [[1]], [],
@@ -1107,7 +1328,7 @@ m4@&t@_divert_pop(0)
 AT_DATA([[input.y]],
 [[%define var-dfg "gram"
 %%
-start: ;
+start: %empty;
 ]])
 AT_BISON_CHECK([[-Dvar-dd=cmd-d1 -Dvar-dd=cmd-d2 \
                  -Fvar-ff=cmd-f1 -Fvar-ff=cmd-f2 \
@@ -1124,32 +1345,32 @@ var-fd: cmd-d
 AT_DATA([[input-dg.y]],
 [[%define var "gram"
 %%
-start: ;
+start: %empty;
 ]])
 AT_BISON_CHECK([[-Dvar=cmd-d input-dg.y]], [[1]], [],
 [[input-dg.y:1.9-11: error: %define variable 'var' redefined
-<command line>:1:      previous definition
+<command line>:2:      previous definition
 ]])
 
 AT_DATA([[input-dg.y]],
 [[%define var "gram"
 %%
-start: ;
+start: %empty;
 ]])
 AT_BISON_CHECK([[-fcaret -Dvar=cmd-d input-dg.y]], [[1]], [],
 [[input-dg.y:1.9-11: error: %define variable 'var' redefined
  %define var "gram"
          ^^^
-<command line>:2:      previous definition
+<command line>:3:      previous definition
 ]])
 
 AT_DATA([[input-unused.y]],
 [[%%
-start: ;
+start: %empty;
 ]])
 AT_BISON_CHECK([[-Dunused-d -Funused-f input-unused.y]], [[1]], [],
-[[<command line>:1: error: %define variable 'unused-d' is not used
-<command line>:2: error: %define variable 'unused-f' is not used
+[[<command line>:2: error: %define variable 'unused-d' is not used
+<command line>:3: error: %define variable 'unused-f' is not used
 ]])
 
 AT_CLEANUP
@@ -1158,14 +1379,14 @@ AT_CLEANUP
 ## %define Boolean variables.  ##
 ## --------------------------- ##
 
-AT_SETUP([[%define Boolean variables]])
+AT_SETUP([["%define" Boolean variables]])
 
 AT_DATA([Input.y],
 [[%language "Java"
 %define public "maybe"
 %define parser_class_name "Input"
 %%
-start: ;
+start: %empty;
 ]])
 
 AT_BISON_CHECK([[Input.y]], [1], [],
@@ -1178,33 +1399,40 @@ AT_CLEANUP
 ## %define enum variables.  ##
 ## ------------------------ ##
 
-AT_SETUP([[%define enum variables]])
+AT_SETUP([["%define" enum variables]])
+
+# Check errors from the front-end, and the back-end.  Since the
+# front-end quits before calling the back-end, these tests cannot be
+# fused.
 
 # Front-end.
 AT_DATA([[input.y]],
-[[%define lr.default-reductions bogus
+[[%define lr.default-reduction bogus
 %%
-start: ;
+start: %empty;
 ]])
-AT_BISON_CHECK([[input.y]], [[1]], [[]],
-[[input.y:1.9-29: error: invalid value for %define variable 'lr.default-reductions': 'bogus'
-input.y:1.9-29:     accepted value: 'most'
-input.y:1.9-29:     accepted value: 'consistent'
-input.y:1.9-29:     accepted value: 'accepting'
+AT_BISON_CHECK([[-fcaret input.y]], [[1]], [[]],
+[[input.y:1.9-28: error: invalid value for %define variable 'lr.default-reduction': 'bogus'
+ %define lr.default-reduction bogus
+         ^^^^^^^^^^^^^^^^^^^^
+input.y:1.9-28:     accepted value: 'most'
+input.y:1.9-28:     accepted value: 'consistent'
+input.y:1.9-28:     accepted value: 'accepting'
 ]])
 
 # Back-end.
-# FIXME: these should be indented, but we shouldn't mess with the m4 yet
 AT_DATA([[input.y]],
 [[%define api.push-pull neither
 %%
-start: ;
+start: %empty;
 ]])
-AT_BISON_CHECK([[input.y]], [1], [],
+AT_BISON_CHECK([[-fcaret input.y]], [[1]], [[]],
 [[input.y:1.9-21: error: invalid value for %define variable 'api.push-pull': 'neither'
-input.y:1.9-21: error: accepted value: 'pull'
-input.y:1.9-21: error: accepted value: 'push'
-input.y:1.9-21: error: accepted value: 'both'
+ %define api.push-pull neither
+         ^^^^^^^^^^^^^
+input.y:1.9-21:     accepted value: 'pull'
+input.y:1.9-21:     accepted value: 'push'
+input.y:1.9-21:     accepted value: 'both'
 ]])
 
 AT_CLEANUP
@@ -1213,39 +1441,37 @@ AT_CLEANUP
 ## %define backward compatibility.  ##
 ## -------------------------------- ##
 
-AT_SETUP([[%define backward compatibility]])
-
-# The error messages tell us whether underscores in these variables are
-# being converted to dashes.
-
-AT_DATA([[input.y]],
-[[%define api.push_pull "neither"
-%%
-start: ;
-]])
-AT_BISON_CHECK([[input.y]], [1], [],
-[[input.y:1.9-21: error: invalid value for %define variable 'api.push-pull': 'neither'
-input.y:1.9-21: error: accepted value: 'pull'
-input.y:1.9-21: error: accepted value: 'push'
-input.y:1.9-21: error: accepted value: 'both'
-]])
+AT_SETUP([["%define" backward compatibility]])
 
+# The error messages tell us whether the variables are properly updated.
 AT_DATA([[input.y]],
-[[%define lr.keep_unreachable_states maybe
+[[%define api.push_pull both
+%define lr.keep_unreachable_states maybe
+%define namespace "foo"
+%define api.namespace {foo}
+%define variant
 %%
-start: ;
-]])
-AT_BISON_CHECK([[input.y]], [1], [],
-[[input.y:1.9-34: error: invalid value for %define Boolean variable 'lr.keep-unreachable-states'
-]])
-
-AT_DATA([[input.y]],
-[[%define foo_bar "baz"
-%%
-start: ;
-]])
-AT_BISON_CHECK([[input.y]], [[1]], [],
-[[input.y:1.9-15: error: %define variable 'foo_bar' is not used
+start: %empty;
+]])
+AT_BISON_CHECK([[-fcaret input.y]], [1], [],
+[[input.y:1.9-21: warning: deprecated directive, use '%define api.push-pull both' [-Wdeprecated]
+ %define api.push_pull both
+         ^^^^^^^^^^^^^
+input.y:2.9-34: warning: deprecated directive, use '%define lr.keep-unreachable-state maybe' [-Wdeprecated]
+ %define lr.keep_unreachable_states maybe
+         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+input.y:3.9-17: warning: deprecated directive, use '%define api.namespace foo' [-Wdeprecated]
+ %define namespace "foo"
+         ^^^^^^^^^
+input.y:4.9-21: error: %define variable 'api.namespace' redefined
+ %define api.namespace {foo}
+         ^^^^^^^^^^^^^
+input.y:3.9-17:     previous definition
+ %define namespace "foo"
+         ^^^^^^^^^
+input.y:5.9-15: warning: deprecated directive, use '%define api.value.type variant' [-Wdeprecated]
+ %define variant
+         ^^^^^^^
 ]])
 
 AT_CLEANUP
@@ -1258,7 +1484,7 @@ AT_SETUP([[Unused %define api.pure]])
 
 # AT_CHECK_API_PURE(DECLS, VALUE)
 # -------------------------------
-# Make sure Bison reports that `%define api.pure VALUE' is unused when DECLS
+# Make sure Bison reports that '%define api.pure VALUE' is unused when DECLS
 # are specified.
 m4_define([AT_CHECK_API_PURE],
 [
@@ -1266,7 +1492,7 @@ AT_DATA([[input.y]],
 [[%define api.pure ]$2[
 ]$1[
 %%
-start: ;
+start: %empty;
 ]])
 
 AT_BISON_CHECK([[input.y]], [[1]], [],
@@ -1274,10 +1500,10 @@ AT_BISON_CHECK([[input.y]], [[1]], [],
 ]])
 ])
 
-AT_CHECK_API_PURE([[%language "c++" %defines]], [[]])
-AT_CHECK_API_PURE([[%language "c++" %defines]], [[false]])
-AT_CHECK_API_PURE([[%language "c++" %defines %glr-parser]], [[""]])
-AT_CHECK_API_PURE([[%language "c++" %defines %glr-parser]], [[false]])
+AT_CHECK_API_PURE([[%language "c++"]], [[]])
+AT_CHECK_API_PURE([[%language "c++"]], [[false]])
+AT_CHECK_API_PURE([[%language "c++" %glr-parser]], [[""]])
+AT_CHECK_API_PURE([[%language "c++" %glr-parser]], [[false]])
 AT_CHECK_API_PURE([[%language "java"]], [[true]])
 AT_CHECK_API_PURE([[%language "java"]], [[false]])
 
@@ -1297,35 +1523,35 @@ m4_define([AT_CHECK_NAMESPACE_ERROR],
 AT_DATA([[input.y]],
 [[%language "C++"
 %defines
-%define namespace "]$1["
+%define api.namespace {]$1[}
 %%
-start: ;
+start: %empty;
 ]])
 
 AT_BISON_CHECK([[input.y]], [1], [],
 [m4_foreach([b4_arg], m4_dquote(m4_shift($@)),
-[[input.y:3.9-17: error: ]b4_arg[
+[[input.y:3.9-21: error: ]b4_arg[
 ]])])
 ])
 
 AT_CHECK_NAMESPACE_ERROR([[]],
                          [[namespace reference is empty]])
-AT_CHECK_NAMESPACE_ERROR([[                            ]],
+AT_CHECK_NAMESPACE_ERROR([[ @tb@@tb@  @tb@ @tb@]],
                          [[namespace reference is empty]])
 AT_CHECK_NAMESPACE_ERROR([[foo::::bar]],
                          [[namespace reference has consecutive "::"]])
-AT_CHECK_NAMESPACE_ERROR([[foo::       ::bar]],
+AT_CHECK_NAMESPACE_ERROR([[foo:: @tb@::bar]],
                          [[namespace reference has consecutive "::"]])
 AT_CHECK_NAMESPACE_ERROR([[::::bar]],
                          [[namespace reference has consecutive "::"]])
 AT_CHECK_NAMESPACE_ERROR([[:: ::bar]],
                          [[namespace reference has consecutive "::"]])
-AT_CHECK_NAMESPACE_ERROR([[foo::bar::  ::]],
+AT_CHECK_NAMESPACE_ERROR([[foo::bar::@tb@::]],
                          [[namespace reference has consecutive "::"]],
                          [[namespace reference has a trailing "::"]])
 AT_CHECK_NAMESPACE_ERROR([[foo::bar::]],
                          [[namespace reference has a trailing "::"]])
-AT_CHECK_NAMESPACE_ERROR([[foo::bar::  ]],
+AT_CHECK_NAMESPACE_ERROR([[foo::bar:: @tb@]],
                          [[namespace reference has a trailing "::"]])
 AT_CHECK_NAMESPACE_ERROR([[::]],
                          [[namespace reference has a trailing "::"]])
@@ -1352,12 +1578,22 @@ 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
+AT_BISON_CHECK([-fcaret empty.y], [1], [],
+[[empty.y:2.8-9: warning: empty character literal [-Wother]
+ start: '';
+        ^^
 empty.y:3.8-4.0: error: missing "'" at end of line
-empty.y:4.8: warning: empty character literal
+ start: '
+        ^
+empty.y:3.8-4.0: warning: empty character literal [-Wother]
+ start: '
+        ^
 empty.y:4.8: error: missing "'" at end of file
+ start: '
+        ^
+empty.y:4.8: warning: empty character literal [-Wother]
+ start: '
+        ^
 ]])
 
 AT_DATA([two.y],
@@ -1368,11 +1604,11 @@ start: 'ab
 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: error: missing "'" at end of line
-two.y:4.8-10: warning: extra characters in character literal
+two.y:3.8-4.0: warning: extra characters in character literal [-Wother]
 two.y:4.8-10: error: missing "'" at end of file
+two.y:4.8-10: warning: extra characters in character literal [-Wother]
 ]])
 
 AT_DATA([three.y],
@@ -1383,11 +1619,11 @@ start: 'abc
 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: error: missing "'" at end of line
-three.y:4.8-11: warning: extra characters in character literal
+three.y:3.8-4.0: warning: extra characters in character literal [-Wother]
 three.y:4.8-11: error: missing "'" at end of file
+three.y:4.8-11: warning: extra characters in character literal [-Wother]
 ]])
 
 AT_CLEANUP
@@ -1414,25 +1650,25 @@ AT_CHECK([[$PERL -e 'print "start: \"\\\t\\\f\\\0\\\1\" ;";' >> input.y \
 
 AT_BISON_CHECK([input.y], [1], [],
 [[input.y:2.9-12: error: 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: error: 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: error: 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: error: 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: error: 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: error: 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: error: 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: error: 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: error: 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: error: 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: error: invalid character after \-escape: \t
 input.y:5.17: error: invalid character after \-escape: \f
 input.y:5.18: error: invalid character after \-escape: \0
@@ -1449,17 +1685,17 @@ AT_SETUP([[LAC: Errors for %define]])
 
 AT_DATA([[input.y]],
 [[%%
-start: ;
+start: %empty;
 ]])
 
 # parse.lac.* options are useless if LAC isn't actually activated.
 AT_BISON_CHECK([[-Dparse.lac.es-capacity-initial=1 input.y]],
                [[1]], [],
-[[<command line>:1: error: %define variable 'parse.lac.es-capacity-initial' is not used
+[[<command line>:2: error: %define variable 'parse.lac.es-capacity-initial' is not used
 ]])
 AT_BISON_CHECK([[-Dparse.lac.memory-trace=full input.y]],
                [[1]], [],
-[[<command line>:1: error: %define variable 'parse.lac.memory-trace' is not used
+[[<command line>:2: error: %define variable 'parse.lac.memory-trace' is not used
 ]])
 
 AT_CLEANUP
@@ -1472,28 +1708,27 @@ AT_SETUP([[-Werror is not affected by -Wnone and -Wall]])
 
 AT_DATA([[input.y]],
 [[%%
-foo-bar: ;
+a: '0' { $$ = $; };
 ]])
 
 # -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.15: warning: stray '$' [-Wother]
 ]])
 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.15: warning: stray '$' [-Wother]
 ]])
 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.15: warning: stray '$' [-Wother]
 ]])
 
 # -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
+AT_BISON_CHECK([[-Werror,none,other input.y]], [[1]], [[]],
+[[input.y:2.15: error: stray '$' [-Werror=other]
+]])
+AT_BISON_CHECK([[-Werror,no-all,other input.y]], [[1]], [[]],
+[[input.y:2.15: error: stray '$' [-Werror=other]
 ]])
-[mv stderr experr]
-AT_BISON_CHECK([[-Werror,no-all,yacc input.y]], [[1]], [[]], [[experr]])
 
 AT_CLEANUP
 
@@ -1502,7 +1737,7 @@ AT_CLEANUP
 ## %name-prefix and %define api.prefix are incompatible.  ##
 ## ------------------------------------------------------ ##
 
-AT_SETUP([[%name-prefix and %define api.prefix are incompatible]])
+AT_SETUP([[%name-prefix and api.prefix are incompatible]])
 
 # AT_TEST(DIRECTIVES, OPTIONS, ERROR-LOCATION)
 # --------------------------------------------
@@ -1510,7 +1745,7 @@ m4_pushdef([AT_TEST],
 [AT_DATA([[input.y]],
 [[$1
 %%
-exp:;
+exp: %empty;
 ]])
 AT_BISON_CHECK([[$2 input.y]], [[1]], [[]],
 [[$3: error: '%name-prefix' and '%define api.prefix' cannot be used together
@@ -1518,8 +1753,8 @@ AT_BISON_CHECK([[$2 input.y]], [[1]], [[]],
 ])
 
 AT_TEST([%define api.prefix foo %name-prefix "bar"], [], [input.y:1.9-18])
-AT_TEST([], [-Dapi.prefix=foo -p bar], [<command line>:1])
-AT_TEST([%name-prefix "bar"], [-Dapi.prefix=foo], [<command line>:1])
+AT_TEST([], [-Dapi.prefix=foo -p bar], [<command line>:2])
+AT_TEST([%name-prefix "bar"], [-Dapi.prefix=foo], [<command line>:2])
 AT_TEST([%define api.prefix foo], [-p bar], [input.y:1.9-18])
 
 m4_popdef([AT_TEST])
@@ -1537,23 +1772,27 @@ AT_SETUP([[Stray $ or @]])
 # check that the warnings are reported once, not three times.
 
 AT_DATA_GRAMMAR([[input.y]],
-[[%token TOK
+[[%type <TYPE> exp
+%token <TYPE> TOK TOK2
 %destructor     { $%; @%; } <*> exp TOK;
 %initial-action { $%; @%; };
 %printer        { $%; @%; } <*> exp TOK;
+%{ $ @ %} // Should not warn.
 %%
 exp: TOK        { $%; @%; $$ = $1; };
+%%
+$ @ // Should not warn.
 ]])
 
-AT_BISON_CHECK([[input.y]], 0, [],
-[[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 '@'
+AT_BISON_CHECK([[-Wall input.y]], 0, [],
+[[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:16.19: warning: stray '$' [-Wother]
+input.y:16.23: warning: stray '@' [-Wother]
 ]])
 
 AT_CLEANUP
@@ -1576,6 +1815,7 @@ m4_pushdef([AT_TEST],
 [AT_DATA([[input.y]],
 [[%type <$1(DEAD %type)> exp
 %token <$1(DEAD %token)> a
+%token b
 %initial-action
 {
   $$;
@@ -1596,13 +1836,13 @@ m4_pushdef([AT_TEST],
 };
 %%
 exp:
-  a a[last]
+  a a[name] b
   {
     $$;
     $][1;
     $<$1(DEAD action 1)>$
     $<$1(DEAD action 2)>1
-    $<$1(DEAD action 3)>last
+    $<$1(DEAD action 3)>name
     $<$1(DEAD action 4)>0
     ;
   };
@@ -1622,3 +1862,121 @@ AT_TEST([@:>@m4_errprintn])
 m4_popdef([AT_TEST])
 
 AT_CLEANUP
+
+##----------------------- ##
+## Deprecated directives. ##
+## ---------------------- ##
+
+AT_SETUP([[Deprecated directives]])
+
+AT_KEYWORDS([[deprec]])
+
+AT_DATA_GRAMMAR([[input.y]],
+[[
+%default_prec
+%error_verbose
+%expect_rr 0
+%file-prefix = "foo"
+%file-prefix
+ =
+"bar"
+%fixed-output_files
+%fixed_output-files
+%fixed-output-files
+%name-prefix= "foo"
+%no-default_prec
+%no_default-prec
+%no_lines
+%output = "foo"
+%pure_parser
+%token_table
+%glr-parser
+%% exp : '0'
+]])
+
+AT_BISON_CHECK([[input.y]], [[0]], [[]],
+[[input.y:10.1-13: warning: deprecated directive: '%default_prec', use '%default-prec' [-Wdeprecated]
+input.y:11.1-14: warning: deprecated directive: '%error_verbose', use '%define parse.error verbose' [-Wdeprecated]
+input.y:12.1-10: warning: deprecated directive: '%expect_rr', use '%expect-rr' [-Wdeprecated]
+input.y:13.1-14: warning: deprecated directive: '%file-prefix =', use '%file-prefix' [-Wdeprecated]
+input.y:14.1-15.2: warning: deprecated directive: '%file-prefix\n =', use '%file-prefix' [-Wdeprecated]
+input.y:17.1-19: warning: deprecated directive: '%fixed-output_files', use '%fixed-output-files' [-Wdeprecated]
+input.y:18.1-19: warning: deprecated directive: '%fixed_output-files', use '%fixed-output-files' [-Wdeprecated]
+input.y:20.1-13: warning: deprecated directive: '%name-prefix=', use '%name-prefix' [-Wdeprecated]
+input.y:21.1-16: warning: deprecated directive: '%no-default_prec', use '%no-default-prec' [-Wdeprecated]
+input.y:22.1-16: warning: deprecated directive: '%no_default-prec', use '%no-default-prec' [-Wdeprecated]
+input.y:23.1-9: warning: deprecated directive: '%no_lines', use '%no-lines' [-Wdeprecated]
+input.y:24.1-9: warning: deprecated directive: '%output =', use '%output' [-Wdeprecated]
+input.y:25.1-12: warning: deprecated directive: '%pure_parser', use '%pure-parser' [-Wdeprecated]
+input.y:26.1-12: warning: deprecated directive: '%token_table', use '%token-table' [-Wdeprecated]
+]])
+
+AT_CLEANUP
+
+## ---------------------------- ##
+## Unput's effect on locations. ##
+## ---------------------------- ##
+dnl When the scanner detects a deprecated construct, it unputs the correct
+dnl version, but it should *not* have any impact on the scanner cursor. If it
+dnl does, the locations of directives on the same line become erroneous.
+
+AT_SETUP([[Unput's effect on locations]])
+
+AT_KEYWORDS([[deprec]])
+
+AT_DATA_GRAMMAR([[input.y]],
+[[
+%glr-parser
+%expect_rr 42 %expect_rr 42
+              %expect_rr 42
+%error_verbose %error_verbose
+               %error_verbose
+%% exp: '0'
+]])
+
+AT_BISON_CHECK([[input.y]], [[1]], [[]],
+[[input.y:11.1-10: warning: deprecated directive: '%expect_rr', use '%expect-rr' [-Wdeprecated]
+input.y:11.15-24: warning: deprecated directive: '%expect_rr', use '%expect-rr' [-Wdeprecated]
+input.y:12.15-24: warning: deprecated directive: '%expect_rr', use '%expect-rr' [-Wdeprecated]
+input.y:13.1-14: warning: deprecated directive: '%error_verbose', use '%define parse.error verbose' [-Wdeprecated]
+input.y:13.16-29: warning: deprecated directive: '%error_verbose', use '%define parse.error verbose' [-Wdeprecated]
+input.y:13.11-21: error: %define variable 'parse.error' redefined
+input.y:13-6:         previous definition
+input.y:14.16-29: warning: deprecated directive: '%error_verbose', use '%define parse.error verbose' [-Wdeprecated]
+input.y:14.11-21: error: %define variable 'parse.error' redefined
+input.y:13.11-21:     previous definition
+]])
+
+AT_CLEANUP
+
+##--------------------------- ##
+## Non-deprecated directives. ##
+## -------------------------- ##
+
+AT_SETUP([[Non-deprecated directives]])
+
+AT_KEYWORDS([[deprec]])
+
+AT_DATA_GRAMMAR([[input.y]],
+[[
+%default-prec
+%error-verbose
+%expect-rr 42
+%file-prefix "foo"
+%file-prefix
+"bar"
+%fixed-output-files
+%name-prefix "foo"
+%no-default-prec
+%no-lines
+%output "foo"
+%pure-parser
+%token-table
+%% exp : '0'
+]])
+
+AT_BISON_CHECK([[input.y]], [[0]], [[]],
+[[input.y: warning: %expect-rr applies only to GLR parsers [-Wother]
+]])
+
+AT_CLEANUP
index ad26be34da72c3eb1de1416af5ddfec1ce37eb91..7f77f28352f4e932d415421837ac8ba0c70aa55b 100644 (file)
@@ -24,9 +24,9 @@ AT_BANNER([[Java Calculator.]])
 
 
 # _AT_DATA_JAVA_CALC_Y($1, $2, $3, [BISON-DIRECTIVES])
-# ----------------------------------------------------------------------
-# Produce `calc.y'.  Don't call this macro directly, because it contains
-# some occurrences of `$1' etc. which will be interpreted by m4.  So
+# ----------------------------------------------------
+# Produce 'calc.y'.  Don't call this macro directly, because it contains
+# some occurrences of '$1' etc. which will be interpreted by m4.  So
 # you should call it with $1, $2, and $3 as arguments, which is what
 # AT_DATA_JAVA_CALC_Y does.
 m4_define([_AT_DATA_JAVA_CALC_Y],
@@ -54,11 +54,11 @@ AT_DATA([Calc.y],
 %token <Integer> NUM "number"
 %type  <Integer> exp
 
-%nonassoc '=' /* comparison            */
+%nonassoc '='       /* comparison            */
 %left '-' '+'
 %left '*' '/'
-%left NEG     /* negation--unary minus */
-%right '^'    /* exponentiation        */
+%precedence NEG     /* negation--unary minus */
+%right '^'          /* exponentiation        */
 
 /* Grammar follows */
 %%
@@ -137,7 +137,7 @@ AT_LOCATION_IF([[
     ]AT_LOCATION_IF([[yypos = new Position (yypos.lineno (),
                                             yypos.token () + 1);]])[
     if (ttype == st.TT_EOF)
-      return Calc.EOF;
+      return EOF;
 
     else if (ttype == st.TT_EOL)
       {
@@ -148,7 +148,7 @@ AT_LOCATION_IF([[
     else if (ttype == st.TT_WORD)
       {
         yylval = new Integer (st.sval);
-        return Calc.NUM;
+        return NUM;
       }
 
     else
@@ -206,7 +206,7 @@ AT_BISON_OPTION_POPDEFS
 
 # AT_DATA_CALC_Y([BISON-OPTIONS])
 # -------------------------------
-# Produce `calc.y'.
+# Produce 'calc.y'.
 m4_define([AT_DATA_JAVA_CALC_Y],
 [_AT_DATA_JAVA_CALC_Y($[1], $[2], $[3], [$1])
 ])
@@ -215,7 +215,7 @@ m4_define([AT_DATA_JAVA_CALC_Y],
 # _AT_CHECK_JAVA_CALC_ERROR(BISON-OPTIONS, INPUT,
 #                           [VERBOSE-AND-LOCATED-ERROR-MESSAGE])
 # --------------------------------------------------------------
-# Run `calc' on INPUT, and expect a `syntax error' message.
+# Run 'calc' on INPUT, and expect a 'syntax error' message.
 #
 # If INPUT starts with a slash, it is used as absolute input file name,
 # otherwise as contents.
@@ -240,7 +240,7 @@ AT_DATA([[expout]],
 AT_YYERROR_SEES_LOC_IF([],
 [[sed 's/^[-0-9.]*: //' expout >at-expout
 mv at-expout expout]])
-# 3. If error-verbose is not used, strip the`, unexpected....' part.
+# 3. If error-verbose is not used, strip the', unexpected....' part.
 m4_bmatch([$1], [%error-verbose], [],
 [[sed 's/syntax error, .*$/syntax error/' expout >at-expout
 mv at-expout expout]])
@@ -249,8 +249,8 @@ AT_CHECK([cat stderr], 0, [expout])
 ])
 
 # _AT_CHECK_JAVA_CALC([BISON-DIRECTIVES], [BISON-CODE])
-# -----------------------------------------------------------------------
-# Start a testing chunk which compiles `calc' grammar with
+# -----------------------------------------------------
+# Start a testing chunk which compiles 'calc' grammar with
 # BISON-DIRECTIVES, and performs several tests over the parser.
 m4_define([_AT_CHECK_JAVA_CALC],
 [# We use integers to avoid dependencies upon the precision of doubles.
@@ -310,7 +310,7 @@ _AT_CHECK_JAVA_CALC_ERROR([$1], [/dev/null],
 #   - (* * *): nothing to pop, a lot to discard
 #   - (1 + 2 * *): some to pop and discard
 #
-# - test the action associated to `error'
+# - test the action associated to 'error'
 #
 # - check the lookahead that triggers an error is not discarded
 #   when we enter error recovery.  Below, the lookahead causing the
@@ -341,8 +341,8 @@ AT_CLEANUP
 
 
 # AT_CHECK_JAVA_CALC([BISON-DIRECTIVES])
-# --------------------------------------------------------
-# Start a testing chunk which compiles `calc' grammar with
+# --------------------------------------
+# Start a testing chunk which compiles 'calc' grammar with
 # BISON-DIRECTIVES, and performs several tests over the parser.
 # Run the test with and without %error-verbose.
 m4_define([AT_CHECK_JAVA_CALC],
@@ -394,9 +394,10 @@ AT_DATA([[YYParser.y]], [
 %debug
 %error-verbose
 %token-table
+%token END "end"
 $1
 %%
-start: "end" {$2};
+start: END {$2};
 %%
 class m4_default([$3], [Position]) {}
 ])
@@ -407,7 +408,7 @@ AT_JAVA_COMPILE([[YYParser.java]])
 
 
 # AT_CHECK_JAVA_MINIMAL_W_LEXER([1:DIRECTIVES], [2:LEX_THROWS],
-#       [3:YYLEX_ACTION], [4:LEXER_BODY], [5:PARSER_ACTION], [6:STYPE],
+#       [3:YYLEX_ACTION], [4:LEXER_BODY], [5:PARSER_ACTION], [6:VALUE_TYPE],
 #       [7:POSITION_TYPE], [8:LOCATION_TYPE])
 # ---------------------------------------------------------------------
 # Check that a mininal parser with DIRECTIVES and a "%code lexer".
@@ -443,14 +444,14 @@ m4_define([AT_CHECK_JAVA_MINIMAL_W_LEXER],
 # Check that YYParser.java contains exactly COUNT lines matching ^LINE$
 # with grep.
 m4_define([AT_CHECK_JAVA_GREP],
-       [AT_CHECK([grep -c '^$1$' YYParser.java], [], [m4_default([$2], [1])
+        [AT_CHECK([grep -c '^$1$' YYParser.java], [], [m4_default([$2], [1])
 ])
 ])
 
 
-# ----------------------------------- #
-# Java parser class and package names #
-# ----------------------------------- #
+# ------------------------------------- #
+# Java parser class and package names #
+# ------------------------------------- #
 
 AT_SETUP([Java parser class and package names])
 
@@ -460,6 +461,9 @@ AT_CHECK_JAVA_GREP([[class YYParser]])
 AT_CHECK_JAVA_MINIMAL([[%name-prefix "Prefix"]])
 AT_CHECK_JAVA_GREP([[class PrefixParser]])
 
+AT_CHECK_JAVA_MINIMAL([[%define api.token.prefix "TOK_"]])
+AT_CHECK_JAVA_GREP([[.*TOK_END.*]])
+
 AT_CHECK_JAVA_MINIMAL([[%define parser_class_name "ParserClassName"]])
 AT_CHECK_JAVA_GREP([[class ParserClassName]])
 
@@ -469,9 +473,9 @@ AT_CHECK_JAVA_GREP([[package user_java_package;]])
 AT_CLEANUP
 
 
-# --------------------------- #
-# Java parser class modifiers #
-# --------------------------- #
+# ----------------------------- #
+# Java parser class modifiers #
+# ----------------------------- #
 
 AT_SETUP([Java parser class modifiers])
 
@@ -524,6 +528,12 @@ AT_CHECK_JAVA_MINIMAL([[
 %define strictfp]])
 AT_CHECK_JAVA_GREP([[public final strictfp class YYParser]])
 
+# FIXME: Can't do a Java compile because javacomp.sh is configured for 1.3
+AT_CHECK_JAVA_MINIMAL([[
+%define annotations "/*@Deprecated @SupressWarnings(\"unchecked\") @SupressWarnings({\"unchecked\", \"deprecation\"}) @SupressWarnings(value={\"unchecked\", \"deprecation\"})*/"
+%define public]])
+AT_CHECK_JAVA_GREP([[/\*@Deprecated @SupressWarnings("unchecked") @SupressWarnings({"unchecked", "deprecation"}) @SupressWarnings(value={"unchecked", "deprecation"})\*/ public class YYParser]])
+
 AT_CLEANUP
 
 
@@ -554,54 +564,54 @@ AT_CLEANUP
 AT_SETUP([Java %parse-param and %lex-param])
 
 AT_CHECK_JAVA_MINIMAL([])
-AT_CHECK_JAVA_GREP([[ *public YYParser (Lexer yylexer) {]])
+AT_CHECK_JAVA_GREP([[ *public YYParser (Lexer yylexer) *]])
 
 AT_CHECK_JAVA_MINIMAL([[%parse-param {int parse_param1}]])
 AT_CHECK_JAVA_GREP([[ *protected final int parse_param1;]])
-AT_CHECK_JAVA_GREP([[ *public YYParser (Lexer yylexer, *int parse_param1) {]])
-AT_CHECK_JAVA_GREP([[[  ]*this.parse_param1 = parse_param1;]])
+AT_CHECK_JAVA_GREP([[ *public YYParser (Lexer yylexer, *int parse_param1) *]])
+AT_CHECK_JAVA_GREP([[ *this.parse_param1 = parse_param1;]])
 
 AT_CHECK_JAVA_MINIMAL([[
 %parse-param {int parse_param1}
 %parse-param {long parse_param2}]])
 AT_CHECK_JAVA_GREP([[ *protected final int parse_param1;]])
 AT_CHECK_JAVA_GREP([[ *protected final long parse_param2;]])
-AT_CHECK_JAVA_GREP([[ *public YYParser (Lexer yylexer, *int parse_param1, *long parse_param2) {]])
-AT_CHECK_JAVA_GREP([[[  ]*this.parse_param1 = parse_param1;]])
-AT_CHECK_JAVA_GREP([[[  ]*this.parse_param2 = parse_param2;]])
+AT_CHECK_JAVA_GREP([[ *public YYParser (Lexer yylexer, *int parse_param1, *long parse_param2) *]])
+AT_CHECK_JAVA_GREP([[ *this.parse_param1 = parse_param1;]])
+AT_CHECK_JAVA_GREP([[ *this.parse_param2 = parse_param2;]])
 
 AT_CHECK_JAVA_MINIMAL_W_LEXER([], [], [[return EOF;]])
-AT_CHECK_JAVA_GREP([[ *public YYParser () {]])
-AT_CHECK_JAVA_GREP([[ *protected YYParser (Lexer yylexer) {]])
+AT_CHECK_JAVA_GREP([[ *public YYParser () *]])
+AT_CHECK_JAVA_GREP([[ *protected YYParser (Lexer yylexer) *]])
 
 AT_CHECK_JAVA_MINIMAL_W_LEXER([[%parse-param {int parse_param1}]],
-       [], [[return EOF;]])
+    [], [[return EOF;]])
 AT_CHECK_JAVA_GREP([[ *protected final int parse_param1;]])
-AT_CHECK_JAVA_GREP([[ *public YYParser (int parse_param1) {]])
-AT_CHECK_JAVA_GREP([[ *protected YYParser (Lexer yylexer, *int parse_param1) {]])
-AT_CHECK_JAVA_GREP([[[  ]*this.parse_param1 = parse_param1;]], [2])
+AT_CHECK_JAVA_GREP([[ *public YYParser (int parse_param1) *]])
+AT_CHECK_JAVA_GREP([[ *protected YYParser (Lexer yylexer, *int parse_param1) *]])
+AT_CHECK_JAVA_GREP([[ *this.parse_param1 = parse_param1;]], [2])
 
 AT_CHECK_JAVA_MINIMAL_W_LEXER([[
 %parse-param {int parse_param1}
 %parse-param {long parse_param2}]],
-       [], [[return EOF;]])
+    [], [[return EOF;]])
 AT_CHECK_JAVA_GREP([[ *protected final int parse_param1;]])
 AT_CHECK_JAVA_GREP([[ *protected final long parse_param2;]])
-AT_CHECK_JAVA_GREP([[ *public YYParser (int parse_param1, *long parse_param2) {]])
-AT_CHECK_JAVA_GREP([[ *protected YYParser (Lexer yylexer, *int parse_param1, *long parse_param2) {]])
-AT_CHECK_JAVA_GREP([[[  ]*this.parse_param1 = parse_param1;]], [2])
-AT_CHECK_JAVA_GREP([[[  ]*this.parse_param2 = parse_param2;]], [2])
+AT_CHECK_JAVA_GREP([[ *public YYParser (int parse_param1, *long parse_param2) *]])
+AT_CHECK_JAVA_GREP([[ *protected YYParser (Lexer yylexer, *int parse_param1, *long parse_param2) *]])
+AT_CHECK_JAVA_GREP([[ *this.parse_param1 = parse_param1;]], [2])
+AT_CHECK_JAVA_GREP([[ *this.parse_param2 = parse_param2;]], [2])
 
 AT_CHECK_JAVA_MINIMAL_W_LEXER([[%lex-param {char lex_param1}]],
-       [], [[return EOF;]], [[YYLexer (char lex_param1) {}]])
-AT_CHECK_JAVA_GREP([[ *public YYParser (char lex_param1) {]])
+    [], [[return EOF;]], [[YYLexer (char lex_param1) {}]])
+AT_CHECK_JAVA_GREP([[ *public YYParser (char lex_param1) *]])
 AT_CHECK_JAVA_GREP([[.* = new YYLexer *(lex_param1);]])
 
 AT_CHECK_JAVA_MINIMAL_W_LEXER([[
 %lex-param {char lex_param1}
 %lex-param {short lex_param2}]],
-       [], [[return EOF;]], [[YYLexer (char lex_param1, short lex_param2) {}]])
-AT_CHECK_JAVA_GREP([[ *public YYParser (char lex_param1, *short lex_param2) {]])
+    [], [[return EOF;]], [[YYLexer (char lex_param1, short lex_param2) {}]])
+AT_CHECK_JAVA_GREP([[ *public YYParser (char lex_param1, *short lex_param2) *]])
 AT_CHECK_JAVA_GREP([[.* = new YYLexer *(lex_param1, *lex_param2);]])
 
 AT_CHECK_JAVA_MINIMAL_W_LEXER([[
@@ -609,14 +619,14 @@ AT_CHECK_JAVA_MINIMAL_W_LEXER([[
 %parse-param {long parse_param2}
 %lex-param {char lex_param1}
 %lex-param {short lex_param2}]],
-       [], [[return EOF;]], [[YYLexer (char lex_param1, short lex_param2) {}]])
+    [], [[return EOF;]], [[YYLexer (char lex_param1, short lex_param2) {}]])
 AT_CHECK_JAVA_GREP([[ *protected final int parse_param1;]])
 AT_CHECK_JAVA_GREP([[ *protected final long parse_param2;]])
-AT_CHECK_JAVA_GREP([[ *public YYParser (char lex_param1, *short lex_param2, *int parse_param1, *long parse_param2) {]])
+AT_CHECK_JAVA_GREP([[ *public YYParser (char lex_param1, *short lex_param2, *int parse_param1, *long parse_param2) *]])
 AT_CHECK_JAVA_GREP([[.* = new YYLexer *(lex_param1, *lex_param2);]])
-AT_CHECK_JAVA_GREP([[ *protected YYParser (Lexer yylexer, *int parse_param1, *long parse_param2) {]])
-AT_CHECK_JAVA_GREP([[[  ]*this.parse_param1 = parse_param1;]], [2])
-AT_CHECK_JAVA_GREP([[[  ]*this.parse_param2 = parse_param2;]], [2])
+AT_CHECK_JAVA_GREP([[ *protected YYParser (Lexer yylexer, *int parse_param1, *long parse_param2) *]])
+AT_CHECK_JAVA_GREP([[ *this.parse_param1 = parse_param1;]], [2])
+AT_CHECK_JAVA_GREP([[ *this.parse_param2 = parse_param2;]], [2])
 
 AT_CLEANUP
 
@@ -627,74 +637,74 @@ AT_CLEANUP
 
 AT_SETUP([Java throws specifications])
 
-# %define throws       - 0 1 2
-# %define lex-throws   - 0 1 2
-# %code lexer            0 1
+# %define throws        - 0 1 2
+# %define lex-throws    - 0 1 2
+# %code lexer             0 1
 
 m4_define([AT_JT_lex_throws_define], [m4_case(AT_JT_lex_throws,
-       -1, [],
-        0, [[%define lex_throws ""]],
-        1, [[%define lex_throws "InterruptedException"]],
-        2, [[%define lex_throws "InterruptedException, IllegalAccessException"]])])
+        -1, [],
+         0, [[%define lex_throws ""]],
+         1, [[%define lex_throws "InterruptedException"]],
+         2, [[%define lex_throws "InterruptedException, IllegalAccessException"]])])
 
 m4_define([AT_JT_yylex_throws], [m4_case(AT_JT_lex_throws,
-       -1, [[ throws java.io.IOException]],
-        0, [],
-        1, [[ throws InterruptedException]],
-        2, [[ throws InterruptedException, IllegalAccessException]])])
+        -1, [[ throws java.io.IOException]],
+         0, [],
+         1, [[ throws InterruptedException]],
+         2, [[ throws InterruptedException, IllegalAccessException]])])
 
 m4_define([AT_JT_yylex_action], [m4_case(AT_JT_lex_throws,
-       -1, [[throw new java.io.IOException();]],
-        0, [[return EOF;]],
-        1, [[throw new InterruptedException();]],
-        2, [[throw new IllegalAccessException();]])])
+        -1, [[throw new java.io.IOException();]],
+         0, [[return EOF;]],
+         1, [[throw new InterruptedException();]],
+         2, [[throw new IllegalAccessException();]])])
 
 
 m4_define([AT_JT_throws_define], [m4_case(AT_JT_throws,
-       -1, [],
-        0, [[%define throws ""]],
-        1, [[%define throws "ClassNotFoundException"]],
-        2, [[%define throws "ClassNotFoundException, InstantiationException"]])])
+        -1, [],
+         0, [[%define throws ""]],
+         1, [[%define throws "ClassNotFoundException"]],
+         2, [[%define throws "ClassNotFoundException, InstantiationException"]])])
 
 m4_define([AT_JT_yyaction_throws], [m4_case(AT_JT_throws,
-       -1, [],
-        0, [],
-        1, [[ throws ClassNotFoundException]],
-        2, [[ throws ClassNotFoundException, InstantiationException]])])
+        -1, [],
+         0, [],
+         1, [[ throws ClassNotFoundException]],
+         2, [[ throws ClassNotFoundException, InstantiationException]])])
 
 m4_define([AT_JT_parse_throws_2], [m4_case(AT_JT_throws,
-       -1, [],
-        0, [],
-        1, [[, ClassNotFoundException]],
-        2, [[, ClassNotFoundException, InstantiationException]])])
+        -1, [],
+         0, [],
+         1, [[, ClassNotFoundException]],
+         2, [[, ClassNotFoundException, InstantiationException]])])
 
 m4_define([AT_JT_parse_throws],
-       [m4_if(m4_quote(AT_JT_yylex_throws), [],
-               [AT_JT_yyaction_throws],
-               [AT_JT_yylex_throws[]AT_JT_parse_throws_2])])
+        [m4_if(m4_quote(AT_JT_yylex_throws), [],
+                [AT_JT_yyaction_throws],
+                [AT_JT_yylex_throws[]AT_JT_parse_throws_2])])
 
 m4_define([AT_JT_initial_action], [m4_case(AT_JT_throws,
-       -1, [],
-        0, [],
-        1, [[%initial-action {if (true) throw new ClassNotFoundException();}]],
-        2, [[%initial-action {if (true) throw new InstantiationException();}]])])
+        -1, [],
+         0, [],
+         1, [[%initial-action {if (true) throw new ClassNotFoundException();}]],
+         2, [[%initial-action {if (true) throw new InstantiationException();}]])])
 
 m4_define([AT_JT_parse_action], [m4_case(AT_JT_throws,
-       -1, [],
-        0, [],
-        1, [[throw new ClassNotFoundException();]],
-        2, [[throw new ClassNotFoundException();]])])
+        -1, [],
+         0, [],
+         1, [[throw new ClassNotFoundException();]],
+         2, [[throw new ClassNotFoundException();]])])
 
 m4_for([AT_JT_lexer], 0, 1, 1,
   [m4_for([AT_JT_lex_throws], -1, 2, 1,
     [m4_for([AT_JT_throws], -1, 2, 1,
       [m4_if(AT_JT_lexer, 0,
-       [AT_CHECK_JAVA_MINIMAL([
+        [AT_CHECK_JAVA_MINIMAL([
 AT_JT_throws_define
 AT_JT_lex_throws_define
 AT_JT_initial_action],
 [AT_JT_parse_action])],
-       [AT_CHECK_JAVA_MINIMAL_W_LEXER([
+        [AT_CHECK_JAVA_MINIMAL_W_LEXER([
 AT_JT_throws_define
 AT_JT_lex_throws_define
 AT_JT_initial_action],
@@ -710,14 +720,36 @@ AT_CHECK_JAVA_GREP([[ *public boolean parse ()]AT_JT_parse_throws[ *]])
 AT_CLEANUP
 
 
-# --------------------------------------------- #
-# Java stype, position_class and location_class #
-# --------------------------------------------- #
+# ------------------------------------- #
+# Java constructor init and init_throws #
+# ------------------------------------- #
+
+AT_SETUP([Java constructor init and init_throws])
+
+AT_CHECK_JAVA_MINIMAL([[
+%define extends "Thread"
+%code init { super("Test Thread"); if (true) throw new InterruptedException(); }
+%define init_throws "InterruptedException"
+%lex-param {int lex_param}]])
+AT_CHECK([[grep -q 'super("Test Thread"); if (true) throw new InterruptedException();' YYParser.java]])
+
+AT_CHECK_JAVA_MINIMAL_W_LEXER([[
+%define extends "Thread"
+%code init { super("Test Thread"); if (true) throw new InterruptedException(); }
+%define init_throws "InterruptedException"]], [], [[return EOF;]])
+AT_CHECK([[grep -q 'super("Test Thread"); if (true) throw new InterruptedException();' YYParser.java]])
+
+AT_CLEANUP
+
+
+# ------------------------------------------ #
+# Java value, position, and location types.  #
+# ------------------------------------------ #
 
-AT_SETUP([Java stype, position_class and location_class])
+AT_SETUP([Java value, position, and location types])
 
 AT_CHECK_JAVA_MINIMAL([[
-%define stype "java.awt.Color"
+%define api.value.type "java.awt.Color"
 %type<java.awt.Color> start;
 %define api.location.type "MyLoc"
 %define api.position.type "MyPos"
@@ -727,7 +759,7 @@ AT_CHECK([[$EGREP -v ' */?\*' YYParser.java | grep 'Position']], [1], [ignore])
 AT_CHECK([[$EGREP -v ' */?\*' YYParser.java | grep 'Location']], [1], [ignore])
 
 AT_CHECK_JAVA_MINIMAL_W_LEXER([[
-%define stype "java.awt.Color"
+%define api.value.type "java.awt.Color"
 %type<java.awt.Color> start;
 %define api.location.type "MyLoc"
 %define api.position.type "MyPos"
index 4a3993b5e6945650a7bb0bed45f8c7754aab5c5a..46bbfeda76f313f947a426b06d86b219c188bd26 100644 (file)
@@ -29,6 +29,23 @@ m4_define([m4_null_if],
          [],  [$2],
          [$3])])
 
+# AT_SETUP_STRIP(TITLE)
+# ---------------------
+# Abbreviate the TITLE to be passed to AT_SETUP.  Remove new-lines
+# that completely break AT_SETUP.
+m4_define([AT_SETUP_STRIP],
+[m4_bpatsubsts([$1],
+      [%\(language\|skeleton\) "?\([^\" ]*\)"?],
+        [\2],
+      [%define "?\([-A-Za-z0-9_.]+\)"? \({[^\}]+}\|"[^\"]+"\|[-A-Za-z0-9_.]+\)],
+        [\1=\2],
+      [%define "?\([-A-Za-z0-9_.]+\)"?],
+        [\1],
+      [ *
++ *],    [ ])dnl
+])
+
+
 ## ------------- ##
 ## Basic tests.  ##
 ## ------------- ##
@@ -80,21 +97,30 @@ m4_define([AT_RESTORE_SPECIAL_FILES], [at_restore_special_files])
 
 # AT_LOC_PUSHDEF(FIRST-LINE, FIRST-COLUMN, LAST-LINE, LAST-COLUMN)
 # ----------------------------------------------------------------
-# Pushdef AT_LOC_(FIRST|LAST)_(LINE|COLUMN).
+# Pushdef AT(_LOC)?_(FIRST|LAST)_(LINE|COLUMN).
 m4_define([AT_LOC_PUSHDEF],
-[m4_pushdef([AT_LOC_FIRST_LINE],  [AT_LOC.$1])
-m4_pushdef([AT_LOC_FIRST_COLUMN], [AT_LOC.$2])
-m4_pushdef([AT_LOC_LAST_LINE],    [AT_LOC.$3])
-m4_pushdef([AT_LOC_LAST_COLUMN],  [AT_LOC.$4])])
+[m4_pushdef([AT_FIRST_LINE],  [$1])
+m4_pushdef([AT_FIRST_COLUMN], [$2])
+m4_pushdef([AT_LAST_LINE],    [$3])
+m4_pushdef([AT_LAST_COLUMN],  [$4])
+m4_pushdef([AT_LOC_FIRST_LINE],   [AT_LOC.AT_FIRST_LINE])
+m4_pushdef([AT_LOC_FIRST_COLUMN], [AT_LOC.AT_FIRST_COLUMN])
+m4_pushdef([AT_LOC_LAST_LINE],    [AT_LOC.AT_LAST_LINE])
+m4_pushdef([AT_LOC_LAST_COLUMN],  [AT_LOC.AT_LAST_COLUMN])])
 
 # AT_LOC_POPDEF
 # -------------
-# Popdef AT_LOC_(FIRST|LAST)_(LINE|COL).
+# Popdef AT(_LOC)?_(FIRST|LAST)_(LINE|COLUMN).
 m4_define([AT_LOC_POPDEF],
 [m4_popdef([AT_LOC_FIRST_LINE])
 m4_popdef([AT_LOC_FIRST_COLUMN])
 m4_popdef([AT_LOC_LAST_LINE])
-m4_popdef([AT_LOC_LAST_COLUMN])])
+m4_popdef([AT_LOC_LAST_COLUMN])
+m4_popdef([AT_FIRST_LINE])
+m4_popdef([AT_FIRST_COLUMN])
+m4_popdef([AT_LAST_LINE])
+m4_popdef([AT_LAST_COLUMN])
+])
 
 
 
@@ -108,13 +134,15 @@ m4_define([AT_BISON_OPTION_PUSHDEFS],
 # _AT_BISON_OPTION_PUSHDEFS($1, $2, [BISON-OPTIONS])
 # --------------------------------------------------
 # This macro works around the impossibility to define macros
-# inside macros, because issuing `[$1]' is not possible in M4 :(.
-# This sucks hard, GNU M4 should really provide M5 like $$1.
+# inside macros, because issuing '[$1]' is not possible in M4 :(.
+# 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
 m4_pushdef([AT_DEFINES_IF],
 [m4_bmatch([$3], [%defines], [$1], [$2])])
+m4_pushdef([AT_DEBUG_IF],
+[m4_bmatch([$3], [%debug\|%define parse.trace], [$1], [$2])])
 m4_pushdef([AT_SKEL_CC_IF],
 [m4_bmatch([$3], [%language "[Cc]\+\+"\|%skeleton "[a-z0-9]+\.cc"], [$1], [$2])])
 m4_pushdef([AT_SKEL_JAVA_IF],
@@ -142,7 +170,8 @@ m4_pushdef([AT_LOCATION_TYPE_IF],
 m4_pushdef([AT_PARAM_IF],
 [m4_bmatch([$3], [%parse-param], [$1], [$2])])
 # Comma-terminated list of formals parse-parameters.
-# E.g., %parse-param { int x } {int y} -> "int x, int y, ".
+# E.g., %parse-param { int x } %parse-param {int y} -> "int x, int y, ".
+# FIXME: Support grouped parse-param.
 m4_pushdef([AT_PARSE_PARAMS])
 m4_bpatsubst([$3], [%parse-param { *\([^{}]*[^{} ]\) *}],
              [m4_append([AT_PARSE_PARAMS], [\1, ])])
@@ -151,10 +180,20 @@ m4_pushdef([AT_PURE_IF],
 [m4_bmatch([$3], [%define  *api\.pure\|%pure-parser],
            [m4_bmatch([$3], [%define  *api\.pure *"?false"?], [$2], [$1])],
            [$2])])
+# AT_NAME_PREFIX: also consider api.namespace.
 m4_pushdef([AT_NAME_PREFIX],
-[m4_bmatch([$3], [\(%define api\.prefix\|%name-prefix\) ".*"],
-           [m4_bregexp([$3], [\(%define api\.prefix\|%name-prefix\) "\([^""]*\)"], [\2])],
-           [yy])])
+[m4_bmatch([$3], [\(%define api\.\(namespace\|prefix\)\|%name-prefix\) .*],
+   [m4_bregexp([$3],
+     [\(%define api\.\(namespace\|prefix\)\|%name-prefix\) [\{\"]\([^""]*\)[\"\}]],
+     [\3])],
+   [yy])])
+m4_pushdef([AT_TOKEN_CTOR_IF],
+[m4_bmatch([$3], [%define api\.token\.constructor], [$1], [$2])])
+m4_pushdef([AT_TOKEN_PREFIX],
+[m4_bmatch([$3], [%define api\.token\.prefix ".*"],
+           [m4_bregexp([$3], [%define api\.token\.prefix "\(.*\)"], [\1])])])
+m4_pushdef([AT_VARIANT_IF],
+[m4_bmatch([$3], [%define api\.value\.type "?variant"?], [$1], [$2])])
 m4_pushdef([AT_API_prefix],
 [m4_bmatch([$3], [%define api\.prefix ".*"],
            [m4_bregexp([$3], [%define api\.prefix "\([^""]*\)"], [\1])],
@@ -168,13 +207,13 @@ m4_pushdef([AT_API_PREFIX],
 m4_pushdef([AT_YYERROR_ARG_LOC_IF],
 [AT_LOCATION_IF([AT_PURE_IF([m4_bmatch([$3],
                                        m4_quote(m4_join([\|],
-                                                        [%define api.pure "?full"?],
+                                                        [%define api\.pure "?full"?],
                                                         [%glr-parser],
                                                         [%parse-param],
                                                         [%skeleton "?glr.c"?])),
                                        [$1], [$2])],
                             [$2])],
-                [$2])])
+                    [$2])])
 
 # yyerror always sees the locations (when activated) if the parser is impure.
 # When the parser is pure, yyerror sees the location if it is received as an
@@ -189,7 +228,7 @@ m4_pushdef([AT_YYERROR_SEES_LOC_IF],
 # 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]],
@@ -203,15 +242,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)]])
@@ -230,6 +269,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
 
 
@@ -251,6 +292,9 @@ m4_popdef([AT_YYERROR_SEES_LOC_IF])
 m4_popdef([AT_YYERROR_ARG_LOC_IF])
 m4_popdef([AT_API_PREFIX])
 m4_popdef([AT_API_prefix])
+m4_popdef([AT_VARIANT_IF])
+m4_popdef([AT_TOKEN_PREFIX])
+m4_popdef([AT_TOKEN_CTOR_IF])
 m4_popdef([AT_NAME_PREFIX])
 m4_popdef([AT_LOCATION_TYPE_IF])
 m4_popdef([AT_LOCATION_IF])
@@ -265,6 +309,7 @@ m4_popdef([AT_SKEL_JAVA_IF])
 m4_popdef([AT_GLR_CC_IF])
 m4_popdef([AT_LALR1_CC_IF])
 m4_popdef([AT_DEFINES_IF])
+m4_popdef([AT_DEBUG_IF])
 AT_LOC_POPDEF])dnl
 ])# AT_BISON_OPTION_POPDEFS
 
@@ -274,6 +319,25 @@ AT_LOC_POPDEF])dnl
 ## Generating Grammar Files.  ##
 ## -------------------------- ##
 
+# _AT_LANG_DISPATCH(LANG, MACRO, ARGS)
+# ------------------------------------
+# Call the specialization of MACRO for LANG with ARGS.  Complain if
+# unavailable.
+m4_define([_AT_LANG_DISPATCH],
+[m4_ifdef([$2($1)],
+       [m4_indir([$2($1)], m4_shift2($@))],
+       [m4_fatal([$2: unknown language: $1])])])
+
+
+# AT_LANG_DISPATCH(MACRO, ARGS)
+# -----------------------------
+# Call the specialization of MACRO for AT_LANG with ARGS.  Complain if
+# unavailable.
+m4_define([AT_LANG_DISPATCH],
+[_AT_LANG_DISPATCH(AT_LANG, $@)])
+
+
+
 # AT_DATA_SOURCE_PROLOGUE
 # ------------------------
 # The prologue that should be included in any source code that is
@@ -363,29 +427,76 @@ static
 # AT_YYERROR_DEFINE
 # -------------------------
 # Must be called inside a AT_BISON_OPTION_PUSHDEFS/POPDEFS pair.
-m4_define([AT_YYERROR_FORMALS],
-[m4_case(AT_LANG,
-[c], [AT_YYERROR_ARG_LOC_IF([AT_YYLTYPE const * const llocp, ])AT_PARSE_PARAMS [const char *msg]])[]dnl
-])
+m4_define([AT_YYERROR_FORMALS],  [AT_LANG_DISPATCH([$0], $@)])
+m4_define([AT_YYERROR_PROTOTYPE],[AT_LANG_DISPATCH([$0], $@)])
+m4_define([AT_YYERROR_DECLARE_EXTERN], [AT_LANG_DISPATCH([$0], $@)])
+m4_define([AT_YYERROR_DECLARE],  [AT_LANG_DISPATCH([$0], $@)])
+m4_define([AT_YYERROR_DEFINE],   [AT_LANG_DISPATCH([$0], $@)])
 
-m4_define([AT_YYERROR_PROTOTYPE],
-[m4_case(AT_LANG,
-[c], [[void ]AT_NAME_PREFIX[error (]AT_YYERROR_FORMALS[)]])[]dnl
-])
+# AT_MAIN_DEFINE
+# --------------
+m4_define([AT_MAIN_DEFINE],   [AT_LANG_DISPATCH([$0], $@)])
 
-m4_define([AT_YYERROR_DECLARE_EXTERN],
-[m4_case(AT_LANG,
-[c], [AT_YYERROR_PROTOTYPE;])[]dnl
-])
 
-m4_define([AT_YYERROR_DECLARE],
-[m4_case(AT_LANG,
-[c], [static AT_YYERROR_DECLARE_EXTERN])[]dnl
-])
 
-m4_define([AT_YYERROR_DEFINE],
-[m4_case(AT_LANG,
-[c], [[#include <stdio.h>
+## --- ##
+## C.  ##
+## --- ##
+
+m4_define([AT_YYERROR_FORMALS(c)],
+[AT_YYERROR_ARG_LOC_IF([AT_YYLTYPE const * const llocp, ])AT_PARSE_PARAMS[const char *msg]])
+
+m4_define([AT_YYERROR_PROTOTYPE(c)],
+[[void ]AT_NAME_PREFIX[error (]AT_YYERROR_FORMALS[)]])
+
+m4_define([AT_YYERROR_DECLARE_EXTERN(c)],
+[AT_YYERROR_PROTOTYPE;])
+
+m4_define([AT_YYERROR_DECLARE(c)],
+[#include <stdio.h>
+]AT_LOCATION_IF([[
+#if defined ]AT_YYLTYPE[_IS_TRIVIAL && ]AT_YYLTYPE[_IS_TRIVIAL
+static unsigned location_print (FILE *yyo, ]AT_YYLTYPE[ const * const yylocp);
+# ifndef LOCATION_PRINT
+#  define LOCATION_PRINT(File, Loc) location_print (File, &(Loc))
+# endif
+#endif
+]])[
+static AT_YYERROR_DECLARE_EXTERN])
+
+
+m4_define([AT_YYERROR_DEFINE(c)],
+[[
+]AT_LOCATION_IF([[
+# if defined ]AT_YYLTYPE[_IS_TRIVIAL && ]AT_YYLTYPE[_IS_TRIVIAL
+/* Print *YYLOCP on YYO. */
+__attribute__((__unused__))
+static unsigned
+location_print (FILE *yyo, ]AT_YYLTYPE[ const * const yylocp)
+{
+  unsigned res = 0;
+  int end_col = 0 != yylocp->last_column ? yylocp->last_column - 1 : 0;
+  if (0 <= yylocp->first_line)
+    {
+      res += fprintf (yyo, "%d", yylocp->first_line);
+      if (0 <= yylocp->first_column)
+        res += fprintf (yyo, ".%d", yylocp->first_column);
+    }
+  if (0 <= yylocp->last_line)
+    {
+      if (yylocp->first_line < yylocp->last_line)
+        {
+          res += fprintf (yyo, "-%d", yylocp->last_line);
+          if (0 <= end_col)
+            res += fprintf (yyo, ".%d", end_col);
+        }
+      else if (0 <= end_col && yylocp->first_column < end_col)
+        res += fprintf (yyo, "-%d", end_col);
+    }
+  return res;
+}
+#endif
+]])[
 /* A C error reporting function.  */
 static
 ]AT_YYERROR_PROTOTYPE[
@@ -393,19 +504,70 @@ static
               [[^,]+[^A-Za-z_0-9]\([A-Za-z_][A-Za-z_0-9]*\), *], [
   YYUSE(\1);])dnl
 AT_YYERROR_SEES_LOC_IF([[
-  YY_LOCATION_PRINT (stderr, ]AT_LOC[);
+  LOCATION_PRINT (stderr, ]AT_LOC[);
   fprintf (stderr, ": ");]])[
   fprintf (stderr, "%s\n", msg);
-}]],
-[c++], [[/* A C++ error reporting function.  */
+}]])
+
+
+m4_define([AT_MAIN_DEFINE(c)],
+[[#include <stdlib.h> /* getenv. */
+#include <string.h> /* strcmp. */
+int
+main (int argc, char const* argv[])
+{]AT_DEBUG_IF([[
+  if (getenv("YYDEBUG")
+      || (argc == 2
+          && (!strcmp (argv[1], "-d") || !strcmp (argv[1], "--debug"))))
+    yydebug |= 1;]], [[
+  (void) argc;
+  (void) argv;]])[
+  return ]AT_NAME_PREFIX[parse ();
+}]])
+
+
+## ----- ##
+## C++.  ##
+## ----- ##
+
+# No need to declare, it's part of the class interface.
+m4_define([AT_YYERROR_DECLARE(c++)],        [])
+m4_define([AT_YYERROR_DECLARE_EXTERN(c++)], [])
+
+m4_define([AT_YYERROR_DEFINE(c++)],
+[[/* A C++ error reporting function.  */
 void
-]AT_NAME_PREFIX[::parser::error (const location_type& l, const std::string& m)
+]AT_NAME_PREFIX[::parser::error (]AT_LOCATION_IF([[const location_type& l, ]])[const std::string& m)
 {
-  (void) l;
   std::cerr << ]AT_LOCATION_IF([l << ": " << ])[m << std::endl;
-}]],
-[java], [AT_LOCATION_IF([[public void yyerror (Calc.Location l, String s)
-  {
+}]])
+
+
+m4_define([AT_MAIN_DEFINE(c++)],
+[[#include <cstdlib> // getenv.
+#include <cstring> // strcmp.
+int
+main (int argc, char const* argv[])
+{
+  ]AT_NAME_PREFIX[::parser p;]AT_DEBUG_IF([[
+  if (getenv("YYDEBUG")
+      || (argc == 2
+          && (!strcmp (argv[1], "-d") || !strcmp (argv[1], "--debug"))))
+    p.set_debug_level (true);]], [[
+  (void) argc;
+  (void) argv;]])[
+  return p.parse ();
+}]])
+
+
+
+## ------ ##
+## Java.  ##
+## ------ ##
+
+m4_define([AT_YYERROR_DEFINE(java)],
+[AT_LOCATION_IF([[public void yyerror (Calc.Location l, String s)
+{
     if (l == null)
       System.err.println (s);
     else
@@ -415,9 +577,19 @@ void
   public void yyerror (String s)
   {
     System.err.println (s);
-  }]])],
-[m4_fatal([$0: invalid language: ]AT_LANG)])dnl
-])
+  }
+]])])
+
+m4_define([AT_MAIN_DEFINE(java)],
+[[class input
+{
+  public static void main (String args[]) throws IOException
+  {
+    YYParser p = new YYParser ();
+    p.parse ();
+  }
+}]])
+
 
 
 ## --------------- ##
@@ -429,7 +601,7 @@ void
 # High-level routine that may call bison several times, under different
 # conditions.
 #
-# Check Bison by invoking `bison BISON_ARGS'.  BISON_ARGS should not contain
+# Check Bison by invoking 'bison BISON_ARGS'.  BISON_ARGS should not contain
 # shell constructs (such as redirection or pipes) that would prevent
 # appending additional command-line arguments for bison. OTHER_AT_CHECK_ARGS
 # are the usual remaining arguments to AT_CHECK: STATUS, STDOUT, etc.
@@ -452,15 +624,11 @@ m4_define([AT_BISON_CHECK],
 [m4_null_if([$2], [AT_BISON_CHECK_XML($@)])
 AT_BISON_CHECK_NO_XML($@)])
 
-m4_define([AT_BISON_WERROR_MSG],
-          [[bison: warnings being treated as errors]])
-
-
 # AT_BISON_CHECK_(BISON_ARGS, [OTHER_AT_CHECK_ARGS])
 # --------------------------------------------------
 # Low-level macro to run bison once.
 m4_define([AT_BISON_CHECK_],
-[AT_CHECK(AT_QUELL_VALGRIND[[ bison ]]$@)])
+[AT_CHECK(AT_QUELL_VALGRIND[[ bison -fno-caret ]]$@)])
 
 
 # AT_BISON_CHECK_WARNINGS(BISON_ARGS, [OTHER_AT_CHECK_ARGS])
@@ -476,7 +644,7 @@ m4_define([AT_BISON_CHECK_WARNINGS_],
 # added after the grammar file name, so skip these checks in that
 # case.
 if test "$POSIXLY_CORRECT_IS_EXPORTED" = false; then
-  ]AT_SAVE_SPECIAL_FILES[
+          ]AT_SAVE_SPECIAL_FILES[
 
   # To avoid expanding it repeatedly, store specified stdout.
   ]AT_DATA([expout], [$3])[
@@ -486,33 +654,10 @@ if test "$POSIXLY_CORRECT_IS_EXPORTED" = false; then
 
   # 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])[
+  ]AT_DATA([[experr]], [$4])[
+  $PERL -pi -e 's{(.*): warning: (.*)\[-W(.*)\]$}
+                 {$][1: error: $][2\@<:@-Werror=$][3@:>@}' experr
+  ]AT_CHECK([[sed 's,.*/$,,' stderr 1>&2]], [[0]], [[]], [experr])[
 
   # Now check --warnings=error.
   cp stderr experr
@@ -534,7 +679,7 @@ fi]dnl
 # when a tortured grammar's XML is known to be too large for xsltproc to
 # handle.
 m4_define([AT_BISON_CHECK_NO_XML],
-[AT_CHECK(m4_null_if([$2], [], [AT_QUELL_VALGRIND ])[[bison ]]$@)
+[AT_CHECK(m4_null_if([$2], [], [AT_QUELL_VALGRIND ])[[bison -fno-caret ]]$@)
 AT_BISON_CHECK_WARNINGS($@)])
 
 # AT_BISON_CHECK_XML(BISON_ARGS, [OTHER_AT_CHECK_ARGS])
@@ -554,10 +699,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 \
@@ -607,7 +752,7 @@ AT_CHECK(m4_join([ ],
                   [-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])
 # ---------------------------------------------
@@ -626,7 +771,8 @@ 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)
 # ------------------------
@@ -639,6 +785,7 @@ AT_SKIP_IF([[test -z "$CONF_JAVA"]])
 AT_CHECK([[$SHELL ../../../javacomp.sh ]$1],
          [[0]], [ignore], [ignore])])
 
+
 # AT_LANG_COMPILE(OUTPUT, [SOURCES = OUTPUT.c]
 # --------------------------------------------
 # Compile SOURCES into OUTPUT.  Skip if compiler does not work.
@@ -646,13 +793,11 @@ AT_CHECK([[$SHELL ../../../javacomp.sh ]$1],
 # If OUTPUT does not contain '.', assume that we are linking too,
 # otherwise pass "-c"; this is a hack.  The default SOURCES is OUTPUT
 # with trailing .o removed, and ".c"/".cc" appended.
-m4_define([AT_LANG_COMPILE],
-[m4_case(AT_LANG,
-[c],    [AT_COMPILE([$1], [$2])],
-[c++],  [AT_COMPILE_CXX([$1], [$2])],
-[java], [AT_JAVA_COMPILE([$1.java], [$2])],
-        [m4_fatal([unknown language: ]m4_defn([AT_LANG]))])[]dnl
-])
+m4_define([AT_LANG_COMPILE],  [AT_LANG_DISPATCH([$0], $@)])
+m4_define([AT_LANG_COMPILE(c)],    [AT_COMPILE([$1], [$2])])
+m4_define([AT_LANG_COMPILE(c++)],  [AT_COMPILE_CXX([$1], [$2])])
+m4_define([AT_LANG_COMPILE(java)], [AT_JAVA_COMPILE([$1.java], [$2])])
+
 
 # AT_FULL_COMPILE(OUTPUT, [OTHER1], [OTHER2])
 # -------------------------------------------
@@ -661,30 +806,31 @@ m4_define([AT_LANG_COMPILE],
 # OUTPUT-OTHER.c, OUTPUT-OTHER.cc, or OUTPUT-OTHER.java to OUTPUT or
 # OUTPUT.java along with it.  Relies on AT_SKEL_CC_IF and
 # AT_SKEL_JAVA_IF.
-m4_define([AT_FULL_COMPILE],
-[m4_case(AT_LANG,
-[java],
-  [AT_BISON_CHECK([-o $1.java $1.y])
-   AT_LANG_COMPILE([$1],
-                   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_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_ifval($3, [[$1-$3.c]])))])
-])
+m4_define([AT_FULL_COMPILE],  [AT_LANG_DISPATCH([$0], $@)])
+m4_define([AT_FULL_COMPILE(c)],
+[AT_BISON_CHECK([-o $1.c $1.y])
+ AT_LANG_COMPILE([$1],
+                 m4_join([ ],
+                         [$1.c],
+                         m4_ifval($2, [[$1-$2.c]]),
+                         m4_ifval($3, [[$1-$3.c]])))])
+
+m4_define([AT_FULL_COMPILE(c++)],
+[AT_BISON_CHECK([-o $1.cc $1.y])
+ AT_LANG_COMPILE([$1],
+                 m4_join([ ],
+                         [$1.cc],
+                         m4_ifval($2, [[$1-$2.cc]]),
+                         m4_ifval($3, [[$1-$3.cc]])))])
+
+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_ifval($3, [[$1-$3.java]])))])
+
 
 
 
@@ -732,7 +878,7 @@ AT_PARSER_CHECK([./c-and-cxx])
 
 # AT_PARSER_CHECK(COMMAND, EXIT-STATUS, EXPOUT, EXPERR, [PRE])
 # ------------------------------------------------------------
-# So that we can run `./testsuite PREPARSER='valgrind -q' for instance.
+# So that we can run './testsuite PREPARSER='valgrind -q' for instance.
 #
 # Get rid of spurious messages when compiled with --coverage:
 # +profiling:/[...]/lib/fprintf.gcda:Merge mismatch for summaries
@@ -774,16 +920,16 @@ m4_define([AT_JAVA_PARSER_CHECK],
 # that Bison exits with value 0, has no stdout, and has stderr
 # BISON-STDERR.
 #
-# If TEST-SPEC contains the attribute `last-state', check that the value
+# If TEST-SPEC contains the attribute 'last-state', check that the value
 # of TABLES-OR-LAST-STATE is the index of the last state generated for
 # the grammar; in other words, check the number of states (minus one).
-# Otherwise, check that everything in the `.output' file starting with
+# Otherwise, check that everything in the '.output' file starting with
 # the definition of state 0 is the same as the entire value of
 # TABLES-OR-LAST-STATE.
 #
 # Expand the M4 in OTHER-CHECKS to perform additional checks of the
-# `.output' file, which is named `input.output', and/or grammar file,
-# which is named `input.y'.
+# '.output' file, which is named 'input.output', and/or grammar file,
+# which is named 'input.y'.
 #
 # Finally, compile the generated parser and then run it using
 # AT_PARSER_CHECK with PARSER-EXIT-VALUE, PARSER-STDOUT, and
@@ -831,7 +977,6 @@ AT_SETUP([$1])
 AT_BISON_OPTION_PUSHDEFS([$4])
 AT_DATA_GRAMMAR([[input.y]],
 [[%code {
-  #include <stdio.h>
   ]AT_YYERROR_DECLARE[
   ]AT_YYLEX_DECLARE[
 }
@@ -854,11 +999,7 @@ yylex (void)
   return *inputp++;
 }
 
-int
-main (void)
-{
-  return yyparse ();
-}
+]AT_MAIN_DEFINE[
 ]])
 
 # In some versions of Autoconf, AT_CHECK invokes AS_ESCAPE before
@@ -869,7 +1010,7 @@ main (void)
 
 m4_if(m4_index(m4_quote($3), [no-xml]), -1,
       [AT_BISON_CHECK],
-      [AT_BISON_CHECK_NO_XML])([[--report=all --defines -o input.c input.y]],
+      [AT_BISON_CHECK_NO_XML])([[-Wall --report=all --defines -o input.c input.y]],
                                [0], [], m4_dquote($7))
 
 m4_if(m4_index(m4_quote($3), [last-state]), -1,
@@ -906,12 +1047,20 @@ m4_popdef([AT_COND_CASE])])
 
 
 
+
 ## ----------------------- ##
 ## Launch the test suite.  ##
 ## ----------------------- ##
 
 AT_INIT
 
+# AT_SETUP([TITLE])
+# -----------------
+# Redefine AT_SETUP to be more concise.  Must be done after AT_INIT.
+m4_copy_force([AT_SETUP], [B4_SETUP])
+m4_define([AT_SETUP],
+[B4_SETUP(m4_expand([AT_SETUP_STRIP([[$1]])]))])
+
 # Cannot assign CC and CFLAGS here, since atlocal is loaded after
 # options are processed, so we don't know the value of CXX and
 # CXXFLAGS yet.
diff --git a/tests/local.mk b/tests/local.mk
new file mode 100644 (file)
index 0000000..5299c2e
--- /dev/null
@@ -0,0 +1,127 @@
+## Makefile for Bison testsuite.
+
+# Copyright (C) 2000-2013 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/>.
+
+EXTRA_DIST += $(TESTSUITE_AT) tests/testsuite
+
+DISTCLEANFILES       += tests/atconfig $(check_SCRIPTS)
+MAINTAINERCLEANFILES += $(TESTSUITE)
+
+## ------------ ##
+## package.m4.  ##
+## ------------ ##
+
+$(top_srcdir)/tests/package.m4: $(top_srcdir)/configure
+       $(AM_V_GEN)rm -f $@ $@.tmp
+       $(AM_V_at){ \
+         echo '# Signature of the current package.'; \
+         echo 'm4_define([AT_PACKAGE_NAME],      [$(PACKAGE_NAME)])'; \
+         echo 'm4_define([AT_PACKAGE_TARNAME],   [$(PACKAGE_TARNAME)])'; \
+         echo 'm4_define([AT_PACKAGE_VERSION],   [$(PACKAGE_VERSION)])'; \
+         echo 'm4_define([AT_PACKAGE_STRING],    [$(PACKAGE_STRING)])'; \
+         echo 'm4_define([AT_PACKAGE_BUGREPORT], [$(PACKAGE_BUGREPORT)])'; \
+       } >$@.tmp
+       $(AM_V_at)mv $@.tmp $@
+
+## ------------------------- ##
+## Generate the test suite.  ##
+## ------------------------- ##
+
+TESTSUITE_AT =                                  \
+  tests/testsuite.at                            \
+                                                \
+  tests/actions.at                              \
+  tests/c++.at                                  \
+  tests/calc.at                                 \
+  tests/conflicts.at                            \
+  tests/cxx-type.at                             \
+  tests/existing.at                             \
+  tests/glr-regression.at                       \
+  tests/headers.at                              \
+  tests/input.at                                \
+  tests/java.at                                 \
+  tests/local.at                                \
+  tests/named-refs.at                           \
+  tests/output.at                               \
+  tests/package.m4                              \
+  tests/push.at                                 \
+  tests/reduce.at                               \
+  tests/regression.at                           \
+  tests/sets.at                                 \
+  tests/skeletons.at                            \
+  tests/synclines.at                            \
+  tests/torture.at                              \
+  tests/types.at
+
+TESTSUITE = $(top_srcdir)/tests/testsuite
+
+AUTOTEST = $(AUTOM4TE) --language=autotest
+AUTOTESTFLAGS = -I $(top_srcdir)/tests
+$(TESTSUITE): $(TESTSUITE_AT)
+       $(AM_V_GEN) \
+         $(AUTOTEST) $(AUTOTESTFLAGS) $(srcdir)/tests/testsuite.at -o $@.tmp
+       $(AM_V_at)$(PERL) -pi -e 's/\@tb\@/\t/g' $@.tmp
+       $(AM_V_at)mv $@.tmp $@
+
+
+## -------------------- ##
+## Run the test suite.  ##
+## -------------------- ##
+
+# Move into tests/ so that testsuite.dir etc. be created there.
+RUN_TESTSUITE = $(TESTSUITE) -C tests $(TESTSUITEFLAGS)
+check_SCRIPTS = $(BISON) tests/atconfig tests/atlocal
+RUN_TESTSUITE_deps = $(TESTSUITE) $(check_SCRIPTS)
+
+clean-local: clean-local-tests
+clean-local-tests:
+       test ! -f $(TESTSUITE) || $(TESTSUITE) -C tests --clean
+
+check-local: $(RUN_TESTSUITE_deps)
+       $(RUN_TESTSUITE)
+
+# Run the test suite on the *installed* tree.
+installcheck-local: $(RUN_TESTSUITE_deps)
+       $(RUN_TESTSUITE) AUTOTEST_PATH='$(bindir)'
+
+# Be real mean with it.
+.PHONY: maintainer-check-g++
+maintainer-check-g++: $(RUN_TESTSUITE_deps)
+       $(RUN_TESTSUITE) --compile-c-with-cxx
+
+.PHONY: maintainer-check-posix
+maintainer-check-posix: $(RUN_TESTSUITE_deps)
+       $(RUN_TESTSUITE) POSIXLY_CORRECT=1 _POSIX2_VERSION=200112
+
+.PHONY: maintainer-check-valgrind
+maintainer-check-valgrind: $(RUN_TESTSUITE_deps)
+       test -z '$(VALGRIND)' ||                                        \
+         $(RUN_TESTSUITE)                                              \
+           PREBISON='$(VALGRIND_PREBISON)' PREPARSER='$(VALGRIND) -q'  \
+           VALGRIND_OPTS='--leak-check=full --show-reachable=yes'
+
+.PHONY: maintainer-check
+maintainer-check: maintainer-check-posix maintainer-check-valgrind maintainer-check-g++
+
+.PHONY: maintainer-push-check
+maintainer-push-check:
+       $(MAKE) $(AM_MAKEFLAGS) maintainer-check                        \
+         TESTSUITEFLAGS='BISON_USE_PUSH_FOR_PULL=1 $(TESTSUITEFLAGS)'
+
+.PHONY: maintainer-xml-check
+maintainer-xml-check:
+       $(MAKE) $(AM_MAKEFLAGS) maintainer-check                \
+         TESTSUITEFLAGS='BISON_TEST_XML=1 $(TESTSUITEFLAGS)'
index 12e726bc18146d1a74261498027a1edf0b9d34d5..1b76c800a986c07826e389c238e0c37a6f272764 100644 (file)
@@ -46,10 +46,10 @@ static int power (int base, int exponent);
 %token <ival> NUM "number"
 %type  <ival> exp
 
-%nonassoc '='   /* comparison         */
+%nonassoc '='   /* comparison          */
 %left '-' '+'
 %left '*' '/'
-%left NEG       /* negation--unary minus */
+%precedence NEG /* negation--unary minus */
 %right '^'      /* exponentiation        */
 
 %%
@@ -69,7 +69,7 @@ exp:
   {
     if ($l != $r)
       fprintf (stderr, "calc: error: %d != %d\n", $l, $r);
-    $$ = $l;
+   $$ = $l;
   }
 | exp[x] '+' { $<ival>$ = $x; } [l] exp[r]  { $$ = $<ival>l + $r;    }
 | exp[l] '-' exp[r]  { $$ = $l - $r;        }
@@ -181,15 +181,16 @@ AT_DATA([input.txt],
 (2^2)^3 = 64
 ]])
 
-AT_BISON_CHECK([-o test.c test.y])
-AT_COMPILE([[test]])
+AT_FULL_COMPILE([[test]])
 AT_PARSER_CHECK([./test input.txt], 0, [], [stderr])
 AT_BISON_OPTION_POPDEFS
 AT_CLEANUP
 
 
 
-#######################################################################
+## ------------------------------------ ##
+## Undefined and ambiguous references.  ##
+## ------------------------------------ ##
 
 
 AT_SETUP([Undefined and ambiguous references])
@@ -211,10 +212,10 @@ static int power (int base, int exponent);
 %token <ival> NUM "number"
 %type  <ival> exp
 
-%nonassoc '='   /* comparison         */
+%nonassoc '='   /* comparison          */
 %left '-' '+'
 %left '*' '/'
-%left NEG       /* negation--unary minus */
+%precedence NEG /* negation--unary minus */
 %right '^'      /* exponentiation        */
 
 %%
@@ -234,7 +235,7 @@ exp:
   {
     if ($l != $r)
       fprintf (stderr, "calc: error: %d != %d\n", $l, $r);
-    $$ = $l;
+   $$ = $l;
   }
 | exp[x] '+' { $<ival>$ = $x; } [l] exp[r] { $$ = $<ival>lo9 + $r; }
 | exp[x] '-' { $<ival>$ = $x; } [l] exp[r] { $$ = $<ival>exp - $r; }
@@ -250,23 +251,48 @@ exp:
 %%
 ]])
 
-AT_BISON_CHECK([-o test.c test.y], 1, [],
-[[test.y:50.51-60: error: invalid reference: '$<ival>lo9'
-test.y:50.3-68:      symbol not found in production: lo9
-test.y:51.51-60: warning: misleading reference: '$<ival>exp'
-test.y:42.1-3:       refers to: $exp at $$
-test.y:51.7:         possibly meant: $x, hiding $exp at $1
-test.y:51.41:        possibly meant: $r, hiding $exp at $4
-test.y:52.51-52: error: $l of 'exp' has no declared type
-test.y:55.40-43: error: invalid reference: '$r12'
-test.y:55.3-47:      symbol not found in production: r12
-test.y:56.29-33: error: invalid reference: '$expo'
-test.y:56.3-46:      symbol not found in production: expo
+AT_BISON_CHECK([-fcaret -o test.c test.y], 1, [],
+[[test.y:52.51-60: error: invalid reference: '$<ival>lo9'
+ | exp[x] '+' { $<ival>$ = $x; } [l] exp[r] { $$ = $<ival>lo9 + $r; }
+                                                   ^^^^^^^^^^
+test.y:52.3-68:      symbol not found in production: lo9
+ | exp[x] '+' { $<ival>$ = $x; } [l] exp[r] { $$ = $<ival>lo9 + $r; }
+   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+test.y:53.51-60: warning: misleading reference: '$<ival>exp' [-Wother]
+ | exp[x] '-' { $<ival>$ = $x; } [l] exp[r] { $$ = $<ival>exp - $r; }
+                                                   ^^^^^^^^^^
+test.y:44.1-3:       refers to: $exp at $$
+ exp:
+ ^^^
+test.y:53.7:         possibly meant: $x, hiding $exp at $1
+ | exp[x] '-' { $<ival>$ = $x; } [l] exp[r] { $$ = $<ival>exp - $r; }
+       ^
+test.y:53.41:        possibly meant: $r, hiding $exp at $4
+ | exp[x] '-' { $<ival>$ = $x; } [l] exp[r] { $$ = $<ival>exp - $r; }
+                                         ^
+test.y:54.51-52: error: $l of 'exp' has no declared type
+ | exp[x] '*' { $<ival>$ = $x; } [l] exp[r] { $$ = $l * $r; }
+                                                   ^^
+test.y:57.40-43: error: invalid reference: '$r12'
+ | exp[l] '^' exp[r]  { $$ = power ($l, $r12); }
+                                        ^^^^
+test.y:57.3-47:      symbol not found in production: r12
+ | exp[l] '^' exp[r]  { $$ = power ($l, $r12); }
+   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+test.y:58.29-33: error: invalid reference: '$expo'
+ | '(' exp ')'        { $$ = $expo;           }
+                             ^^^^^
+test.y:58.3-46:      symbol not found in production: expo
+ | '(' exp ')'        { $$ = $expo;           }
+   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 ]])
 AT_BISON_OPTION_POPDEFS
 AT_CLEANUP
 
-#######################################################################
+
+## ----------------------- ##
+## Misleading references.  ##
+## ----------------------- ##
 
 AT_SETUP([Misleading references])
 AT_DATA_GRAMMAR([test.y],
@@ -277,7 +303,7 @@ foo: '1'
 foo.bar: '2'
 ]])
 AT_BISON_CHECK([-o test.c test.y], 0, [],
-[[test.y:11.22-29: warning: misleading reference: '$foo.bar'
+[[test.y:11.22-29: warning: misleading reference: '$foo.bar' [-Wother]
 test.y:11.8-10:      refers to: $foo at $1
 test.y:11.12-18:     possibly meant: $[foo.bar] at $2
 ]])
@@ -694,7 +720,7 @@ start:
 ;
 ]])
 AT_BISON_CHECK([[test.y]], [[0]], [],
-[[test.y:4.9: warning: stray '$'
-test.y:5.9: warning: stray '@'
+[[test.y:4.9: warning: stray '$' [-Wother]
+test.y:5.9: warning: stray '@' [-Wother]
 ]])
 AT_CLEANUP
index fa8978ded170d09a75e5426e23fd36d4feea24c4..7dbc3db7488d613fac3228cd4ecf126e21d98f29 100644 (file)
@@ -22,85 +22,96 @@ AT_BANNER([[Output file names.]])
 #                 [ADDITIONAL-TESTS], [PRE-TESTS])
 # -----------------------------------------------------------------------------
 m4_define([AT_CHECK_OUTPUT],
-[AT_SETUP([[Output files: $2 $3 $5]])
-$7
-for file in $1 $4; do
-  case "$file" in
-    */*) mkdir -p `echo "$file" | sed 's,/.*,,'`;;
+[AT_SETUP([[Output files: ]$2 $3 $5])[
+]$7[
+for file in ]$1 $4[; do
+  case $file in
+    */*) mkdir -p `echo "$file" | sed 's,/[^/]*,,'`;;
   esac
 done
-AT_DATA([$1],
-[[$2
+]AT_DATA([$1],
+[$2[
 %%
 foo: {};
+]])[
+
+]AT_BISON_CHECK([$3 $1 $5], 0)[
+# Ignore the files non-generated files
+]AT_CHECK([find . -type f -and -not -path './$1' -and -not -path './testsuite.log' |
+           sed 's,\./,,' |
+           sort |
+           xargs echo],
+          [], [$4
+])[
+]$6[
+]AT_CLEANUP[
 ]])
 
-AT_BISON_CHECK([$3 $1 $5], 0)
-AT_CHECK([ls $4], [], [ignore])
-$6
-AT_CLEANUP
-])
-
 AT_CHECK_OUTPUT([foo.y], [], [-dv],
-               [foo.output foo.tab.c foo.tab.h])
+                [foo.output foo.tab.c foo.tab.h])
 
 # Some versions of Valgrind (at least valgrind-3.6.0.SVN-Debian) report
 # "fgrep: write error: Bad file descriptor" when stdout is closed, so we
 # skip this test group during maintainer-check-valgrind.
 AT_CHECK_OUTPUT([foo.y], [], [-dv],
-               [foo.output foo.tab.c foo.tab.h],
-               [>&-], [],
-               [AT_CHECK([[case "$PREBISON" in *valgrind*) exit 77;; esac]])])
+                [foo.output foo.tab.c foo.tab.h],
+                [>&-], [],
+                [AT_CHECK([[case "$PREBISON" in *valgrind*) exit 77;; esac]])])
 
 AT_CHECK_OUTPUT([foo.y], [], [-dv -o foo.c],
-               [foo.c foo.h foo.output])
+                [foo.c foo.h foo.output])
 AT_CHECK_OUTPUT([foo.y], [], [-dv -o foo.tab.c],
-               [foo.output foo.tab.c foo.tab.h])
-AT_CHECK_OUTPUT([foo.y], [], [-dv -y],
-               [y.output y.tab.c y.tab.h])
+                [foo.output foo.tab.c foo.tab.h])
+
+AT_CHECK_OUTPUT([foo.y], [], [-dv -g --xml -y],
+                [y.dot y.output y.tab.c y.tab.h y.xml])
+# With '-o y.tab.c', we expect 'y.output' etc. (for compatility with Yacc).
+AT_CHECK_OUTPUT([foo.y], [], [-dv -g --xml -o y.tab.c],
+                [y.dot y.output y.tab.c y.tab.h y.xml])
+
 AT_CHECK_OUTPUT([foo.y], [], [-dv -b bar],
-               [bar.output bar.tab.c bar.tab.h])
+                [bar.output bar.tab.c bar.tab.h])
 AT_CHECK_OUTPUT([foo.y], [], [-dv -g -o foo.c],
-               [foo.c foo.dot foo.h foo.output])
+                [foo.c foo.dot foo.h foo.output])
 
 
 AT_CHECK_OUTPUT([foo.y], [%defines %verbose],      [],
-               [foo.output foo.tab.c foo.tab.h])
+                [foo.output foo.tab.c foo.tab.h])
 AT_CHECK_OUTPUT([foo.y], [%defines %verbose %yacc],[],
-               [y.output y.tab.c y.tab.h])
+                [y.output y.tab.c y.tab.h])
 
 AT_CHECK_OUTPUT([foo.yy], [%defines %verbose %yacc],[],
-               [y.output y.tab.c y.tab.h])
+                [y.output y.tab.c y.tab.h])
 
 # Exercise %output and %file-prefix including deprecated '='
 AT_CHECK_OUTPUT([foo.y], [%file-prefix "bar" %defines %verbose],      [],
-               [bar.output bar.tab.c bar.tab.h])
-AT_CHECK_OUTPUT([foo.y], [%output="bar.c" %defines %verbose %yacc],[],
-               [bar.output bar.c bar.h])
+                [bar.output bar.tab.c bar.tab.h])
+AT_CHECK_OUTPUT([foo.y], [%output "bar.c" %defines %verbose %yacc],[],
+                [bar.c bar.h bar.output])
 AT_CHECK_OUTPUT([foo.y],
-               [%file-prefix="baz" %output "bar.c" %defines %verbose %yacc],
-               [],
-               [bar.output bar.c bar.h])
+                [%file-prefix "baz" %output "bar.c" %defines %verbose %yacc],
+                [],
+                [bar.c bar.h bar.output])
 
 
 # Check priorities of extension control.
 AT_CHECK_OUTPUT([foo.yy], [%defines %verbose], [],
-               [foo.output foo.tab.cc foo.tab.hh])
+                [foo.output foo.tab.cc foo.tab.hh])
 
 AT_CHECK_OUTPUT([foo.yy], [%defines %verbose ], [-o foo.c],
-               [foo.c foo.h foo.output])
+                [foo.c foo.h foo.output])
 
 AT_CHECK_OUTPUT([foo.yy], [],
-               [--defines=foo.hpp -o foo.c++],
-               [foo.c++ foo.hpp])
+                [--defines=foo.hpp -o foo.c++],
+                [foo.c++ foo.hpp])
 
 AT_CHECK_OUTPUT([foo.yy], [%defines "foo.hpp"],
-               [-o foo.c++],
-               [foo.c++ foo.hpp])
+                [-o foo.c++],
+                [foo.c++ foo.hpp])
 
 AT_CHECK_OUTPUT([foo.yy], [],
-               [-o foo.c++ --graph=foo.gph],
-               [foo.c++ foo.gph])
+                [-o foo.c++ --graph=foo.gph],
+                [foo.c++ foo.gph])
 
 
 ## ------------ ##
@@ -113,22 +124,36 @@ AT_CHECK([grep 'include .subdir/' $1.cc], 1, [])
 AT_CHECK([grep 'include .subdir/' $1.hh], 1, [])
 ])
 
+AT_CHECK_OUTPUT([foo.yy], [%skeleton "lalr1.cc" %verbose], [],
+                [foo.output foo.tab.cc])
+
 AT_CHECK_OUTPUT([foo.yy], [%skeleton "lalr1.cc" %defines %verbose], [],
-               [foo.tab.cc foo.tab.hh foo.output location.hh stack.hh position.hh])
+                [foo.output foo.tab.cc foo.tab.hh stack.hh])
+
+AT_CHECK_OUTPUT([foo.yy], [%skeleton "lalr1.cc" %verbose %locations], [],
+                [foo.output foo.tab.cc])
+
+AT_CHECK_OUTPUT([foo.yy], [%skeleton "lalr1.cc" %defines %verbose %locations], [],
+                [foo.output foo.tab.cc foo.tab.hh location.hh position.hh stack.hh])
 
 AT_CHECK_OUTPUT([subdir/foo.yy], [%skeleton "lalr1.cc" %defines %verbose], [],
-               [foo.tab.cc foo.tab.hh foo.output location.hh stack.hh position.hh],
-               [], [AT_CHECK_NO_SUBDIR_PART([foo.tab])])
+                [foo.output foo.tab.cc foo.tab.hh stack.hh],
+                [], [AT_CHECK_NO_SUBDIR_PART([foo.tab])])
 
-AT_CHECK_OUTPUT([subdir/foo.yy], [%skeleton "lalr1.cc" %defines %verbose],
-               [-o subdir/foo.cc],
-               [subdir/foo.cc subdir/foo.hh subdir/foo.output subdir/location.hh subdir/stack.hh subdir/position.hh],
-               [], [AT_CHECK_NO_SUBDIR_PART([subdir/foo])])
+AT_CHECK_OUTPUT([subdir/foo.yy], [%skeleton "lalr1.cc" %defines %verbose %locations],
+                [-o subdir/foo.cc],
+                [subdir/foo.cc subdir/foo.hh subdir/foo.output subdir/location.hh subdir/position.hh subdir/stack.hh],
+                [], [AT_CHECK_NO_SUBDIR_PART([subdir/foo])])
 
 AT_CHECK_OUTPUT([gram_dir/foo.yy],
                 [%skeleton "lalr1.cc" %defines %verbose %file-prefix "output_dir/foo"],
                 [],
-               [output_dir/foo.tab.cc output_dir/foo.tab.hh output_dir/foo.output output_dir/location.hh output_dir/stack.hh output_dir/position.hh])
+                [output_dir/foo.output output_dir/foo.tab.cc output_dir/foo.tab.hh output_dir/stack.hh])
+
+AT_CHECK_OUTPUT([gram_dir/foo.yy],
+                [%skeleton "lalr1.cc" %defines %locations %verbose %file-prefix "output_dir/foo"],
+                [],
+                [output_dir/foo.output output_dir/foo.tab.cc output_dir/foo.tab.hh output_dir/location.hh output_dir/position.hh output_dir/stack.hh])
 
 
 # AT_CHECK_CONFLICTING_OUTPUT(INPUT-FILE, DIRECTIVES, FLAGS, STDERR,
@@ -157,22 +182,22 @@ AT_CLEANUP
 
 AT_CHECK_CONFLICTING_OUTPUT([foo.y],
 [], [--graph="foo.tab.c"],
-[foo.y: warning: conflicting outputs to file 'foo.tab.c'
-])
+[[foo.y: warning: conflicting outputs to file 'foo.tab.c' [-Wother]
+]])
 
 AT_CHECK_CONFLICTING_OUTPUT([foo.y],
 [%defines "foo.output"], [-v],
-[foo.y: warning: conflicting outputs to file 'foo.output'
-])
+[[foo.y: warning: conflicting outputs to file 'foo.output' [-Wother]
+]])
 
 AT_CHECK_CONFLICTING_OUTPUT([foo.y],
-[%skeleton "lalr1.cc" %defines], [--graph="location.hh"],
-[foo.y: warning: conflicting outputs to file 'location.hh'
-])
+[%skeleton "lalr1.cc" %defines %locations], [--graph="location.hh"],
+[[foo.y: warning: conflicting outputs to file 'location.hh' [-Wother]
+]])
 
 AT_CHECK_CONFLICTING_OUTPUT([foo.y], [], [-o foo.y],
-[foo.y: error: refusing to overwrite the input file 'foo.y'
-], 1)
+[[foo.y: error: refusing to overwrite the input file 'foo.y'
+]], 1)
 
 
 # AT_CHECK_OUTPUT_FILE_NAME(FILE-NAME-PREFIX, [ADDITIONAL-TESTS])
index 6de7186bbcf6c92262345332467620b486caa6a2..7e4977a0ade60123ba123e6a8c13abc65e7ed968 100644 (file)
@@ -88,16 +88,16 @@ exp: useful;
 ]])
 
 AT_BISON_CHECK([[input.y]], 0, [],
-[[input.y: warning: 9 nonterminals useless in grammar
-input.y:4.8-15: warning: nonterminal useless in grammar: useless1
-input.y:5.8-15: warning: nonterminal useless in grammar: useless2
-input.y:6.8-15: warning: nonterminal useless in grammar: useless3
-input.y:7.8-15: warning: nonterminal useless in grammar: useless4
-input.y:8.8-15: warning: nonterminal useless in grammar: useless5
-input.y:9.8-15: warning: nonterminal useless in grammar: useless6
-input.y:10.8-15: warning: nonterminal useless in grammar: useless7
-input.y:11.8-15: warning: nonterminal useless in grammar: useless8
-input.y:12.8-15: warning: nonterminal useless in grammar: useless9
+[[input.y: warning: 9 nonterminals useless in grammar [-Wother]
+input.y:4.8-15: warning: nonterminal useless in grammar: useless1 [-Wother]
+input.y:5.8-15: warning: nonterminal useless in grammar: useless2 [-Wother]
+input.y:6.8-15: warning: nonterminal useless in grammar: useless3 [-Wother]
+input.y:7.8-15: warning: nonterminal useless in grammar: useless4 [-Wother]
+input.y:8.8-15: warning: nonterminal useless in grammar: useless5 [-Wother]
+input.y:9.8-15: warning: nonterminal useless in grammar: useless6 [-Wother]
+input.y:10.8-15: warning: nonterminal useless in grammar: useless7 [-Wother]
+input.y:11.8-15: warning: nonterminal useless in grammar: useless8 [-Wother]
+input.y:12.8-15: warning: nonterminal useless in grammar: useless9 [-Wother]
 ]])
 
 AT_CHECK([[sed -n '/^Grammar/q;/^$/!p' input.output]], 0,
@@ -143,86 +143,64 @@ useless9: '9';
 ]])
 
 AT_BISON_CHECK([[-fcaret input.y]], 0, [],
-[[input.y: warning: 9 nonterminals useless in grammar
-input.y: warning: 9 rules useless in grammar
-input.y:6.1-8: warning: nonterminal useless in grammar: useless1
+[[input.y: warning: 9 nonterminals useless in grammar [-Wother]
+input.y: warning: 9 rules useless in grammar [-Wother]
+input.y:6.1-8: warning: nonterminal useless in grammar: useless1 [-Wother]
  useless1: '1';
  ^^^^^^^^
-input.y:7.1-8: warning: nonterminal useless in grammar: useless2
+input.y:7.1-8: warning: nonterminal useless in grammar: useless2 [-Wother]
  useless2: '2';
  ^^^^^^^^
-input.y:8.1-8: warning: nonterminal useless in grammar: useless3
+input.y:8.1-8: warning: nonterminal useless in grammar: useless3 [-Wother]
  useless3: '3';
  ^^^^^^^^
-input.y:9.1-8: warning: nonterminal useless in grammar: useless4
+input.y:9.1-8: warning: nonterminal useless in grammar: useless4 [-Wother]
  useless4: '4';
  ^^^^^^^^
-input.y:10.1-8: warning: nonterminal useless in grammar: useless5
+input.y:10.1-8: warning: nonterminal useless in grammar: useless5 [-Wother]
  useless5: '5';
  ^^^^^^^^
-input.y:11.1-8: warning: nonterminal useless in grammar: useless6
+input.y:11.1-8: warning: nonterminal useless in grammar: useless6 [-Wother]
  useless6: '6';
  ^^^^^^^^
-input.y:12.1-8: warning: nonterminal useless in grammar: useless7
+input.y:12.1-8: warning: nonterminal useless in grammar: useless7 [-Wother]
  useless7: '7';
  ^^^^^^^^
-input.y:13.1-8: warning: nonterminal useless in grammar: useless8
+input.y:13.1-8: warning: nonterminal useless in grammar: useless8 [-Wother]
  useless8: '8';
  ^^^^^^^^
-input.y:14.1-8: warning: nonterminal useless in grammar: useless9
+input.y:14.1-8: warning: nonterminal useless in grammar: useless9 [-Wother]
  useless9: '9';
  ^^^^^^^^
-input.y:6.11-13: warning: rule useless in grammar
+input.y:6.11-13: warning: rule useless in grammar [-Wother]
  useless1: '1';
            ^^^
-input.y:7.11-13: warning: rule useless in grammar
+input.y:7.11-13: warning: rule useless in grammar [-Wother]
  useless2: '2';
            ^^^
-input.y:8.11-13: warning: rule useless in grammar
+input.y:8.11-13: warning: rule useless in grammar [-Wother]
  useless3: '3';
            ^^^
-input.y:9.11-13: warning: rule useless in grammar
+input.y:9.11-13: warning: rule useless in grammar [-Wother]
  useless4: '4';
            ^^^
-input.y:10.11-13: warning: rule useless in grammar
+input.y:10.11-13: warning: rule useless in grammar [-Wother]
  useless5: '5';
            ^^^
-input.y:11.11-13: warning: rule useless in grammar
+input.y:11.11-13: warning: rule useless in grammar [-Wother]
  useless6: '6';
            ^^^
-input.y:12.11-13: warning: rule useless in grammar
+input.y:12.11-13: warning: rule useless in grammar [-Wother]
  useless7: '7';
            ^^^
-input.y:13.11-13: warning: rule useless in grammar
+input.y:13.11-13: warning: rule useless in grammar [-Wother]
  useless8: '8';
            ^^^
-input.y:14.11-13: warning: rule useless in grammar
+input.y:14.11-13: warning: rule useless in grammar [-Wother]
  useless9: '9';
            ^^^
 ]])
 
-AT_BISON_CHECK([[input.y]], 0, [],
-[[input.y: warning: 9 nonterminals useless in grammar
-input.y: warning: 9 rules useless in grammar
-input.y:6.1-8: warning: nonterminal useless in grammar: useless1
-input.y:7.1-8: warning: nonterminal useless in grammar: useless2
-input.y:8.1-8: warning: nonterminal useless in grammar: useless3
-input.y:9.1-8: warning: nonterminal useless in grammar: useless4
-input.y:10.1-8: warning: nonterminal useless in grammar: useless5
-input.y:11.1-8: warning: nonterminal useless in grammar: useless6
-input.y:12.1-8: warning: nonterminal useless in grammar: useless7
-input.y:13.1-8: warning: nonterminal useless in grammar: useless8
-input.y:14.1-8: warning: nonterminal useless in grammar: useless9
-input.y:6.11-13: warning: rule useless in grammar: useless1: '1'
-input.y:7.11-13: warning: rule useless in grammar: useless2: '2'
-input.y:8.11-13: warning: rule useless in grammar: useless3: '3'
-input.y:9.11-13: warning: rule useless in grammar: useless4: '4'
-input.y:10.11-13: warning: rule useless in grammar: useless5: '5'
-input.y:11.11-13: warning: rule useless in grammar: useless6: '6'
-input.y:12.11-13: warning: rule useless in grammar: useless7: '7'
-input.y:13.11-13: warning: rule useless in grammar: useless8: '8'
-input.y:14.11-13: warning: rule useless in grammar: useless9: '9'
-]])
 
 AT_CHECK([[sed -n '/^Grammar/q;/^$/!p' input.output]], 0,
 [[Nonterminals useless in grammar
@@ -298,35 +276,25 @@ non_productive: non_productive useless_token
 ]])
 
 AT_BISON_CHECK([[-fcaret not-reduced.y]], 0, [],
-[[not-reduced.y: warning: 2 nonterminals useless in grammar
-not-reduced.y: warning: 3 rules useless in grammar
-not-reduced.y:14.1-13: warning: nonterminal useless in grammar: not_reachable
+[[not-reduced.y: warning: 2 nonterminals useless in grammar [-Wother]
+not-reduced.y: warning: 3 rules useless in grammar [-Wother]
+not-reduced.y:14.1-13: warning: nonterminal useless in grammar: not_reachable [-Wother]
  not_reachable: useful  { /* A not reachable action. */ }
  ^^^^^^^^^^^^^
-not-reduced.y:11.6-19: warning: nonterminal useless in grammar: non_productive
+not-reduced.y:11.6-19: warning: nonterminal useless in grammar: non_productive [-Wother]
     | non_productive    { /* A non productive action. */ }
       ^^^^^^^^^^^^^^
-not-reduced.y:11.6-57: warning: rule useless in grammar
+not-reduced.y:11.6-57: warning: rule useless in grammar [-Wother]
     | non_productive    { /* A non productive action. */ }
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-not-reduced.y:14.16-56: warning: rule useless in grammar
+not-reduced.y:14.16-56: warning: rule useless in grammar [-Wother]
  not_reachable: useful  { /* A not reachable action. */ }
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-not-reduced.y:17.17-18.63: warning: rule useless in grammar
+not-reduced.y:17.17-18.63: warning: rule useless in grammar [-Wother]
  non_productive: non_productive useless_token
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 ]])
 
-AT_BISON_CHECK([[not-reduced.y]], 0, [],
-[[not-reduced.y: warning: 2 nonterminals useless in grammar
-not-reduced.y: warning: 3 rules useless in grammar
-not-reduced.y:14.1-13: warning: nonterminal useless in grammar: not_reachable
-not-reduced.y:11.6-19: warning: nonterminal useless in grammar: non_productive
-not-reduced.y:11.6-57: warning: rule useless in grammar: exp: non_productive
-not-reduced.y:14.16-56: warning: rule useless in grammar: not_reachable: useful
-not-reduced.y:17.17-18.63: warning: rule useless in grammar: non_productive: non_productive useless_token
-]])
-
 AT_CHECK([[sed -n '/^Grammar/q;/^$/!p' not-reduced.output]], 0,
 [[Nonterminals useless in grammar
    not_reachable
@@ -393,13 +361,13 @@ indirection: underivable;
 ]])
 
 AT_BISON_CHECK([[input.y]], 0, [],
-[[input.y: warning: 2 nonterminals useless in grammar
-input.y: warning: 3 rules useless in grammar
-input.y:5.15-25: warning: nonterminal useless in grammar: underivable
-input.y:6.14-24: warning: nonterminal useless in grammar: indirection
-input.y:5.15-25: warning: rule useless in grammar: exp: underivable
-input.y:6.14-24: warning: rule useless in grammar: underivable: indirection
-input.y:7.14-24: warning: rule useless in grammar: indirection: underivable
+[[input.y: warning: 2 nonterminals useless in grammar [-Wother]
+input.y: warning: 3 rules useless in grammar [-Wother]
+input.y:5.15-25: warning: nonterminal useless in grammar: underivable [-Wother]
+input.y:6.14-24: warning: nonterminal useless in grammar: indirection [-Wother]
+input.y:5.15-25: warning: rule useless in grammar [-Wother]
+input.y:6.14-24: warning: rule useless in grammar [-Wother]
+input.y:7.14-24: warning: rule useless in grammar [-Wother]
 ]])
 
 AT_CHECK([[sed -n '/^Grammar/q;/^$/!p' input.output]], 0,
@@ -429,8 +397,8 @@ exp: exp;
 ]])
 
 AT_BISON_CHECK([[input.y]], 1, [],
-[[input.y: warning: 2 nonterminals useless in grammar
-input.y: warning: 2 rules useless in grammar
+[[input.y: warning: 2 nonterminals useless in grammar [-Wother]
+input.y: warning: 2 rules useless in grammar [-Wother]
 input.y:3.1-3: fatal error: start symbol exp does not derive any sentence
 ]])
 
@@ -475,7 +443,7 @@ AT_TEST_LR_TYPE([[Single State Split]],
 [[%left 'a'
 // Conflict resolution renders state 12 unreachable for canonical LR(1).  We
 // keep it so that the paser table diff is easier to code.
-%define lr.keep-unreachable-states]],
+%define lr.keep-unreachable-state]],
 [[
 S: 'a' A 'a' /* rule 1 */
  | 'b' A 'b' /* rule 2 */
@@ -708,7 +676,7 @@ AT_TEST_LR_TYPE([[Lane Split]],
 [[%left 'a'
 // Conflict resolution renders state 16 unreachable for canonical LR(1).  We
 // keep it so that the paser table diff is easier to code.
-%define lr.keep-unreachable-states]],
+%define lr.keep-unreachable-state]],
 [[
 /* Similar to the last test case set but two states must be split.  */
 S: 'a' A 'a' /* rule 1 */
@@ -952,7 +920,7 @@ AT_TEST_LR_TYPE([[Complex Lane Split]],
 [[%left 'a'
 // Conflict resolution renders state 16 unreachable for canonical LR(1).  We
 // keep it so that the paser table diff is easier to code.
-%define lr.keep-unreachable-states]],
+%define lr.keep-unreachable-state]],
 [[
 /* Similar to the last test case set but forseeing the S/R conflict from the
    first state that must be split is becoming difficult.  Imagine if B were
@@ -965,7 +933,7 @@ S: 'a' A 'a'
 A: 'a' 'a' B
  ;
 B: 'a'
- | %prec 'a'
+ | %empty %prec 'a'
  ;
 c: 'a' 'a' 'b'
  | A
@@ -1218,7 +1186,7 @@ dnl PARSER-EXIT-VALUE, PARSER-STDOUT, PARSER-STDERR
 ]])])
 
 AT_TEST_LR_TYPE([[Split During Added Lookahead Propagation]],
-[[%define lr.keep-unreachable-states]],
+[[%define lr.keep-unreachable-state]],
 [[
 /* The partial state chart diagram below is for LALR(1).  State 0 is the start
    state.  States are iterated for successor construction in numerical order.
@@ -1270,7 +1238,7 @@ dnl INPUT
 
 dnl BISON-STDERR
 [AT_COND_CASE([[LALR]],
-[[input.y: conflicts: 1 reduce/reduce
+[[input.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
 ]], [])],
 
 dnl TABLES
@@ -1522,28 +1490,28 @@ dnl PARSER-EXIT-VALUE, PARSER-STDOUT, PARSER-STDERR
 
 
 ## ------------------------------- ##
-## %define lr.default-reductions.  ##
+## %define lr.default-reduction.  ##
 ## ------------------------------- ##
 
 # AT_TEST_LR_DEFAULT_REDUCTIONS(GRAMMAR, INPUT, TABLES)
 # -----------------------------------------------------
 m4_define([AT_TEST_LR_DEFAULT_REDUCTIONS],
 [
-AT_TEST_TABLES_AND_PARSE([[no %define lr.default-reductions]],
+AT_TEST_TABLES_AND_PARSE([[no %define lr.default-reduction]],
                          [[most]], [[]],
                          [[]],
                          [$1], [$2], [[]], [$3])
-AT_TEST_TABLES_AND_PARSE([[%define lr.default-reductions most]],
+AT_TEST_TABLES_AND_PARSE([[%define lr.default-reduction most]],
                          [[most]], [[]],
-                         [[%define lr.default-reductions most]],
+                         [[%define lr.default-reduction most]],
                          [$1], [$2], [[]], [$3])
-AT_TEST_TABLES_AND_PARSE([[%define lr.default-reductions consistent]],
+AT_TEST_TABLES_AND_PARSE([[%define lr.default-reduction consistent]],
                          [[consistent]], [[]],
-                         [[%define lr.default-reductions consistent]],
+                         [[%define lr.default-reduction consistent]],
                          [$1], [$2], [[]], [$3])
-AT_TEST_TABLES_AND_PARSE([[%define lr.default-reductions accepting]],
+AT_TEST_TABLES_AND_PARSE([[%define lr.default-reduction accepting]],
                          [[accepting]], [[]],
-                         [[%define lr.default-reductions accepting]],
+                         [[%define lr.default-reduction accepting]],
                          [$1], [$2], [[]], [$3])
 ])
 
@@ -1565,8 +1533,8 @@ a: 'a' ;
    and multiple reductions.  The first reduction has more lookaheads than the
    second, so the first should always be preferred as the default reduction if
    enabled.  The second reduction has one lookahead.  */
-b: ;
-c: ;
+b: %empty;
+c: %empty;
 ]],
 dnl Visit each state mentioned above.
 [['a', 'a']],
index 6a165bf56cd25791949de666885d199b0cb69378..f101f2180f9205fb62a687d69536042fb65c72dd 100644 (file)
@@ -130,7 +130,6 @@ AT_SETUP([Early token definitions without --yacc])
 AT_BISON_OPTION_PUSHDEFS
 AT_DATA_GRAMMAR([input.y],
 [[%{
-#include <stdio.h>
 ]AT_YYERROR_DECLARE_EXTERN[
 ]AT_YYLEX_DECLARE_EXTERN[
 void print_my_token (void);
@@ -141,6 +140,7 @@ void print_my_token (void);
   int val;
 };
 %{
+#include <stdio.h>
 void
 print_my_token (void)
 {
@@ -209,7 +209,7 @@ exp: '(' exp ')' | NUM ;
 AT_BISON_OPTION_POPDEFS
 
 AT_BISON_CHECK([-v -o input.c input.y], 0, [],
-[[input.y:6.8-14: warning: symbol "<=" used more than once as a literal string
+[[input.y:6.8-14: warning: symbol "<=" used more than once as a literal string [-Wother]
 ]])
 
 AT_CLEANUP
@@ -263,11 +263,11 @@ AT_CHECK([cat input.output], [],
 
     0 $accept: expr $end
 
-    1 $@1: /* empty */
+    1 $@1: %empty
 
     2 expr: 'a' $@1 'b'
 
-    3 $@2: /* empty */
+    3 $@2: %empty
 
     4 expr: $@2 'c'
 
@@ -373,11 +373,14 @@ AT_DATA([input.y],
 %token  <operator>  LE 134  "<="
 %left  OR  "<="
 %%
-exp: ;
+exp: %empty;
 %%
 ]])
 
-AT_BISON_CHECK([-v -o input.c input.y])
+AT_BISON_CHECK([-v -Wall -o input.c input.y], 0, [],
+[[input.y:1.29-32: warning: useless precedence and associativity for "||" [-Wprecedence]
+input.y:2.29-32: warning: useless precedence and associativity for "<=" [-Wprecedence]
+]])
 
 AT_CLEANUP
 
@@ -446,8 +449,6 @@ AT_BISON_OPTION_PUSHDEFS
 # Bison managed, when fed with '%token 'f' "f"' to #define 'f'!
 AT_DATA_GRAMMAR([input.y],
 [%{
-#include <stdlib.h>
-#include <stdio.h>
 ]AT_YYERROR_DECLARE[
 ]AT_YYLEX_DECLARE[
 %}
@@ -464,12 +465,7 @@ exp: "a" "\\\'\?\"\a\b\f\n\r\t\v\001\201\x001\x000081??!";
 %%
 ]AT_YYERROR_DEFINE[
 ]AT_YYLEX_DEFINE([{ SPECIAL }])[
-
-int
-main (void)
-{
-  return yyparse ();
-}
+]AT_MAIN_DEFINE[
 ]])
 AT_BISON_OPTION_POPDEFS
 
@@ -478,14 +474,14 @@ AT_BISON_OPTION_POPDEFS
 # C-string literal.  Also notice that unnecessary escaping, such as "\?", from
 # the user specification is eliminated.
 AT_BISON_CHECK([-o input.c input.y], [[0]], [[]],
-[[input.y:22.8-14: warning: symbol SPECIAL redeclared
-input.y:22.8-63: warning: symbol "\\'?\"\a\b\f\n\r\t\v\001\201\001\201??!" used more than once as a literal string
+[[input.y:22.8-14: warning: symbol SPECIAL redeclared [-Wother]
+input.y:22.8-63: warning: symbol "\\'?\"\a\b\f\n\r\t\v\001\201\001\201??!" used more than once as a literal string [-Wother]
 ]])
 AT_BISON_CHECK([-fcaret -o input.c input.y], [[0]], [[]],
-[[input.y:22.8-14: warning: symbol SPECIAL redeclared
+[[input.y:22.8-14: warning: symbol SPECIAL redeclared [-Wother]
  %token SPECIAL "\\\'\?\"\a\b\f\n\r\t\v\001\201\x001\x000081??!"
         ^^^^^^^
-input.y:22.8-63: warning: symbol "\\'?\"\a\b\f\n\r\t\v\001\201\001\201??!" used more than once as a literal string
+input.y:22.8-63: warning: symbol "\\'?\"\a\b\f\n\r\t\v\001\201\001\201??!" used more than once as a literal string [-Wother]
  %token SPECIAL "\\\'\?\"\a\b\f\n\r\t\v\001\201\x001\x000081??!"
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 ]])
@@ -546,7 +542,7 @@ AT_SETUP([Web2c Report])
 AT_KEYWORDS([report])
 
 AT_DATA([input.y],
-[[%token       undef_id_tok const_id_tok
+[[%token        undef_id_tok const_id_tok
 
 %start CONST_DEC_PART
 \f
@@ -556,12 +552,12 @@ CONST_DEC_PART:
         ;
 
 CONST_DEC_LIST:
-         CONST_DEC
+          CONST_DEC
         | CONST_DEC_LIST CONST_DEC
         ;
 
 CONST_DEC:
-         { } undef_id_tok '=' const_id_tok ';'
+          { } undef_id_tok '=' const_id_tok ';'
         ;
 %%
 ]])
@@ -577,7 +573,7 @@ AT_CHECK([cat input.output], 0,
     2 CONST_DEC_LIST: CONST_DEC
     3               | CONST_DEC_LIST CONST_DEC
 
-    4 $@1: /* empty */
+    4 $@1: %empty
 
     5 CONST_DEC: $@1 undef_id_tok '=' const_id_tok ';'
 
@@ -725,7 +721,7 @@ AT_KEYWORDS([report])
 AT_DATA([input.y],
 [[%%
 statement:  struct_stat;
-struct_stat:  /* empty. */ | if else;
+struct_stat:  %empty | if else;
 if: "if" "const" "then" statement;
 else: "else" statement;
 %%
@@ -767,15 +763,6 @@ AT_CHECK([[cat tables.c]], 0,
        2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
        5,     6
 };
-static const yytype_uint8 yyprhs[] =
-{
-       0,     0,     3,     5,     6,     9,    14
-};
-static const yytype_int8 yyrhs[] =
-{
-       8,     0,    -1,     9,    -1,    -1,    10,    11,    -1,     3,
-       4,     5,     8,    -1,     6,     8,    -1
-};
 static const yytype_uint8 yyrline[] =
 {
        0,     2,     2,     3,     3,     4,     5
@@ -789,32 +776,24 @@ static const yytype_uint16 yytoknum[] =
 {
        0,   256,   257,   258,   259,   260,   261
 };
-static const yytype_uint8 yyr1[] =
-{
-       0,     7,     8,     9,     9,    10,    11
-};
-static const yytype_uint8 yyr2[] =
+static const yytype_int8 yypact[] =
 {
-       0,     2,     1,     0,     2,     4,     2
+      -2,    -1,     4,    -8,     0,     2,    -8,    -2,    -8,    -2,
+      -8,    -8
 };
 static const yytype_uint8 yydefact[] =
 {
        3,     0,     0,     2,     0,     0,     1,     3,     4,     3,
        6,     5
 };
-static const yytype_int8 yydefgoto[] =
-{
-      -1,     2,     3,     4,     8
-};
-static const yytype_int8 yypact[] =
-{
-      -2,    -1,     4,    -8,     0,     2,    -8,    -2,    -8,    -2,
-      -8,    -8
-};
 static const yytype_int8 yypgoto[] =
 {
       -8,    -7,    -8,    -8,    -8
 };
+static const yytype_int8 yydefgoto[] =
+{
+      -1,     2,     3,     4,     8
+};
 static const yytype_uint8 yytable[] =
 {
       10,     1,    11,     5,     6,     0,     7,     9
@@ -828,6 +807,14 @@ static const yytype_uint8 yystos[] =
        0,     3,     8,     9,    10,     4,     0,     6,    11,     5,
        8,     8
 };
+static const yytype_uint8 yyr1[] =
+{
+       0,     7,     8,     9,     9,    10,    11
+};
+static const yytype_uint8 yyr2[] =
+{
+       0,     2,     1,     0,     2,     4,     2
+};
 ]])
 
 AT_CLEANUP
@@ -853,7 +840,6 @@ m4_define([_AT_DATA_DANCER_Y],
 }
 $1
 %token ARROW INVALID NUMBER STRING DATA
-%defines
 %verbose
 %error-verbose
 /* Grammar follows */
@@ -883,7 +869,7 @@ type: DATA
    | INVALID
    ;
 
-body: /* empty */
+body: %empty
    | body member
    ;
 
@@ -897,23 +883,7 @@ member: STRING
 %%
 ]AT_YYERROR_DEFINE[
 ]AT_YYLEX_DEFINE([":"])[
-]AT_LALR1_CC_IF(
-[int
-yyparse ()
-{
-  yy::parser parser;
-#if YYDEBUG
-  parser.set_debug_level (YYDEBUG);
-#endif
-  return parser.parse ();
-}
-])[
-
-int
-main (void)
-{
-  return yyparse ();
-}
+]AT_MAIN_DEFINE[
 ]])
 ])# _AT_DATA_DANCER_Y
 
@@ -947,21 +917,19 @@ AT_CHECK_DANCER([%skeleton "lalr1.cc"])
 # --------------------------------
 m4_define([_AT_DATA_EXPECT2_Y],
 [AT_DATA_GRAMMAR([expect2.y],
-[[%{
-static int yylex (]AT_LALR1_CC_IF([int *], [void]));
-AT_LALR1_CC_IF([],
-[[#include <stdio.h>
-#include <stdlib.h>
+[%{
+static int yylex (AT_LALR1_CC_IF([int *], [void]));
+AT_LALR1_CC_IF([[#include <cstdlib>]],
+[[
 ]AT_YYERROR_DECLARE])[
 %}
 $1
-%defines
 %error-verbose
 %token A 1000
 %token B
 
 %%
-program: /* empty */
+program: %empty
  | program e ';'
  | program error ';';
 
@@ -992,12 +960,7 @@ yylex (]AT_LALR1_CC_IF([int *lval], [void])[)
   assert (toknum < sizeof tokens / sizeof *tokens);
   return tokens[toknum++];
 }
-
-int
-main (void)
-{
-  return yyparse ();
-}
+]AT_MAIN_DEFINE[
 ]])
 ])# _AT_DATA_EXPECT2_Y
 
@@ -1031,22 +994,20 @@ AT_SETUP([Braced code in declaration in rules section])
 
 # Bison once mistook braced code in a declaration in the rules section to be a
 # rule action.
-AT_BISON_OPTION_PUSHDEFS
+AT_BISON_OPTION_PUSHDEFS([%debug])
 AT_DATA_GRAMMAR([input.y],
 [[%{
-#include <stdio.h>
 ]AT_YYERROR_DECLARE[
 ]AT_YYLEX_DECLARE[
 %}
-
+%debug
 %error-verbose
-
 %%
 
 start:
   {
     printf ("Bison would once convert this action to a midrule because of the"
-           " subsequent braced code.\n");
+            " subsequent braced code.\n");
   }
   ;
 
@@ -1056,19 +1017,13 @@ start:
 %%
 ]AT_YYERROR_DEFINE[
 ]AT_YYLEX_DEFINE(["a"])[
-
-int
-main (void)
-{
-  yydebug = 1;
-  return !yyparse ();
-}
+]AT_MAIN_DEFINE[
 ]])
 AT_BISON_OPTION_POPDEFS
 
-AT_BISON_CHECK([-t -o input.c input.y])
+AT_BISON_CHECK([-o input.c input.y])
 AT_COMPILE([input])
-AT_PARSER_CHECK([./input], 0,
+AT_PARSER_CHECK([./input --debug], 1,
 [[Bison would once convert this action to a midrule because of the subsequent braced code.
 ]],
 [[Starting parse
@@ -1107,7 +1062,7 @@ start: 'a' "A" 'b';
 %token 'a' "A";
 ]])
 
-AT_BISON_CHECK([-t -o input.c input.y])
+AT_BISON_CHECK([-o input.c input.y])
 
 AT_CLEANUP
 
@@ -1164,11 +1119,10 @@ AT_SETUP([[Token number in precedence declaration]])
 # we lost this in Bison 1.50.
 AT_BISON_OPTION_PUSHDEFS
 AT_DATA_GRAMMAR([input.y],
-[[%{
-  #include <stdio.h>
+[[%code {
   ]AT_YYERROR_DECLARE[
   ]AT_YYLEX_DECLARE[
-%}
+}
 
 %error-verbose
 %right END 0
@@ -1189,18 +1143,14 @@ sr_conflict:
 
 ]AT_YYERROR_DEFINE[
 ]AT_YYLEX_DEFINE([{ 1, 2, 3, 0 }])[
-
-int
-main (void)
-{
-  return yyparse ();
-}
+]AT_MAIN_DEFINE[
 ]])
 AT_BISON_OPTION_POPDEFS
 
-AT_BISON_CHECK([[-o input.c input.y]], [[0]],,
-[[input.y:23.5-19: warning: rule useless in parser due to conflicts: start: start
-input.y:27.5-19: warning: rule useless in parser due to conflicts: sr_conflict: TK2 "tok alias"
+AT_BISON_CHECK([[-Wall -o input.c input.y]], [[0]],,
+[[input.y:24.5-19: warning: rule useless in parser due to conflicts [-Wother]
+input.y:28.5-19: warning: rule useless in parser due to conflicts [-Wother]
+input.y:18.7-9: warning: useless precedence and associativity for TK1 [-Wprecedence]
 ]])
 AT_COMPILE([[input]])
 AT_PARSER_CHECK([[./input]])
@@ -1218,8 +1168,9 @@ AT_CLEANUP
 
 AT_SETUP([[parse-gram.y: LALR = IELR]])
 
-# Avoid differences in synclines by telling bison that the output files
-# have the same name.
+# Avoid tests/bison's dark magic by processing a local copy of the
+# grammar.  Avoid differences in synclines by telling bison that the
+# output files have the same name.
 [cp $abs_top_srcdir/src/parse-gram.y input.y]
 AT_BISON_CHECK([[-o input.c -Dlr.type=lalr input.y]])
 [mv input.c lalr.c]
@@ -1233,22 +1184,21 @@ AT_CLEANUP
 
 
 
-## --------------------------------------- ##
-## %error-verbose and YYSTACK_USE_ALLOCA.  ##
-## --------------------------------------- ##
+## -------------------------------------------- ##
+## parse.error=verbose and YYSTACK_USE_ALLOCA.  ##
+## -------------------------------------------- ##
 
-AT_SETUP([[%error-verbose and YYSTACK_USE_ALLOCA]])
+AT_SETUP([[parse.error=verbose and YYSTACK_USE_ALLOCA]])
 
 AT_BISON_OPTION_PUSHDEFS
 AT_DATA_GRAMMAR([input.y],
 [[%code {
-  #include <stdio.h>
   ]AT_YYERROR_DECLARE[
   ]AT_YYLEX_DECLARE[
   #define YYSTACK_USE_ALLOCA 1
 }
 
-%error-verbose
+%define parse.error verbose
 
 %%
 
@@ -1281,15 +1231,11 @@ syntax_error:
 %%
 
 ]AT_YYERROR_DEFINE[
-/* Induce two syntax error messages (which requires full error
-   recovery by shifting 3 tokens) in order to detect any loss of the
-   reallocated buffer.  */
+  /* Induce two syntax error messages (which requires full error
+     recovery by shifting 3 tokens) in order to detect any loss of the
+     reallocated buffer.  */
 ]AT_YYLEX_DEFINE(["abc"])[
-int
-main (void)
-{
-  return yyparse ();
-}
+]AT_MAIN_DEFINE[
 ]])
 AT_BISON_OPTION_POPDEFS
 
@@ -1304,9 +1250,9 @@ AT_CLEANUP
 
 
 
-## ------------------------- ##
-## %error-verbose overflow.  ##
-## ------------------------- ##
+## ------------------------------ ##
+## parse.error=verbose overflow.  ##
+## ------------------------------ ##
 
 # Imagine the case where YYSTACK_ALLOC_MAXIMUM = YYSIZE_MAXIMUM and an
 # invocation of yysyntax_error has caused yymsg_alloc to grow to exactly
@@ -1316,11 +1262,11 @@ AT_CLEANUP
 # size calculation would return YYSIZE_MAXIMUM to yyparse.  Then,
 # yyparse would invoke yyerror using the old contents of yymsg.
 
-AT_SETUP([[%error-verbose overflow]])
+AT_SETUP([[parse.error=verbose overflow]])
+
 AT_BISON_OPTION_PUSHDEFS
 AT_DATA_GRAMMAR([input.y],
 [[%code {
-  #include <stdio.h>
   ]AT_YYERROR_DECLARE[
   ]AT_YYLEX_DECLARE[
 
@@ -1341,7 +1287,7 @@ AT_DATA_GRAMMAR([input.y],
   #define YYMAXDEPTH 100
 }
 
-%error-verbose
+%define parse.error verbose
 
 %%
 
@@ -1389,8 +1335,8 @@ syntax_error2:
 %%
 
 ]AT_YYERROR_DEFINE[
-/* Induce two syntax error messages (which requires full error
-   recovery by shifting 3 tokens).  */
+  /* Induce two syntax error messages (which requires full error
+     recovery by shifting 3 tokens).  */
 ]AT_YYLEX_DEFINE(["abc"])[
 int
 main (void)
@@ -1430,17 +1376,16 @@ AT_SETUP([[LAC: Exploratory stack]])
 
 m4_pushdef([AT_LAC_CHECK], [
 
-AT_BISON_OPTION_PUSHDEFS([$1])
+AT_BISON_OPTION_PUSHDEFS([%debug $1])
 
 AT_DATA_GRAMMAR([input.y],
 [[%code {
-  #include <stdio.h>
   ]AT_YYERROR_DECLARE[
   int yylex (]AT_PURE_IF([[YYSTYPE *]], [[void]])[);
 }
-
+%debug
 ]$1[
-%error-verbose
+%define parse.error verbose
 %token 'c'
 
 %%
@@ -1465,21 +1410,16 @@ yylex (]AT_PURE_IF([[YYSTYPE *v]], [[void]])[)
   return *input++;
 }
 
-int
-main (void)
-{
-  yydebug = 1;
-  return yyparse ();
-}
+]AT_MAIN_DEFINE[
 ]])
 
 AT_BISON_CHECK([[-Dparse.lac=full -Dparse.lac.es-capacity-initial=1 \
                  -Dparse.lac.memory-trace=full \
-                 -t -o input.c input.y]], [[0]], [],
-[[input.y: conflicts: 21 shift/reduce
+                 -o input.c input.y]], [[0]], [],
+[[input.y: warning: 21 shift/reduce conflicts [-Wconflicts-sr]
 ]])
 AT_COMPILE([[input]])
-AT_PARSER_CHECK([[./input > stdout.txt 2> stderr.txt]], [[1]])
+AT_PARSER_CHECK([[./input --debug > stdout.txt 2> stderr.txt]], [[1]])
 
 # Make sure syntax error doesn't forget that 'a' is expected.  It would
 # be forgotten without lookahead correction.
@@ -1523,15 +1463,14 @@ AT_CLEANUP
 AT_SETUP([[LAC: Memory exhaustion]])
 
 m4_pushdef([AT_LAC_CHECK],
-[AT_BISON_OPTION_PUSHDEFS
+[AT_BISON_OPTION_PUSHDEFS([%debug])
 AT_DATA_GRAMMAR([input.y],
 [[%code {
-  #include <stdio.h>
   ]AT_YYERROR_DECLARE[
   ]AT_YYLEX_DECLARE[
   #define YYMAXDEPTH 8
 }
-
+%debug
 %error-verbose
 
 %%
@@ -1542,17 +1481,12 @@ A: /*empty*/ | 'a' ;
 %%
 ]AT_YYERROR_DEFINE[
 ]AT_YYLEX_DEFINE(["$1"])[
-int
-main (void)
-{
-  yydebug = 1;
-  return yyparse ();
-}
+]AT_MAIN_DEFINE[
 ]])
 
 AT_BISON_CHECK([[-Dparse.lac=full -Dparse.lac.es-capacity-initial=1 \
-                 -t -o input.c input.y]], [[0]], [],
-[[input.y: conflicts: 8 shift/reduce
+                 -o input.c input.y]], [[0]], [],
+[[input.y: warning: 8 shift/reduce conflicts [-Wconflicts-sr]
 ]])
 AT_COMPILE([[input]])
 AT_BISON_OPTION_POPDEFS
@@ -1560,7 +1494,7 @@ AT_BISON_OPTION_POPDEFS
 
 # Check for memory exhaustion during parsing.
 AT_LAC_CHECK([])
-AT_PARSER_CHECK([[./input]], [[2]], [],
+AT_PARSER_CHECK([[./input --debug]], [[2]], [],
 [[Starting parse
 Entering state 0
 Reading a token: Now at end of input.
@@ -1574,7 +1508,7 @@ Stack now 0
 # Induce an immediate syntax error with an undefined token, and check
 # for memory exhaustion while building syntax error message.
 AT_LAC_CHECK([z], [[0]])
-AT_PARSER_CHECK([[./input]], [[2]], [],
+AT_PARSER_CHECK([[./input --debug]], [[2]], [],
 [[Starting parse
 Entering state 0
 Reading a token: Next token is token $undefined ()
@@ -1605,27 +1539,22 @@ AT_CLEANUP
 m4_pushdef([AT_TEST],
 [AT_SETUP([[Lex and parse params: $1]])
 
+## FIXME: Improve parsing of parse-param.
 AT_BISON_OPTION_PUSHDEFS([%locations %skeleton "$1" %parse-param { int x } %parse-param { int y }])
 
-## FIXME: Improve parsing of parse-param and use the generated
-## yyerror.
 AT_DATA_GRAMMAR([input.y],
-[[%defines
-%locations
+[[%locations
 %skeleton "$1"
 %union { int ival; }
 %parse-param { int x }
 // Spaces, tabs, and new lines.
 %parse-param { @&t@
-        int y   @&t@
+@tb@ int y@tb@ @&t@
          @&t@
  @&t@
 }
 
 %{
-#include <stdio.h>
-#include <stdlib.h>
-
   ]AT_YYERROR_DECLARE[
   ]AT_YYLEX_DECLARE[
 %}
@@ -1648,7 +1577,7 @@ yyparse (int x, int y)
 int
 main (void)
 {
-  return !!yyparse(1, 2);
+  return yyparse(1, 2);
 }
 ]])
 
@@ -1667,3 +1596,33 @@ AT_TEST([lalr1.cc])
 AT_TEST([glr.cc])
 
 m4_popdef([AT_TEST])
+
+
+## ----------------------- ##
+## stdio.h is not needed.  ##
+## ----------------------- ##
+
+# At some point, by accident, yy_location_print_ was using fprintf and
+# FILE which are from stdio.h, which we do not require.
+AT_SETUP([[stdio.h is not needed]])
+
+AT_BISON_OPTION_PUSHDEFS
+
+AT_DATA_GRAMMAR([input.y],
+[[%locations
+%code
+{
+  static int yylex (void) { return 0; }
+  static void yyerror (const char* msg) { (void) msg; }
+}
+%%
+exp: {}
+%%
+]AT_MAIN_DEFINE[
+]])
+
+AT_FULL_COMPILE([input])
+
+AT_BISON_OPTION_POPDEFS
+
+AT_CLEANUP
index 0e6b80f9dac39ff2259c4518751683ff41a95517..fadbe6871210bdb0002e56a7838d273592230d17 100644 (file)
@@ -29,25 +29,25 @@ m4_define([AT_EXTRACT_SETS],
    :null
    p
    n
-   /^[  ]*$/ !b null
+   /^ *$/ !b null
 }
 /^FIRSTS$/ {
    :firsts
    p
    n
-   /^[  ]*$/ !b firsts
+   /^ *$/ !b firsts
 }
 /^FDERIVES$/ {
    :fderiv
    p
    n
-   /^[  ]*$/ !b fderiv
+   /^ *$/ !b fderiv
 }
 /^DERIVES$/ {
    :deriv
    p
    n
-   /^[  ]*$/ !b deriv
+   /^ *$/ !b deriv
 }
 ]])
 AT_CHECK([sed -f extract.sed $1], 0, [stdout])
@@ -82,28 +82,28 @@ AT_BISON_CHECK([[--trace=sets input.y]], [], [], [stderr])
 AT_EXTRACT_SETS([stderr], [sets])
 AT_CHECK([[cat sets]], [],
 [[DERIVES
-       $accept derives
-                 0  e $end
-       e derives
-                 1  'e'
-                 2  /* empty */
+  $accept derives
+      0  e $end
+  e derives
+      1  'e'
+      2  %empty
 NULLABLE
-       $accept: no
-       e: yes
+  $accept: no
+  e: yes
 FIRSTS
-       $accept firsts
-               $accept
-               e
-       e firsts
-               e
+  $accept firsts
+    $accept
+    e
+  e firsts
+    e
 FDERIVES
-       $accept derives
-                 0  e $end
-                 1  'e'
-                 2  /* empty */
-       e derives
-                 1  'e'
-                 2  /* empty */
+  $accept derives
+      0  e $end
+      1  'e'
+      2  %empty
+  e derives
+      1  'e'
+      2  %empty
 ]])
 
 AT_CLEANUP
@@ -113,7 +113,7 @@ AT_CLEANUP
 ## Broken Closure.  ##
 ## ---------------- ##
 
-# TC was once broken during a massive `simplification' of the code.
+# TC was once broken during a massive 'simplification' of the code.
 # It resulted in bison dumping core on the following grammar (the
 # computation of FIRSTS uses TC).  It managed to produce a pretty
 # exotic closure:
@@ -164,7 +164,7 @@ h: 'h';
 
 AT_BISON_CHECK([[--trace=sets input.y]], [], [], [stderr])
 
-AT_CHECK([[sed -n 's/[  ]*$//;/^RTC: Firsts Output BEGIN/,/^RTC: Firsts Output END/p' stderr]], [],
+AT_CHECK([[sed -n 's/[   ]*$//;/^RTC: Firsts Output BEGIN/,/^RTC: Firsts Output END/p' stderr]], [],
 [[RTC: Firsts Output BEGIN
 
    012345678
@@ -212,43 +212,43 @@ AT_BISON_CHECK([[--trace=sets input.y]], [], [], [stderr])
 AT_EXTRACT_SETS([stderr], [sets])
 AT_CHECK([[cat sets]], [],
 [[DERIVES
-       $accept derives
-                 0  exp $end
-       exp derives
-                 1  exp '<' exp
-                 2  exp '>' exp
-                 3  exp '+' exp
-                 4  exp '-' exp
-                 5  exp '^' exp
-                 6  exp '=' exp
-                 7  "exp"
+  $accept derives
+      0  exp $end
+  exp derives
+      1  exp '<' exp
+      2  exp '>' exp
+      3  exp '+' exp
+      4  exp '-' exp
+      5  exp '^' exp
+      6  exp '=' exp
+      7  "exp"
 NULLABLE
-       $accept: no
-       exp: no
+  $accept: no
+  exp: no
 FIRSTS
-       $accept firsts
-               $accept
-               exp
-       exp firsts
-               exp
+  $accept firsts
+    $accept
+    exp
+  exp firsts
+    exp
 FDERIVES
-       $accept derives
-                 0  exp $end
-                 1  exp '<' exp
-                 2  exp '>' exp
-                 3  exp '+' exp
-                 4  exp '-' exp
-                 5  exp '^' exp
-                 6  exp '=' exp
-                 7  "exp"
-       exp derives
-                 1  exp '<' exp
-                 2  exp '>' exp
-                 3  exp '+' exp
-                 4  exp '-' exp
-                 5  exp '^' exp
-                 6  exp '=' exp
-                 7  "exp"
+  $accept derives
+      0  exp $end
+      1  exp '<' exp
+      2  exp '>' exp
+      3  exp '+' exp
+      4  exp '-' exp
+      5  exp '^' exp
+      6  exp '=' exp
+      7  "exp"
+  exp derives
+      1  exp '<' exp
+      2  exp '>' exp
+      3  exp '+' exp
+      4  exp '-' exp
+      5  exp '^' exp
+      6  exp '=' exp
+      7  "exp"
 ]])
 
 AT_CLEANUP
@@ -263,7 +263,7 @@ AT_CLEANUP
 # In some weird cases Bison could compute an incorrect final state
 # number.  This happens only if the $end token is used in the user
 # grammar, which is a very suspicious accidental feature introduced as
-# a side effect of allowing the user to name $end using `%token END 0
+# a side effect of allowing the user to name $end using '%token END 0
 # "end of file"'.
 
 AT_SETUP([Accept])
@@ -288,15 +288,15 @@ mv stdout expout
 # Get the final state in the report, from the "accept" action..
 AT_CHECK([sed -n '
            /^State \(.*\)/{
-            s//final state \1/
-            x
-          }
-          / accept/{
-            x
-            p
-            q
-          }
-       ' input.output],
-       0, [expout])
+             s//final state \1/
+             x
+           }
+           / accept/{
+             x
+             p
+             q
+           }
+        ' input.output],
+        0, [expout])
 
 AT_CLEANUP
index 0afe1037b94ff0dcaa101e07193e5b8ee54ed866..68a004ec5109dc0f5e66e33956ed8c16d4064892 100644 (file)
@@ -106,12 +106,7 @@ yylex (void)
 {
   return 'a';
 }
-
-int
-main (void)
-{
-  return yyparse ();
-}
+]AT_MAIN_DEFINE[
 ]])
 
 AT_DATA_GRAMMAR([[input-cmd-line.y]],
@@ -191,8 +186,8 @@ start: ;
 ]])
 
 AT_BISON_CHECK([[input1.y]], [[1]], [[]],
-[[input1.y: warning: foow fubar
-foow.y:2.3-5.3: warning: foowat fubar
+[[input1.y: warning: foow fubar [-Wother]
+foow.y:2.3-5.3: warning: foowat fubar [-Wother]
 input1.y: error: fooc fubar
 fooc.y:1.1-10.5: error: foocat fubar
 input1.y: fatal error: foof fubar
@@ -281,7 +276,7 @@ start: ;
 ]])
 
 AT_BISON_CHECK([[input2.y]], [[1]], [[]],
-[[input2.y: warning: morning
+[[input2.y: warning: morning [-Wother]
 foo.y:1.5-6: fatal error: M4 should exit immediately here
 ]])
 
index 05f205755aa320d78807dfcdd55cd321ff84726c..99f9df90a3bcab64d7341bedc1f28415398b29e1 100644 (file)
@@ -23,7 +23,7 @@ AT_BANNER([[User Actions.]])
 # --------------------------
 # Compile FILE expecting an error, and save in the file stdout the
 # normalized output.  Ignore the exit status, since some compilers
-# (e.g. c89 on IRIX 6.5) trigger warnings on `#error', instead of
+# (e.g. c89 on IRIX 6.5) trigger warnings on '#error', instead of
 # errors.
 m4_define([AT_SYNCLINES_COMPILE],
 [AT_CHECK([$CC $CFLAGS $CPPFLAGS -c $1], [ignore], [], [stderr])
@@ -268,7 +268,7 @@ m4_popdef([AT_TEST])
 ## ----------- ##
 
 m4_pushdef([AT_TEST],
-[AT_SETUP([%no-lines])
+[AT_SETUP([%no-lines: $1])
 
 AT_BISON_OPTION_PUSHDEFS([%skeleton "$1" %defines])
 AT_DATA_GRAMMAR([input.y],
index 6f3a221b33d0083d298c27cc511e3e352a6db0a3..4c99513212b3d61280c17ddef142ff9fd2277524 100644 (file)
@@ -1,4 +1,4 @@
-# Test suite for GNU Bison.                            -*- Autotest -*-
+# Test suite for GNU Bison.                             -*- Autotest -*-
 
 # Copyright (C) 2000-2004, 2006-2007, 2009-2013 Free Software
 # Foundation, Inc.
@@ -35,6 +35,9 @@ m4_include([sets.at])
 # Testing grammar reduction.
 m4_include([reduce.at])
 
+# Testing conflicts detection and resolution.
+m4_include([conflicts.at])
+
 # Testing that #lines are correct.
 m4_include([synclines.at])
 
@@ -44,8 +47,8 @@ m4_include([headers.at])
 # Testing that user actions are properly performed.
 m4_include([actions.at])
 
-# Testing conflicts detection and resolution.
-m4_include([conflicts.at])
+# Testing semantic types support.
+m4_include([types.at])
 
 # Fulling testing (compilation and execution of the parser) on calc.
 m4_include([calc.at])
index 56a1fa81c61e7bf6f2cb31fc3e647829068c338b..5489e9199487d87f124f603f4f1898b34f383784 100644 (file)
@@ -91,9 +91,9 @@ for my $size (1 .. $max)
   {
     use Text::Wrap;
     print wrap ("| ", "   ",
-               (map { "\"$_\"" } (1 .. $size)),
-               " END \n"),
-                 "    { \$\$ = $size; }\n";
+                (map { "\"$_\"" } (1 .. $size)),
+                " END \n"),
+                  "    { \$\$ = $size; }\n";
   };
 print ";\n";
 
@@ -115,12 +115,7 @@ yylex (void)
     }
   return inner++;
 }
-int
-main (void)
-{
-  yydebug = !!getenv ("YYDEBUG");
-  return yyparse ();
-}
+]AT_MAIN_DEFINE[
 EOF
 ]])
 AT_BISON_OPTION_POPDEFS
@@ -188,7 +183,7 @@ EOF
 use Text::Wrap;
 print
   wrap ("exp: ", "  ",
-       (map { "\"$_\"" } (1 .. $max)), ";"),
+        (map { "\"$_\"" } (1 .. $max)), ";"),
   "\n";
 
 print <<\EOF;
@@ -204,13 +199,7 @@ yylex (void)
   assert (counter++ == MAX + 1);
   return 0;
 }
-
-int
-main (void)
-{
-  yydebug = !!getenv ("YYDEBUG");
-  return yyparse ();
-}
+]AT_MAIN_DEFINE[
 EOF
 ]])
 
@@ -288,8 +277,8 @@ EOF
 
 print
   wrap ("%type <val> ",
-       "            ",
-       map { "n$_" } (1 .. $max)),
+        "            ",
+        map { "n$_" } (1 .. $max)),
   "\n";
 
 print "%token\n";
@@ -342,12 +331,7 @@ yylex (void)
   return counter++;
 }
 
-int
-main (void)
-{
-  yydebug = !!getenv ("YYDEBUG");
-  return yyparse ();
-}
+]AT_MAIN_DEFINE[
 EOF
 ]])
 
diff --git a/tests/types.at b/tests/types.at
new file mode 100644 (file)
index 0000000..6275903
--- /dev/null
@@ -0,0 +1,230 @@
+# Value type.                                     -*- Autotest -*-
+
+# Copyright (C) 2013 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/>.
+
+AT_BANNER([[Value type tests.]])
+
+
+## ----------------------------------- ##
+## %union vs. %define api.value.type.  ##
+## ----------------------------------- ##
+
+AT_SETUP([[%union vs. %define api.value.type]])
+
+AT_DATA([[input.y]],
+[[%union { int ival; }
+%define api.value.type union-directive
+%%
+exp: %empty;
+]])
+
+AT_BISON_CHECK([[input.y]], [[1]], [[]],
+[[input.y:2.9-22: error: '%union' and '%define api.value.type' cannot be used together
+]])
+
+AT_CLEANUP
+
+## ---------------------------------------- ##
+## %yacc vs. %define api.value.type union.  ##
+## ---------------------------------------- ##
+
+AT_SETUP([[%yacc vs. %define api.value.type union]])
+
+AT_DATA([[input.y]],
+[[%yacc
+%define api.value.type union
+%%
+exp: %empty;
+]])
+
+AT_BISON_CHECK([[input.y]], [[1]], [[]],
+[[input.y:2.9-22: error: '%yacc' and '%define api.value.type "union"' cannot be used together
+]])
+
+AT_CLEANUP
+
+
+## ---------------- ##
+## api.value.type.  ##
+## ---------------- ##
+
+# AT_TEST($1: BISON-DIRECTIVES,
+#         $2: MORE-BISON-DIRECTIVES,
+#         $3: PARSER-ACTION,
+#         $4: INPUT, $5: SCANNER-ACTION,
+#         $6: RESULT)
+# --------------------------------------
+# Compile the grammar and check the expected result.
+# BISON-DIRECTIVES are passed to AT_SETUP, contrary to MORE-BISON-DIRECTIVES.
+m4_pushdef([AT_TEST],
+[
+AT_SETUP([$1])
+AT_KEYWORDS([api.value.type])
+AT_BISON_OPTION_PUSHDEFS([%debug $1 $2])
+AT_DATA_GRAMMAR([test.y],
+[[%debug
+
+%code
+{
+# include <stdio.h>
+# include <stdlib.h>
+]AT_YYERROR_DECLARE[
+]AT_YYLEX_DECLARE[
+}
+
+]$1[
+]$2[
+
+%%
+
+start: $3;
+
+%%
+]AT_YYERROR_DEFINE[
+]AT_YYLEX_DEFINE([$4], [$5])[
+]AT_MAIN_DEFINE[
+]])
+
+AT_FULL_COMPILE([[test]])
+AT_PARSER_CHECK([./test], 0, [$6
+], [stderr])
+AT_BISON_OPTION_POPDEFS
+AT_CLEANUP
+])
+
+m4_foreach([b4_skel], [[yacc.c], [glr.c], [lalr1.cc], [glr.cc]],
+ [# A built-in type.
+  AT_TEST([%skeleton "]b4_skel["
+           %define api.value.type {double}],
+          [],
+          ['1' '2' { printf ("%2.1f\n", $1 + $2); }],
+          ["12"],
+          [AT_VAL = (res - '0') / 10.0],
+          [0.3])
+
+  # A typedef which looks like a Bison keyword, but it's using braces.
+  AT_TEST([%skeleton "]b4_skel["
+           %define api.value.type {variant}],
+          [%code requires { typedef double variant; }],
+          ['1' '2' { printf ("%2.1f\n", $1 + $2); }],
+          ["12"],
+          [AT_VAL = (res - '0') / 10.0],
+          [0.3])
+
+  # A user defined struct.
+  AT_TEST([%skeleton "]b4_skel["
+           %define api.value.type {struct foo}],
+          [%code requires { struct foo { float fval; int ival; }; }],
+          ['1' '2'
+             { printf ("%d %2.1f\n", $1.ival + $2.ival, $1.fval + $2.fval); }],
+          ["12"],
+          [AT_VAL.ival = (res - '0') * 10;
+           AT_VAL.fval = (res - '0') / 10.f],
+          [30 0.3])
+
+  # A user defined struct that uses pointers.
+  AT_TEST([%skeleton "]b4_skel["
+           %define api.value.type {struct bar}],
+          [%code requires
+           {
+             struct u
+             {
+               int ival;
+             };
+             struct bar
+             {
+               struct u *up;
+             };
+           }
+           %token <up->ival> '1' '2'
+           %printer { ]AT_SKEL_CC_IF([[yyoutput << $$]],
+                                     [[fprintf (yyo, "%d", $$)]])[; } <up->ival>
+           ],
+          ['1' '2'
+           {
+             printf ("%d %d\n", $1, $<up->ival>2);
+             free ($<up>1);
+             free ($<up>2);
+           }],
+          ["12"],
+          [AT_VAL.up = (struct u *) malloc (sizeof *AT_VAL.up);
+           assert (AT_VAL.up);
+           AT_VAL.up->ival = res - '0';],
+          [1 2])
+
+  # A user defined union.
+  AT_TEST([%skeleton "]b4_skel["
+           %define api.value.type {union foo}],
+          [%code requires { union foo { float fval; int ival; }; }],
+          ['1' '2' { printf ("%d %2.1f\n", $1.ival, $2.fval); }],
+          ["12"],
+          [if (res == '1')
+             AT_VAL.ival = 10;
+           else
+             AT_VAL.fval = .2f],
+          [10 0.2])
+
+  # A %union.
+  AT_TEST([%skeleton "]b4_skel["
+           %union { float fval; int ival; };],
+          [%token <ival> '1';
+           %token <fval> '2';],
+          ['1' '2' { printf ("%d %2.1f\n", $1, $2); }],
+          ["12"],
+          [if (res == '1')
+             AT_VAL.ival = 10;
+           else
+             AT_VAL.fval = 0.2f],
+          [10 0.2])
+
+  # A Bison-defined union.
+  # The tokens names are not available directly in C++, we use their
+  # user number to keep it simple between C and C++.
+  AT_TEST([%skeleton "]b4_skel["
+           %define api.value.type union],
+          [%token <int> ONE 101;
+           %token <float> TWO 102 THREE 103;
+           %printer { ]AT_SKEL_CC_IF([[yyoutput << $$]],
+                                     [[fprintf (yyo, "%d", $$)]])[; } <int>
+           %printer { ]AT_SKEL_CC_IF([[yyoutput << $$]],
+                                     [[fprintf (yyo, "%f", $$)]])[; } <float>
+          ],
+          [ONE TWO THREE { printf ("%d %2.1f %2.1f\n", $1, $2, $3); }],
+          [{ 101, 102, 103, EOF }],
+          [if (res == 101)
+             AT_VAL.ONE = 10;
+           else if (res == 102)
+             AT_VAL.TWO = .2f;
+           else if (res == 103)
+             AT_VAL.THREE = 3.3f],
+          [10 0.2 3.3])
+
+  # A Bison-defined variant, for lalr1.cc only.
+  m4_if(b4_skel, [lalr1.cc], [
+  AT_TEST([%skeleton "]b4_skel["
+           %define api.value.type variant],
+          [%token <int> '1';
+           %token <std::string> '2';],
+          ['1' '2' { std::cout << $1 << ", " << $2 << std::endl; }],
+          ["12"],
+          [if (res == '1')
+             AT_VAL.build(10);
+           else
+             AT_VAL.build<std::string>("two");],
+          [10, two])])
+])
+
+m4_popdef([AT_TEST])