Compare commits

...
Author SHA1 Message Date
Valentin Tolmer 702c92a80b warnings: sort the messages by location
Sort the warnings by location (file, line number, column). They are built
using an obstack then stored in a list, and finally sorted just before
being printed, at the end.

* src/complain.c, src/complain.h: New warning struct, obstack, and
implementation
* src/location.c, location.h (location_obstack_caret,
location_obstack_print): New
* src/main.c: Print the warnings
* src/muscle-tab.c, src/reader.c, src/scan-code.l, src/symtab.c: Adapt for
multi-part warnings
* tests/actions.at, tests/conflicts.at, tests/existing.at, tests/input.at,
* tests/reduce.at, tests/regression.at, tests/skeleton.at: Update testsuite
2013-08-29 14:06:26 +02:00
Valentin TolmerandAkim Demaille a728075710 symbols: improve symbol aliasing
Rather than having duplicate info in the symbol and the alias that has
to be resolved later on, both the symbol and the alias have a common
pointer to a separate structure containing this info.

* src/symtab.h (sym_content): New structure.
* src/symtab.c (sym_content_new, sym_content_free, symbol_free): New

* src/AnnotationList.c, src/conflicts.c, src/gram.c, src/gram.h,
* src/graphviz.c, src/ielr.c, src/output.c, src/parse-gram.y, src/print.c
* src/print-xml.c, src/print_graph.c, src/reader.c, src/reduce.c,
* src/state.h, src/symlist.c, src/symtab.c, src/symtab.h, src/tables.c:
Adjust.

* tests/input.at: Fix expectations (order changes).
2013-08-01 12:49:51 +02:00
Akim Demaille c4aa4ff541 build: ship the ASCII art figures
We don't ship the *.txt files that are used to build the info
file.
Reported by Colin Daley.

* doc/figs/example.txt: New.
* doc/local.mk (bison.info): Depend on the txt files.
And ship them.
2013-08-01 11:41:49 +02:00
Akim Demaille b97bbbaed7 doc: prefer the ".gv" extension to ".dot"
See http://marc.info/?l=graphviz-devel&m=129418103126092 for the
motivation (basically, some word processor now uses *.dot).

* doc/figs/example-reduce.dot: Rename as...
* doc/figs/example-reduce.gv: this.
* doc/figs/example-shift.dot: Rename as...
* doc/figs/example-shift.gv: this.
* doc/figs/example.dot: Rename as...
* doc/figs/example.gv: this.
* doc/local.mk: Adjust.
2013-08-01 11:20:13 +02:00
Akim Demaille e386b50f26 maint: post-release administrivia
* NEWS: Add header line for next release.
* .prev-version: Record previous version.
* cfg.mk (old_NEWS_hash): Auto-update.
2013-07-25 18:13:53 +02:00
Akim Demaille 534497f54b version 3.0
* NEWS: Record release date.
2013-07-25 17:55:58 +02:00
Akim Demaille a62a7b014c regen 2013-07-25 17:55:32 +02:00
Akim Demaille de1a2f20dd news: prepare 3.0
* NEWS (3.0): Reorder.
2013-07-25 17:53:59 +02:00
Akim Demaille afcc58c63e tests: fix invalid assignment when using variants in C++11
* tests/c++.at (Exception safety): In variant mode $$ is an instance
of Object.  Assigning YY_NULL in C++98 is incorrect, but behaves ok,
as it assigns YY_NULL=0 using Object::operator= (char v).  It is wrong
in C++11 as there is operator for "$$ = nullptr".
2013-07-25 17:53:59 +02:00
Akim Demaille d3ae5af6ec yacc: beware of "uninitialized uses" warnings
Again some issues with the fact that yylval is reported by GCC as
possibly not initialized in some cases.  Here, the case at hand is the
%destructor.

I am still not convinced that it is worth going all the trouble of
using pragmas to disable temporarily some warnings, instead of just
initializing the looking symbol once for all, but that's what Paul
voted for, see
<http://lists.gnu.org/archive/html/bison-patches/2012-10/msg00050.html>.

* data/c.m4 (b4_attribute_define): Define
YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN, YY_IGNORE_MAYBE_UNINITIALIZED_END,
YY_INITIAL_VALUE here, as we will need them in the generation of the
destructor function, which is defined in yacc.c before yyparse, which
was in charge of defining these macros.
* data/yacc.c (b4_declare_scanner_communication_variables): Simplify:
trying to factor the definitions of the case pure and impure is
too complex.
Actually, it is not even clear that this macro should really exist,
as even the calls are complex.
Be careful not to issue a lone ";", as this is a statement, and C90
forbids declarations after statements ; so write
"YY_INITIAL_VALUE(Decl;)", not "YY_INITIAL_VALUE(Decl);".
2013-07-25 17:53:59 +02:00
Akim Demaille 41dfa1cbf0 gnulib: update 2013-07-25 13:47:01 +02:00
Akim Demaille b7171c45f4 tests: skip C++ tests if we can't compile a simple program
There are possible conflicts between gnulib replacement functions (in
<stdio.h>) and their C++ wrappers (in <stream>).  Trying to address
these in configure seems too hard, and I don't know how to fix the issue
in gnulib.  Cowardly avoid the problem by skipping C++ tests when this
happens.
Reported by Stefano Lattarini.
http://lists.gnu.org/archive/html/bug-bison/2013-06/msg00001.html

* tests/atlocal.in (BISON_CXX_WORKS): Also set it to "skip" if we can't
compile a simple program using <stream>.
* tests/local.at: Comment changes.
2013-07-03 17:18:54 +02:00
Akim Demaille ac953ff80a tests: fix 'find' portability issues
Reported by Stefano Lattarini.
http://lists.gnu.org/archive/html/bug-bison/2013-06/msg00000.html

* tests/output.at (AT_CHECK_OUTPUT): Use Perl instead.
2013-07-03 08:39:41 +02:00
Akim Demaille facb910cbd maint: post-release administrivia
* NEWS: Add header line for next release.
* .prev-version: Record previous version.
* cfg.mk (old_NEWS_hash): Auto-update.
2013-06-24 10:29:36 +02:00
Akim Demaille 8faace8d1d version 2.7.91
* NEWS: Record release date.
2013-06-24 10:21:33 +02:00
Akim Demaille 9cdcbdf2cf NEWS: prepare for 2.7.91
* NEWS (2.7.91): Java push parsers.
2013-06-24 10:20:46 +02:00
Akim Demaille 45c64fa627 java: rename YYMORE as YYPUSH_MORE for consistency with C
http://lists.gnu.org/archive/html/bison-patches/2013-06/msg00008.html

* data/lalr1.java, doc/bison.texi, tests/javapush.at:
s/YYMORE/YYPUSH_MORE.
2013-06-24 09:37:18 +02:00
Akim Demaille 58b465ae5f tests: fix Java push failure when running with BISON_USE_PUSH_FOR_PULL
* tests/javapush.at (Trivial Push Parser with api.push-pull verification):
When push for pull is enabled, there is one such function generated.
2013-06-21 11:39:02 +02:00
Akim Demaille d116722c54 style: minor changes in the Java tests
* tests/java.at (AT_CHECK_JAVA_GREP): Ignore the exit status.
* tests/javapush.at (AT_CHECK_JAVA_GREP): Be more alike the previous
one.
Formating changes.
Remove stray debugging "jj" file.
2013-06-21 11:38:47 +02:00
Akim Demaille 1d678854a4 java: push: do not reset the error counter
* data/lalr1.java (parse): here, when in push-pull is in "both" mode.
This breaks the test suite, for instance
make check TESTSUITEFLAGS='-d 388 BISON_USE_PUSH_FOR_PULL=1'.
More generally make maintainer-push-check.
2013-06-21 11:17:05 +02:00
Akim Demaille 28c4075b58 build: add Valgrind suppression file for GNU/Linux
* build-aux/linux-gnu.valgrind: New.
* build-aux/local.mk: Ship it.
* configure.ac: Use it.
2013-06-14 09:58:12 +02:00
Dennis HeimbignerandAkim Demaille aa94def12d java: add push-parser support
* data/lalr1.java: Capture the declarations as m4 macros to avoid
duplication.  When push parsing, the declarations occur at the class
instance level rather than within the parse() function.

Change the way that the parser state is initialized.  For
push-parsing, the parse state declarations are moved to
"push_parse_initialize()", which is called on the first invocation of
"push_parse()". The %initial-action code is also inserted after the
invocation of "push_parse_initialize()".

The body of the parse loop is modified to return values at appropriate
points when doing push parsing.  In order to make push parsing work,
it is necessary to divide YYNEWSTATE into two states: YYNEWSTATE and
YYGETTOKEN. On the first call to push_parse(), the state is
YYNEWSTATE. On all later entries, the state is set to YYGETTOKEN. The
YYNEWSTATE switch arm falls through into YYGETTOKEN. YYGETTOKEN
indicates that a new token is potentially needed.  Normally, with a
pull parser, this new token would be obtained by calling "yylex()". In
the push parser, the value YYMORE is returned to the caller. On the
next call to push_parse(), the parser will return to the YYGETTOKEN
state and continue operation.

* tests/javapush.at: New test file for java push parsing.
* tests/testsuite.at: Use it.
* tests/local.mk: Adjust.
* doc/bison.texi (Java Push Parser Interface): New.

Signed-off-by: Akim Demaille <[email protected]>
2013-06-13 10:38:14 +02:00
Akim Demaille 0fcc2e9a74 build: ship all the files, even if the C++ compiler is broken
* examples/calc++/local.mk: Be sure to ship calc++.test even if
the current C++ compiler is not sufficient to run the tests.
2013-06-11 16:36:38 +02:00
Dennis HeimbignerandAkim Demaille 94a6225578 style: comment changes in Java skeleton
* data/lalr1.java: Here.
2013-06-05 10:04:21 +02:00
Akim Demaille 02798ba13d tests: fix a G++ warning
* tests/c++.at: Use YY_NULL instead of 0 for the null pointer.
And formatting changes.
2013-06-03 16:41:17 +02:00
Akim Demaille 8e13c5c03b build: fix a warning from clang
* src/muscle-tab.c: Declare local functions static.
2013-06-03 16:40:30 +02:00
Akim Demaille 266cdc3025 maint: post-release administrivia
* NEWS: Add header line for next release.
* .prev-version: Record previous version.
* cfg.mk (old_NEWS_hash): Auto-update.
2013-05-30 15:28:44 +02:00
Akim Demaille fea2516636 version 2.7.90
* NEWS: Record release date.
2013-05-30 15:02:52 +02:00
Akim Demaille c0ef22ab0b style: syntax-check fixes
* data/yacc.c, src/Sbitset.c, src/Sbitset.h, src/muscle-tab.h,
* src/output.c, src/parse-gram.y, src/reader.c, src/symtab.c,
* src/uniqstr.c, src/uniqstr.h: Fix space before parens.
* cfg.mk (_space_before_paren_exempt): Add needed exceptions.
2013-05-30 14:10:05 +02:00
Akim Demaille 971ef18e30 xml: use %empty in the text output
* data/xslt/xml2text.xsl: here.
2013-05-30 11:07:57 +02:00
Akim Demaille ec991d74e1 build: locally disable new GCC warnings that fail on Flex generated code
* configure.ac: here.
2013-05-30 11:07:57 +02:00
Akim Demaille c0efa83c0b fix a memory leak
* src/print-xml.c (num_escape_bufs): New.
(print_xml): Be sure to release all the escape_bufs.
2013-05-30 11:07:57 +02:00
Akim Demaille e37054cf27 regen 2013-05-30 11:07:56 +02:00
Akim Demaille 89ff1b5e71 build: be sure to include config.h first in the generated parser
Using %code for config.h is wrong, as some headers will already have
been included by Bison.  In some cases, e.g., glibc's string.h, this
results in some declaration not being made for lack of definition of
_GNU_SOURCE, which is performed by config.h.

* src/parse-gram.y: here.
2013-05-30 10:47:49 +02:00
Akim Demaille f122444873 Merge remote-tracking branch 'origin/maint'
* origin/maint:
  maint: post-release administrivia
  version 2.7.1
  regen
2013-05-29 09:05:12 +02:00
Petr MachataandAkim Demaille 30465cb778 drop unused options --raw, -n, -e, --include and -I
* --raw appears to be ignored.  It was marked as obsolete in the
  commit ec3bc39, and documented as no longer supported as of 1.29
  (2001-09-07).  Support for %raw appears to have been dropped in
  e9955c83 on 2002-06-11, but --raw was kept around.  Maybe it's time
  to drop it as well?

* Commit e9955c83 dropped support for %no-parser as well, and
  converted it to option.  --no-parser was later dropped in 728c4be2
  on 2007-08-12, but -n was kept around, probably as an omission.  All
  three are documented as removed since 2.3b (2008-05-27).

* -e existed for a single day in 2001.  It was introduced in eeeb962b
  on 2001-11-27.  The handling was removed in c7925b99 on 2001-11-28,
  but "e" was kept in the list of short options.  Probably an
  omission.

* --include appears to be dead code.  The option sets a variable, but
  that variable is not used anywhere.  It was added in f6bd5427 on
  2001-11-26 as a %-directive, with comments that it's not yet
  implemented.  It was converted to a command-line option later, but
  doesn't seem to ever have been actually implemented.

Signed-off-by: Petr Machata <[email protected]>
Signed-off-by: Akim Demaille <[email protected]>
2013-05-29 08:57:31 +02:00
Akim Demaille f9340b27b2 gnulib: update 2013-05-28 16:40:44 +02:00
Akim Demaille f249e803f0 diagnostics: always point to the first directive
Some directives cannot be used several times (e.g., a given symbol may
only have a single printer).  In case of repeated definitions, an
error is issued for the second definition, yet it is not discarded,
and becomes the definition used for the rest of the file.

This is not consistent with the idea that multiple definitions are not
allowed: discard any repeated directive.

* src/symtab.c (symbol_type_set, symbol_code_props_set)
(semantic_type_code_props_set, symbol_class_set, symbol_translation):
Discard repeated directives.
* tests/input.at (Default %printer and %destructor redeclared)
(Per-type %printer and %destructor redeclared): Update expectations.
2013-04-22 13:55:00 +02:00
Akim Demaille dfb12d6845 tests: factor test for printer/desctructor redefined
* tests/input.at (Default %printer and %destructor redeclared):
Introduce AT_TEST to factor.
2013-04-22 13:47:50 +02:00
Akim Demaille d8ce703102 diagnostics: use appropriate location for useless precedence/associativity
* src/symtab.c (symbol_precedence_set): Use prec_location, not
location (which is the first occurrence of the symbol, possibly just
%token).
Also, as redefinitions are not allowed, keep the first values, not
the subsequent ones.
* tests/conflicts.at, tests/existing.at, tests/regression.at: Adjust.
2013-04-22 11:36:22 +02:00
Akim Demaille 8782fe26cb tests: factor duplicate expected warnings
* tests/existing.at: Instead of "t ? abc : aBc", write "a(t?b:B)c".
2013-04-22 11:13:09 +02:00
Akim Demaille 7ba01e111c tests: enable -Wsign-compare and fix corresponding warnings
-Wsign-compare was disabled for bison's own code, following gnulib's
approach.  However, the generated parsers should not trigger such
warnings.

Reported by Efi Fogel.
http://lists.gnu.org/archive/html/help-bison/2013-04/msg00018.html

See also http://stackoverflow.com/questions/16101062 for the weird
"-(unsigned)i" piece of code.

* configure.ac (warn_tests): Enable -Wsign-compare.
* data/location.cc (position::add_): New.
(position::lines, position::columns): Use it.
* tests/actions.at (AT_CHECK_PRINTER_AND_DESTRUCTOR): Fix signedness issues.
2013-04-19 17:13:07 +02:00
Akim Demaille 6ce4b4ff1b muscle: check more cases of %define variables with code values
* data/bison.m4 (b4_percent_define_check_kind): Fix overquotation.
(api.location.type, api.position.type): Check they have code values here.
* data/c++.m4 (api.location.type): No longer checked here.
(parser_class_name): Check it here.
* data/java.m4 (api.value.type, init_throws, lex_throws, parser_class_name)
(throws, annotations, extends, implements): Check they have code values.
* doc/bison.texi: Fix every incorrect occurrence of %define.
Document the additional syntax for %define: code values.
Document the additional syntax for -D/-F: string and code values.
* tests/calc.at, tests/headers.at, tests/input.at, tests/java.at,
* tests/local.at: Fix dependencies.
2013-04-18 17:19:30 +02:00
Akim Demaille 332019e19a regen 2013-04-18 16:47:41 +02:00
Akim Demaille 9402b62353 parser: do not convert $ and @ in code values of %define variables
* src/parse-gram.y (value: "{...}"): Just strip the braces, but pass
the value as is.
2013-04-18 16:37:23 +02:00
Akim Demaille 985d7177e8 parser: no longer use the "braceless" non-terminal
The purpose of this symbol was only to factor function calls.  As a
result the actions were indeed simpler, but the grammar was somewhat
uselessly obfuscated.  Get rid of this symbol, but introduce functions
to simplify dependencies.

There is no (intended) changes of behavior here.

* src/parse-gram.y (strip_braces, translate_code(
(translate_code_braceless): New.
(braceless): Remove, use "{...}" instead, and one of the previous
functions depending on the context.
(STRING, "%{...%}", EPILOGUE): Declare as <code>, instead of <chars>,
the difference between both is useless (well, I couldn't make sense of
it, even after having read the initial commit that introduced them).
(%union): Remove the now useless "chars" type.
Adjust the printers.
* src/scan-gram.l: Adjust.
2013-04-18 16:36:58 +02:00
Akim Demaille 7dbadca2d0 regen 2013-04-18 15:12:24 +02:00
Akim Demaille 3f21a394f4 style: avoid %{...%} in our parser
* src/parse-gram.y (%{...%}): Split in %code and %code requires.
* src/location.h: Add missing includes for self containedness.
2013-04-18 15:11:53 +02:00
Akim Demaille 827aca04eb style: use %code for local function declarations in our parser
* src/parse-gram.y (version_check, gram_error, char_name, lloc_default):
Move their prototypes from %{...%} to %code.
(YYLLOC_DEFAULT, YY_LOCATION_PRINT): Move from %{...%} to %code.
(current_lhs): Move its implementation to the epilogue.
2013-04-18 15:10:35 +02:00
Akim Demaille ff2e3d397a regen 2013-04-16 18:06:08 +02:00
Akim Demaille aba47f5624 muscle: check the kind of api.prefix, api.location.type
* data/bison.m4: Check api.prefix.
* data/c++.m4: Check api.location.type.
* doc/bison.texi: Fix uses of api.value.type, api.prefix, api.location.type.
Document {...} values for %define.
* src/parse-gram.y: Fix use of api.prefix.
* tests/calc.at: Fix uses of api.location.type.
* tests/input.at: Check api.prefix, and api.location.type.
2013-04-16 17:42:43 +02:00
Akim Demaille abcfd805b8 maint: post-release administrivia
* NEWS: Add header line for next release.
* .prev-version: Record previous version.
* cfg.mk (old_NEWS_hash): Auto-update.
2013-04-15 14:09:40 +02:00
Akim Demaille 1f5542fe2d version 2.7.1
* NEWS: Record release date.
2013-04-15 13:59:02 +02:00
Akim Demaille d065cb3853 regen 2013-04-15 11:29:54 +02:00
Akim Demaille c53b684889 muscle: enforce definition syntax for keyword variables
* src/muscle-tab.c (muscle_percent_define_get_kind)
(muscle_percent_define_check_kind): New.
(muscle_percent_define_default): Variables with a default value are
of "keyword" kind.
(muscle_percent_define_flag_if, muscle_percent_define_check_values):
Check that the variable is of keyword kind.
* data/bison.m4: Likewise, but in M4.  That is to say...
(b4_percent_define_default): Define the kind when the variable is undefined.
(b4_percent_define_check_kind): Use a better error message.
(_b4_percent_define_check_values, _b4_percent_define_check_values):
Former "enum" variables should be defined using the keyword syntax.
* doc/bison.texi: Update.
A couple of fixes.
* tests/input.at (%define keyword variables): New.
2013-04-15 10:57:19 +02:00
Akim Demaille 5fad4d4f09 muscle: let -D/-F support the three kinds of %define variable values
See http://lists.gnu.org/archive/html/bison-patches/2013-04/msg00012.html

* src/getargs.c (getargs): Recognize {value} and "value" for -D and -F.
2013-04-15 10:57:19 +02:00
Akim Demaille 7956485cd6 muscle: minor refactoring
* src/muscle-tab.c (muscle_percent_define_default): Reduce the scopes.
2013-04-15 10:57:05 +02:00
Akim Demaille bb4b189b9c muscle: minor simplification which uncovers a missing warning
* src/muscle-tab.c (muscle_percent_define_ensure): Discover the virtues
of || to factor conditionals.
* NEWS: As api.pure is no longer flagged as "used" by accident,
we now have warnings for useless definitions.
* tests/calc.at: So remove api.pure settings when running C++ tests,
since C++ skeletons use a pure interface.
2013-04-15 10:50:30 +02:00
Akim Demaille d9cfa2bee2 muscle: factor the field retrieval
* src/muscle-tab.c (muscle_percent_define_get_raw): New.
Use it where appropriate.
(location_decode): No longer fetch the value from the table,
take the value as argument.
2013-04-15 10:50:30 +02:00
Akim Demaille 0f9583b69b muscle: factor the handling of used variables
* src/muscle-tab.c (muscle_percent_define_use): New, corresponding
to b4_percent_define_use.
Use it where appropriate.
2013-04-15 10:50:30 +02:00
Akim Demaille c98b5143b0 muscle: factor the computation of variable names
* src/muscle-tab.c (muscle_name): New.
Use it.
Propagate "uniqstr" as value type instead of plain "char const *".
2013-04-15 10:50:12 +02:00
Akim Demaille 07e65a77aa muscle: factor the kind check in M4
* data/bison.m4 (b4_percent_define_check_kind): New.
Use it to check api.token.prefix.
* data/c++.m4: Check the kind of api.namespace.
* doc/bison.texi: Update a reference to former 'namespace' variable.
* tests/input.at ("%define" code variables): Check api.namespace.
2013-04-15 10:37:00 +02:00
Akim Demaille ee616bdc62 muscle: factor conditionals on defined %define variables
* data/bison.m4 (b4_percent_define_ifdef_): New.
Use it where appropriate.
2013-04-15 10:32:48 +02:00
Akim Demaille 630a021850 api.token.prefix: use code values
* data/bison.m4: Remove useless (and incorrect: m4_* instead of b4_*)
default assignment to api.token.prefix.
Check that api.token.prefix is assigned code.
* tests/input.at (%define code variables): New test.
* NEWS, doc/bison.texi, tests/c++.at, tests/calc.at,
* tests/java.at, tests/local.at: Adjust to use braces.
2013-04-11 15:54:46 +02:00
Akim Demaille 75ae829984 c++: fix several issues with locations
Reported by Daniel Frużyński.
http://lists.gnu.org/archive/html/bug-bison/2013-02/msg00000.html

* data/location.cc (position::columns, position::lines): Check for
underflow.
Fix some weird function signatures.
(location): Accept signed integers as arguments where appropriate.
Add operator- and operator+=.
* doc/bison.texi (C++ position, C++ location): Various fixes
and completion.
* tests/c++.at (C++ Locations): New tests.
2013-04-11 12:50:59 +02:00
Akim Demaille 08cc1a3b18 muscles: be sure that %code snippets are not glue together on a single line
Recently "braceless" in the parser was changed so that an eol was no
longer added to the value.  This is not correct when a %code is used
multiple times, because the syncline of the next snippet might be
appended to the last (and not ended) line of the previous snippet.

* src/muscle-tab.h (muscle_grow): Make it private.
* src/muscle-tab.c (muscle_grow): Accept a fourth argument: a required
terminator.
Adjust callers.
* tests/input.at (Multiple %code): New.
2013-04-11 09:21:08 +02:00
Akim Demaille edaa22ec15 style: fix comments
* tests/actions.at: Fix incorrect "prototype".
2013-04-11 08:47:43 +02:00
Akim Demaille cc8962bdde Merge remote-tracking branch 'origin/maint'
* 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
2013-04-10 10:24:56 +02:00
Akim Demaille 435575cb5e api.value.type: use keyword/brace values
Suggested by Joel E. Denny.
http://lists.gnu.org/archive/html/bison-patches/2013-03/msg00016.html

* data/bison.m4 (b4_percent_define_get_kind): New.
(b4_variant_flag): Check that api.value.type is defined as the 'variant'
keyword value.
* data/c.m4 (_b4_value_type_setup_keyword): New.
(b4_value_type_setup): Use it to simplify reading.
Use b4_define_silent.
Decode api.value.type, including its type.
(b4_value_type_define): Likewise.
* data/c++.m4 (b4_value_type_declare): Adjust the decoding of api.value.type,
taking its kind into account.
* doc/bison.texi: Adjust all the examples to the new syntax.
* NEWS: Ditto.
* tests/types.at: Adjust
2013-04-09 16:59:06 +02:00
Akim Demaille 1fa19a7697 api.value.type: diagnose guaranteed failure with --yacc
Instead of generating invalid C code, generate an error when --yacc and
'%define api.value.type union' are used together.

* data/bison.m4: Issue an error in this case.
* tests/types.at (%yacc vs. %define api.value.type union): New, check this
error.
* doc/bison.texi (Type Generation): Document it.
* tests/output.at: Check that '-o y.tab.c' and '-y' behave equally
wrt generated file names.
* NEWS (Use of YACC='bison -y'): New.
Promote the use of 'bison -o y.tab.c'.
2013-04-09 14:07:52 +02:00
Akim Demaille d1a07886ee doc: style changes
* doc/bison.texi (Destructor Decl, Printer Decl): Group series of %token
and %type together.
2013-04-09 14:07:52 +02:00
Akim Demaille 71846502ae doc: display locations in error as recommended by GNU Coding Standards
* doc/bison.texi (Actions and Locations): here.
2013-04-09 14:07:52 +02:00
Akim Demaille 90b89dadb2 doc: api.value.type union
* doc/bison.texi (Type Generation): New section.
(Multi-function Calc): Convert to use api.value.type=union.
2013-04-09 14:07:51 +02:00
Akim Demaille e4d49586b6 doc: move the section about "%union" where types are discussed
* doc/bison.texi (Union Decl): Move to...
(Defining Language Semantics): here.
2013-04-09 14:07:51 +02:00
Akim Demaille 21e3a2b56c doc: deprecate #define YYSTYPE in favor of %define api.value.type
* doc/bison.texi: Convert examples with YYSTYPE to use api.value.type.
Deprecate YYSTYPE.
2013-04-09 14:07:51 +02:00
Akim Demaille cb8d8bb9b6 value type: accept "->" in type tags
Provide a means to dereference pointers when defining tags.  One
example could be:

  %code requires
  {
    typedef struct ListElementType
    {
      union value
      {
        int intVal;
        float floatVal;
        char* charptrVal;
      } value;

      struct ListElementType* next;
    } ListElementType;
  }

  %union
  {
    ListElementType* list;
  }

  %token <list->value.charptrVal> STRING
  %token <list->value.intVal> INTEGER
  %token <list->value.floatVal> REAL
  %type <list> ElementList LiteralType

* src/scan-code.l, src/scan-gram.l: Accept "->" in tags.
* tests/types.at: Add more test cases to cover this case.
2013-04-09 14:07:51 +02:00
Akim Demaille e52ddf820b style: simplify the scanning of type tags
* src/scan-gram.l: Remove the rule for simple tags: the "complex" case
subsumes it.  It was more efficient, but duplicated the code for a
negligible benefit.
2013-04-09 14:07:51 +02:00
Akim Demaille 6574576cfb api.value.type: implement proper support, check, and document
* data/c.m4 (b4_symbol_type_register, b4_type_define_tag)
(b4_symbol_value_union, b4_value_type_setup_union)
(b4_value_type_setup_variant, b4_value_type_setup):
New.
(b4_value_type_define): Use it to set up properly the type.
Handle the various possible values of api.value.type.
* data/c++.m4 (b4_value_type_declare): Likewise.
* data/lalr1.cc (b4_value_type_setup_variant): Redefine.

* tests/types.at: New.
Exercise all the C/C++ skeletons with different types of
api.value.type values.
* tests/local.mk, tests/testsuite.at: Use it.

* doc/bison.texi (%define Summary): Document api.value.type.
* NEWS: Advertise it, together with api.token.constructor.
2013-04-09 14:07:51 +02:00
Akim Demaille dde95ca432 m4: allow the definition of side-effect only macros
* data/bison.m4 (b4_divert_kill, b4_define_silent): New.
* data/c.m4: Comment change.
2013-04-09 14:07:51 +02:00
Akim Demaille 6155db81aa variant: fix inconsistent quotation
* data/variant.hh (b4_char_sizeof): De-overquote.
(b4_value_type_declare): De-underquote.
2013-04-09 14:07:51 +02:00
Akim Demaille 11872a8372 m4: style changes in error messages
* data/bison.m4: Use $0 to denote the current macro's name.
2013-04-09 14:07:50 +02:00
Akim Demaille 49964a4fe0 glr.cc: fix a clang warning
* data/glr.cc (b4_epilogue): Be sure to end with an end-of-line,
so that the file does end with one.
2013-04-08 19:52:16 +02:00
Akim Demaille 68f91d58f1 maint: update copyright years
Run "make update-copyright".
2013-04-08 13:44:57 +02:00
Akim Demaille 42bcf1ce44 build: fix VPATH issue
* Makefile.am (update-b4-copyright, update-package-copyright-year): Fix
path to build-aux.
(cherry picked from commit f6df83b4e8)

Conflicts:
	Makefile.am
2013-04-08 13:39:21 +02:00
Akim Demaille de7331a075 build: avoid clang's colored diagnostics in the test suite
The syncline tests, which try to recognize compiler diagnostics,
are confused by escapes for colors.

* configure.ac (warn_tests): New, to factor the warnings for both
C and C++ tests.
Add -fno-color-diagnostics to it.
* tests/local.at (AT_TEST_TABLES_AND_PARSE): Do not remove glue
together compiler flags.

Conflicts:
	configure.ac
2013-04-08 13:32:47 +02:00
Akim Demaille b0db817ff2 tests: please clang and use ".cc", not ".c", for C++ input
When fed with foo.c, clang++ 3.2 answers:

  clang: error: treating 'c' input as 'c++' when in C++ mode,
                this behavior is deprecated

* tests/output.at (AT_CHECK_OUTPUT_FILE_NAME): Use *.cc and *.hh
for C++.
2013-04-08 13:29:26 +02:00
Akim Demaille a565f73276 gnulib: update 2013-04-08 11:26:44 +02:00
Akim Demaille 3cf3393bd4 skeletons: avoid empty switch constructs
Reported by Rob Conde.
http://lists.gnu.org/archive/html/bug-bison/2013-03/msg00003.html

* data/c.m4 (b4_symbol_actions): Rename as...
(_b4_symbol_actions): this.
(b4_symbol_actions): New wrapper.
Do not emit empty switches.
Adjust all b4_symbol_actions callers.
2013-04-08 11:17:09 +02:00
Akim Demaille e83be476a5 lalr1.cc: fix compiler warnings
Reported by Rob Conde.
http://lists.gnu.org/archive/html/bug-bison/2013-03/msg00003.html

* data/stack.hh (operator=, stack(const stack&)): Make this class
uncopyable, i.e., "undefine" these operators: make them private and
don't implement them.
(clear): New.
* data/lalr1.cc: Use it instead of an assignment.
(parser): Make this class uncopyable.
2013-04-08 10:59:19 +02:00
Akim Demaille 80a2826e69 yacc.c: do not use __attribute__ unprotected
Reported by Victor Khomenko.
http://lists.gnu.org/archive/html/bug-bison/2013-04/msg00001.html

* data/glr.c (YYUSE, __attribute__): Fuse their definition into...
* data/c.m4 (b4_attribute_define): this new macro.
* data/yacc.c, data/glr.c: Use it.
2013-04-08 10:44:09 +02:00
Akim Demaille eb0e86ac80 api.namespace: demonstrate and use {...} values instead of "..." values
* tests/c++.at, tests/input.at: Use "%define api.namespace {foo}" instead
of using quotes.
* tests/local.at (AT_SETUP_STRIP, AT_NAME_PREFIX): Recognize uses of
braces instead of quotes.
* doc/bison.texi: Use braces for api.namespace's values.
2013-04-05 10:43:44 +02:00
Akim Demaille 57597927ef grammar: do not add a \n at the end of blocks of code
Now that we use "braceless" (which is {...} blocks of code with
initial and final braces stripped) to denote "short" values (such as
api.namespaces), the added end-of-line is a nuisance.  As a matter of
fact, this extra-safety was useless, as every expansion of "braceless"
(aka, "user code") is followed by an end of line.

* src/parse-gram.y, src/parse-gram.c (braceless): Instead of replacing
the final brace by \n, just delete the brace.
2013-04-05 10:42:59 +02:00
Akim Demaille de5fb744c9 regen 2013-04-04 16:50:55 +02:00
Akim Demaille 14bfd2e9d9 grammar: record the kind of %define variable values
Provide a means to tell the difference between "keyword" values (e.g.,
%define api.pull both), "string" values (e.g., %define file.name
"foo"), and "code" values (e.g., %define api.namespace {calc}).

Suggested by Joel E. Denny.
http://lists.gnu.org/archive/html/bison-patches/2013-03/msg00016.html

* src/muscle-tab.h, src/muscle-tab.c (muscle_kind, muscle_kind_new)
(muscle_kind_string): New.
(muscle_percent_define_insert): Take the kind as new argument.
Insert it in the muscle table.
Adjust callers.
* src/getargs.c: Adjust callers.
* src/parse-gram.y: Ditto.
(content.opt): Remove, replaced by...
(value): this new non-terminal, whose semantics value is stored
in the new "value" union member.
Provide a printer.
Support values in braces in additions to keyword and string values.

fuse me
2013-04-04 16:50:38 +02:00
Akim Demaille 36a17b50b5 style: fix comments
* src/muscle-tab.c (muscle_percent_define_ensure): Update obsolete
comments.
2013-04-04 16:27:54 +02:00
Akim Demaille 8a9283494b regen 2013-04-04 15:48:08 +02:00
Akim Demaille dac72a91d9 grammar: style changes
* src/parse-gram.y (PARAM_TYPE): Remove useless typedef guard.
There's a header guard.
Use 'yyo' with %printer.
Use a consistent style for %union one-liners.
2013-04-04 15:41:49 +02:00
Akim Demaille a17c70f876 grammar: split %union to group together related aspects
* src/parse-gram.y (INT): Fuse the %type and %token declaration.
Move its %union right before its introduction.
(%union): Split in several %unions, right before their use.
2013-04-04 15:38:06 +02:00
Akim Demaille c56d0037d2 muscle: refactor
* src/muscle-tab.c (muscle_lookup, muscle_entry_new): New.
(muscle_insert, muscle_grow, muscle_find_const, muscle_find): Use them.
2013-04-04 15:18:29 +02:00
Akim Demaille 9fb61ca8d8 style: comment changes
* src/muscle-tab.c: Move the documentation of public functions to...
* src/muscle-tab.h: here.
Fix comment consistency issues.
2013-04-03 17:15:50 +02:00
Akim Demaille 3f6e5dd6ac muscle: minor refactoring
* src/muscle-tab.h (MUSCLE_INSERT_C_STRING): Use MUSCLE_INSERT_STRING.
2013-04-03 17:07:22 +02:00
Akim Demaille 2dc8862bab regen 2013-03-06 10:31:55 +01:00
Valentin TolmerandAkim Demaille 5202b6ac1d gram: correct token numbering in precedence declarations
In a precedence declaration, when tokens are declared with a litteral
character (e.g., 'a') or with a identifier (e.g., B), Bison behaved
differently: the litteral tokens would be numbered first, and then the
other ones, leading to the following grammar:

  %right A B 'c' 'd'

being numbered as such: 'c' 'd' A B.

* src/parse-gram.y (symbol.prec): Set the symbol number when reading the
symbols.
* tests/conflicts.at (Token declaration order: literals vs. identifiers):
New.

Signed-off-by: Akim Demaille <[email protected]>
2013-03-06 10:31:47 +01:00
Akim Demaille 02879b4e81 maint: update autoconf submodule
* submodules/autoconf: Up to master.
No significant changes in the files we use (m4sugar.m4 and foreach.m4).
2013-03-04 18:26:25 +01:00
Akim Demaille f24695eff9 diagnostics: no longer include the yacc category in -Wall
It would be a pity to warn the users against Bison features...
http://lists.gnu.org/archive/html/bison-patches/2013-02/msg00107.html

* src/complain.h, src/complain.c (Wall): Disable Wyacc.
(Weverything): New (hidden so far) category which really denotes all
the categories (what used to be Wall).
(warnings_args, warnings_types): Adjust.
(warning_argmatch): Now !none = Weverything and conversely, no longer Wall.
* NEWS, doc/bison.texi, src/getargs.c: Adjust the documentation.
* tests/input.at (-Werror is not affected by -Wnone and -Wall): Adjust
by not using a -Wyacc type of warning.
2013-03-04 18:21:44 +01:00
Akim Demaille 05e25f2384 grammar: no longer detect and cure missing semicolon at end of actions
Bison 3.0 is already breaking backward compatibility with other
features.  It is an appropriate time to drop this feature.  Note that
it was disabled when --yacc is passed.  See
http://lists.gnu.org/archive/html/bison-patches/2013-02/msg00102.html

Basically, revert e8cd1ad655.

* src/scan-code.l (braces_level, need_semicolon, in_cpp): Remove.
Remove every rule needed to detect and add missing semicolon.
* tests/actions.at (Fix user actions without a trailing semicolon):
Remove.
* NEWS: Adjust.
2013-03-04 08:29:18 +01:00
Akim Demaille f1526426cd build: stop using bison -y
* Makefile.am (YACC): Pass -o y.tab.c, so that ylwrap is happy, and
yet we don't pass --yacc to bison.
(AM_YFLAGS): Disable Yacc warnings.
2013-03-04 08:25:32 +01:00
Akim Demaille 7601a471f5 c++: rename b4_semantic_type_declare as b4_value_type_declare
This is to match the names used in C and api.value.type, even if the
parser actually defines semantic_type.

* data/c++.m4 (b4_semantic_type_declare): Rename as...
(b4_value_type_declare): this.
* data/variant.hh: Likewise.
2013-02-23 16:16:15 +01:00
Akim Demaille 6c7022f7d3 news: typo
* NEWS: here.
2013-02-23 16:16:15 +01:00
Akim Demaille edd3280b69 style: space changes in the tests
* tests/local.at: here.
2013-02-23 16:16:15 +01:00
Akim Demaille fe65b14424 style: formatting changes in the doc
* doc/bison.texi: Use @file where appropriate.
2013-02-22 13:18:39 +01:00
Akim Demaille e39fcdda38 tests: fix invalid C++11 code
* tests/c++.at (Object): Somehow instances of Object were assigned
YY_NULL, which is 0 most of the time (that case passes), but is
nullptr in C++11, and there is nothing in Object to support such an
assignment (failure).  Use 0 as value, and provide the needed
assignment operator.
Also, use a more natural order within the class definition.
2013-02-19 17:47:13 +01:00
Akim Demaille 5ae8eb3202 tests: fix failures with G++ 4.8 in Flex scanner
* configure.ac (WARN_NO_NULL_CONVERSION_CXXFLAGS): Rename as...
(FLEX_SCANNER_CXXFLAGS): this.
Pass -Wno-zero-as-null-pointer-constant to G++ if it supports it.
* examples/calc++/local.mk: Adjust.
2013-02-19 17:42:33 +01:00
Akim Demaille bbed3fdef6 regen 2013-02-19 10:07:37 +01:00
Akim Demaille 42fef01256 gnulib: update 2013-02-19 09:51:38 +01:00
Akim Demaille 29248b4c13 style: rename variant private members
* data/variant.hh (buffer, tname, as_, raw, align_me): Rename as...
(yybuffer_, yytname_,yyas_, yyraw, yyalign_me): these.
2013-02-19 09:51:38 +01:00
Akim Demaille 361444e419 style: space changes
* data/variant.hh: Be sure to leave a space before arguments in function
calls.
2013-02-19 09:51:38 +01:00
Akim Demaille 85bc7f5466 variant: fix G++ 4.4 warnings
The changes by Théophile Ranquet about type punning issues need
to be extend to in-place new to please G++ 4.4.7.

* data/variant.hh (variant::as_): New, factors the casts that avoid
compiler warnings.
(as, build): Use them.
2013-02-19 09:51:38 +01:00
Akim Demaille 1282c12476 news: spell fixes
* NEWS: here.
2013-02-18 14:30:19 +01:00
Akim Demaille 0fe5a72a26 diagnostics: factor and enhance messages about duplicate rule directives
When reporting a duplicate directive on a rule, point to its first
occurrence:

one.y:11.10-15: error: only one %empty allowed per rule
   %empty {} %empty
             ^^^^^^
one.y:11.3-8: previous declaration
   %empty {} %empty
   ^^^^^^

And consistently discard the second one.

* src/complain.h, src/complain.c (duplicate_directive): New.
* src/reader.c: Use it where appropriate.
* src/symlist.h, src/symlist.c (symbol_list): Add a dprec_location member.
* tests/actions.at: Adjust expected output.
2013-02-18 10:01:29 +01:00
Akim Demaille 4c9b8f1318 style: no longer use backquotes
* tests/actions.at, tests/atlocal.in, tests/c++.at, tests/calc.at,
* tests/conflicts.at, tests/existing.at, tests/glr-regression.at,
* tests/input.at, tests/java.at, tests/local.at, tests/sets.at,
* tests/synclines.at, doc/bison.texi, lib/libiberty.h, lib/timevar.h:
Use single quotes.
2013-02-18 10:01:28 +01:00
Akim Demaille 45eebca42d style: no longer use backquotes
* README, REFERENCES, TODO, configure.ac, data/README, data/bison.m4,
* data/c++.m4, data/c.m4, data/java.m4, data/lalr1.cc,
* data/lalr1.java, data/yacc.c, doc/local.mk, etc/bench.pl.in,
* src/conflicts.c, src/files.c, src/getargs.c, src/gram.h, src/lalr.c,
* src/location.c, src/location.h, src/muscle-tab.c, src/muscle-tab.h,
* src/output.c, src/parse-gram.c, src/parse-gram.y, src/print-xml.c,
* src/print.c, src/reader.c, src/reduce.c, src/scan-skel.l,
* src/symtab.h, src/system.h, src/tables.c:
Use single quotes, as currently recommended by the GNU Coding Standards.
2013-02-18 10:01:28 +01:00
Akim Demaille d49751602c style: no longer use backquotes in messages
* src/getargs.c (usage): Use single quotes.
2013-02-18 10:01:28 +01:00
Akim Demaille 6240346aa0 doc: use %empty instead of /* empty */
* doc/bison.texi: Change the comments into explicit %empty.
2013-02-18 10:01:28 +01:00
Akim Demaille 09add9c24f doc: introduce %empty and -Wempty-rule
* doc/bison.texi (Grammar Rules): Make it a @section which
contains...
(Rules Syntax): this new subsection (with the previous contents of
"Grammar Rules".
(Empty Rules): New subsection, extracted from the former
"Grammar Rules".
Document %empty.
(Recursion): New a subsection of "Grammar Rules".
Complete a few index entries.
(Bison Options): Document -Wempty-rule.
2013-02-18 10:01:28 +01:00
Akim Demaille 8b807f1177 report: use %empty to denote empty rules
* src/gram.c (rule_rhs_print): Use %empty for empty rules.
* tests/conflicts.at, tests/regression.at, tests/sets.at: Adjust.
2013-02-18 10:01:28 +01:00
Akim Demaille 42d101da8d diagnostics: %empty enables -Wempty-rule
* src/complain.h, src/complain.c (warning_is_unset): New.
* src/reader.c (grammar_current_rule_empty_set): If enabled -Wempty-rule,
if not disabled.
* tests/actions.at (Implicitly empty rule): Check this feature.
Also check that -Wno-empty-rule does disable this warning.
2013-02-18 10:01:28 +01:00
Akim Demaille f68a49ed49 -Wempty-rule: diagnose empty rules without %empty
* src/complain.h, src/complain.c (warning_empty_rule, Wempty_rule):
New warning category.
(warnings_args, warnings_types): Adjust.
* src/reader.c (grammar_rule_check): Check the empty rules are
flagged by %empty.
* tests/actions.at (Implicitly empty rule): New.
* tests/existing.at: Add expected warnings.
2013-02-18 10:01:27 +01:00
Akim Demaille 684083f065 tests: use %empty
* tests/actions.at, tests/input.at, tests/reduce.at,
* tests/regression.at:
here.
2013-02-18 10:01:27 +01:00
Akim Demaille 8ecac08f2d regen 2013-02-18 10:01:27 +01:00
Akim Demaille fd003416d5 parser: use %empty
Avoid that Bison's own use of "bison -Wall" trigger warnings.

* src/parse-gram.y: Use %empty for every empty rule.
2013-02-18 10:01:27 +01:00
Akim Demaille ae2b48f5c0 grammar: introduce %empty
Provide a means to explicitly denote empty right-hand sides of rules:
instead of

  exp:  { ... }

allow

  exp: %empty { ... }

Make sure that %empty is properly used.

With help from Joel E. Denny and Gabriel Rassoul.
http://lists.gnu.org/archive/html/bison-patches/2013-01/msg00142.html

* src/reader.h, src/reader.c (grammar_current_rule_empty_set): New.
* src/parse-gram.y (%empty): New token.
Use it.
* src/scan-gram.l (%empty): Scan it.
* src/reader.c (grammar_rule_check): Check that %empty is properly used.
* tests/actions.at (Invalid uses of %empty, Valid uses of %empty): New.
2013-02-18 10:01:27 +01:00
Akim Demaille 9e4917b2a1 getargs: minor simplification
* src/getargs.c (flag_argmatch): Simplify the handling of "none".
2013-02-16 07:45:14 +01:00
Akim Demaille 12bc1c9e47 style: move argument handling of -W into the diagnostics module
This allows to reduce the number of public interfaces.

* src/getargs.c (--yacc): Use warning_argmatch instead of tweaking
directly warnings_flag (which will be private).
(warning_argmatch, warnings_argmatch): Move to...
* src/complain.h, src/complain.c: here.

* src/getargs.h, src/getargs.c (warnings_args, warnings_types): Move to...
* src/complain.c: here, now private.

* src/complain.h (severity, warnings_flag): Move to...
* src/complain.c: here, now private.
2013-02-16 07:45:07 +01:00
Akim Demaille 808e523db4 diagnostics: revamp the handling of -Werror
Recent discussions with Joel E. Denny
(http://lists.gnu.org/archive/html/bison-patches/2013-02/msg00026.html)
show that it is desirable to tell the difference between an option
that was explicitly disabled with -Wno-foo, as opposed to be left
unset.  The current framework does not allow this.

Instead of having a first int to store which options are enabled, and
another to store which are turned into errors, use an array that for
each warning category tells its status: disabled, unset, warning,
error.

* src/complain.h, src/complain.c (warning_bit): New enum.
(warnings): Use it.
(severity): New enum.
(warnings_flag): Now an array of severity.
(errors_flag): Remove, now done by warnings_flag.
(complain_init): New function, to initialie warnings_flag.
(warnings_are_errors): New Boolean, for -Werror.
* src/complain.c (warning_severity): New.
(warnings_print_categories, complains): Use it.
* src/getargs.c (warning_argmatch): Adjust to use warnings_flag.
(warnings_argmatch): Ditto.
Handle -Werror and -Wno-error here.
(getargs): Adjust.
* src/main.c (main): Call complain_init.
* tests/input.at (Invalid options): Add more corner cases.
2013-02-16 07:45:06 +01:00
Akim Demaille 4a3c55cf1a options: simplify the handling of -W
* src/getargs.c (warnings_argmatch, warning_argmatch): Simplify by
replacing function arguments with their actual values.
(WARNING_ARGMATCH): Remove, useless.
Adjust callers.
2013-02-14 15:00:52 +01:00
Akim Demaille c017f88fde options: don't accept "error=" for -f and -r
* src/getargs.c (warning_argmatch, warnings_argmatch, WARNINGS_ARGMATCH):
New.
Use them for -W/--warning.
They are copied from...
(flag_argmatch, flags_argmatch, FLAGS_ARGMATCH): these.
Simplify by removing the support for "error".
* tests/input.at (Invalid options): New.
* TODO (Laxism in Bison invocation arguments): Remove.
2013-02-14 15:00:51 +01:00
Akim Demaille 219458e22f diagnostics: factor the list of warning names
* src/getargs.h, src/getargs.c (warnings_args, warnings_types): Make
them public.
* src/complain.h, src/complain.c (warnings_print_categories): Its
only use outside complain.c was removed in a recent commit, so
make it static.
Simplify its implementation.
Use warnings_args and warnings_types.
* src/muscle-tab.c (muscle_percent_define_check_values): Make it
silent.
2013-02-14 15:00:51 +01:00
Akim Demaille fec5f3c0cc diagnostics: no longer pretty-print rules in error messages, carets suffice
* src/gram.c (grammar_rules_useless_report): Let -fcaret handle the
pretty-printing of the guilty rules.
(rule_print): Inline in its only use.
* tests/conflicts.at, tests/existing.at, tests/reduce.at,
* tests/regression.at: Adjust.
* NEWS: Document.
2013-02-14 15:00:51 +01:00
Akim Demaille 9a9130f26d options: no longer document warnings when diagnosing an invalid -W
The argmatch functions accept prefixes of the alternatives (like
getopt does for long options).  Bison uses this to document the
warning categories.  This is troublesome: it duplicates the --help
documentation, it is not gettextized, it is displayed with ugly quotes
(because argmatch uses it to display the list of possible answers),
and it prevents straighforward uses of the tables of valid warning
categories (for instance so that warning diagnostics end with the name
of the warning).

The "hidden" option --trace uses the same trick, but it does not need
to be translated, nor to be described in --help.

* src/getargs.c (warnings_args): Remove pseudo documentation.
Comment changes.
2013-02-14 15:00:44 +01:00
Akim Demaille 312d0d654f tests: enlarge the allowed duration for calc tests
Hydra "often" fails on this test:

252. calc.at:658: 252. Calculator %glr-parser api.pure
parse.error=verbose %debug %locations %defines api.prefix="calc"
%verbose %yacc %parse-param {semantic_value *result}
%parse-param {int *count} (calc.at:658): FAILED

* tests/calc.at: Give 200s instead of 100s.
Use AT_DEBUG_IF.
2013-02-11 09:07:25 +01:00
Akim Demaille 848bcc288d debug: improve the display of symbol lists
* src/symtab.c (symbol_print): Remove useless quotes (the symbol already
has quotes).
Prefer fputs.
* src/symlist.c (symbol_list_syms_print): Likewise.
Fix separators.
2013-02-11 09:04:17 +01:00
Akim Demaille ec6dc4375e style: minor changes
* src/complain.c: Space changes.
* src/reader.c: Comment changes.
Avoid && in assertions.
* src/location.c: Move comments to...
* src/location.h: here.
* src/symlist.h, src/symlist.c: Create a pseudo section for members
that apply to the rule.
2013-02-09 18:35:28 +01:00
Akim Demaille c21e515e05 news: restructure, document variants for C++
* NEWS: here.
2013-02-08 17:28:06 +01:00
Akim Demaille 1dce289a00 c++: api.token.constructor requires api.value.type=variant
Eventually it should also support "union".

* data/glr.cc: Move this check to...
* data/c++.m4: here, as lalr1.cc is affected too.
2013-02-08 17:28:02 +01:00
Akim Demaille 66c209cf43 build: restore C90 compatibility
* src/parse-gram.y, src/parse-gram.c: Don't use // comments.
2013-02-05 14:37:55 +01:00
Akim Demaille efbc95a7e4 doc: use @group to improve page breaking
* doc/bison.texi: here.
2013-02-05 11:44:12 +01:00
Akim Demaille c5dbd909d0 style: rename internal "stype" as "union_members" for clarity
"stype" is quite unclear, and it also collides with the former %define
variable that had the same name (replaced by api.value.type).

* src/parse-gram.y (stype): Rename as...
(union_members): this.
* data/bison.m4: Adjust.
(b4_user_stype): Rename as...
(b4_user_union_members): this.
* data/c++.m4, data/c.m4: Adjust.
* src/parse-gram.c: regen.
2013-02-04 18:45:21 +01:00
Akim Demaille 6112cb1802 tests: improve the language independance layer
* tests/local.at (_AT_LANG_DISPATCH): New, shamelessly stolen from
Autoconf's _AT_LANG_DISPATCH.
(AT_LANG_DISPATCH): New.
(AT_YYERROR_FORMALS, AT_YYERROR_PROTOTYPE, AT_YYERROR_DECLARE_EXTERN)
(AT_YYERROR_DECLARE, AT_YYERROR_DEFINE, AT_MAIN_DEFINE, AT_COMPILE)
(AT_FULL_COMPILE):
Use AT_LANG_DISPATCH instead of an ad hoc m4_case.
2013-02-04 16:49:10 +01:00
Akim Demaille 246ff8c1d3 regen 2013-02-04 16:49:10 +01:00
Akim Demaille f50fa14529 style: space changes in the parser
* src/parse-gram.y: Fix spaces.
2013-02-04 16:49:09 +01:00
Akim Demaille 2c056d696d parser: use api.pure full
* src/parse-gram.y: Use api.pure full instead of silly macro tricks.
2013-02-04 16:49:09 +01:00
Akim Demaille 06505b0c69 style: use a for loop instead of a while loop, and scope reduction
* src/reader.c (packgram): Improve readability.
The parser calls grammar_current_rule_end at the end of every rhs,
which adds a NULL to separate the rules.  So there is no need to
check whether "p" is non-null before proceeding.
2013-02-04 16:46:54 +01:00
Theophile Ranquet e96415a54b variants: stylistic change
* data/variant.hh (tname): Respect the GNU Coding Standards for this
pointer's declaration.
2013-02-01 15:09:54 +01:00
Theophile Ranquet f038e56cdc grammar: free the association tracking graph
The graph introduced by Valentin wasn't free'd after use.

* src/symtab.c (assoc_free): New, clear the array of linked lists with...
(linkedlist_free): This, new.
(print_precedence_warnings): Call assoc_free when done.
(print_assoc_warnings): Free used_assoc after use.
2013-02-01 15:06:26 +01:00
Theophile Ranquet f2e1d4090d tests: use AT_FULL_COMPILE where possible
* tests/c++.at (C++ Variant-based Symbol, Variants): Here.  Rename the
generated input files to use .y instead of .yy, as a requirement for using
AT_FULL_COMPILE instead of a combination of AT_BISON_CHECK and
AT_BISON_COMPILE_CXX.
2013-02-01 15:06:26 +01:00
Theophile Ranquet be6fa942ac variants: avoid type punning issue
This is based on what is recommended by both Scott Meyers, in 'Effective
C++', and Andrei Alexandrescu and Herb Sutter in 'C++ Coding Standards'.

Use a static_cast on void* rather than directly use a reinterpret_cast,
which can have nefarious effects on objects.  However, even though following
this guideline is good practice in general, I am not quite sure how relevant
it is when applied to conversions from POD to objects.  Actually, it might
very well be the opposite: isn't this exactly what reinterpret_cast is for?
What we really want *is* to transmit the memory map as a series of bytes,
which, if I am correct, falls into the kind of "low level" hack for which
this cast is meant.

In any case, this silences the warning, which will be greatly appreciated by
anyone using variants with a compiler supporting -fstrict-aliasing.

* data/variant.hh (as): Here.
* tests/c++.at (Exception safety, C++ Variant-based Symbols, Variants):
Don't use NO_STRICT_ALIAS_CXXFLAGS (revert commit ddb9db15), as type punning
is no longer an issue.
* tests/atlocal.in, configure.ac (NO_STRICT_ALIAS_CXXFLAGS): Remove
definition.
* examples/local.mk (NO_STRICT_ALIAS_CXXFLAGS): Remove from AM_CXXFLAGS.
* doc/bison.texi: Don't mention type punning issues.
2013-02-01 15:06:20 +01:00
Theophile Ranquet f29f8af3ed todo: update
Reformulate and give more details on my thoughts concerning the graphical
visualization, and add an entry about a bug in the options processing for
warnings as errors.

* TODO: Here.
2013-02-01 14:44:23 +01:00
Akim Demaille 74ce3cfbf6 regen 2013-02-01 14:26:29 +01:00
Akim Demaille b805eca764 location: pass the location first
* src/location.h, src/location.c (location_print): For consistency
with other data structures and other location_* routines, pass the
location argument first.
* src/complain.c: Adjust.
(location_caret): Likewise.
* src/parse-gram.y: Adjust.
2013-02-01 14:24:48 +01:00
Akim Demaille e6c25014bb symlist: use the right stream
* src/symlist.c (symbol_list_syms_print): Use "f", not stderr.
2013-02-01 14:23:49 +01:00
Akim Demaille 97ad789d10 tests: put two related tests together
* tests/conflicts.at (Useless associativity warning): Move next
to "Useless precedence warning".
2013-01-30 21:41:41 +01:00
Akim Demaille d2f9ae18be news: name contributors
* NEWS: here.
2013-01-30 21:40:47 +01:00
Valentin TolmerandAkim Demaille cc2235ace2 warnings: introduce -Wprecedence
The new warning category "precedence" flags useless precedence and
associativity.  -Wprecedence can now be used, it is disabled by default.
The warnings about precedence and associativity are grouped into one, and
the testsuite was corrected accordingly.

* src/complain.h (warnings): Introduce "precedence".
* src/complain.c (warnings_print_categories): Adjust.
* src/getargs.c (warnings_args, warning_types): Likewise.
* src/symtab.h, src/symtab.c (print_associativity_warnings): Remove.
* src/symtab.h (register_assoc): Correct arguments.
* src/symtab.c (print_precedence_warnings): Print both warnings together.
* doc/bison.texi (Bison options): Document the warnings and provide an
example.
* tests/conflicts.at, tests/existing.at, tests/local.at,
* tests/regression.at: Adapt the testsuite for the new category
(-Wprecedence instead of -Wother where appropriate).
2013-01-30 21:39:08 +01:00
Akim Demaille 657ed6d3be tests: style changes
* tests/glr-regression.at: Issue yyerror before yylex.
2012-12-15 14:58:05 +01:00
101 changed files with 6784 additions and 3613 deletions
+1 -1
View File
@@ -1 +1 @@
2.7 3.0
+4 -4
View File
@@ -32,8 +32,8 @@ EXTRA_DIST = .prev-version .version \
## version of Bison nearby... ## version of Bison nearby...
BISON = $(top_builddir)/tests/bison BISON = $(top_builddir)/tests/bison
BISON_IN = $(top_srcdir)/tests/bison.in BISON_IN = $(top_srcdir)/tests/bison.in
YACC = $(BISON) -y YACC = $(BISON) -o y.tab.c
AM_YFLAGS = -d -v --warnings=all,error --report=all AM_YFLAGS = -d -v -Werror -Wall -Wno-yacc --report=all
# Initialization before completion by local.mk's. # Initialization before completion by local.mk's.
AM_CFLAGS = $(WARN_CFLAGS) AM_CFLAGS = $(WARN_CFLAGS)
@@ -78,11 +78,11 @@ dist-hook: gen-ChangeLog
.PHONY: update-b4-copyright update-package-copyright-year .PHONY: update-b4-copyright update-package-copyright-year
update-b4-copyright: update-b4-copyright:
find $(srcdir)/data -type f \ $(AM_V_GEN)find $(srcdir)/data -type f \
| xargs $(srcdir)/build-aux/$@ | xargs $(srcdir)/build-aux/$@
@echo 'warning: src/parse-gram.[hc] may need to be regenerated.' @echo 'warning: src/parse-gram.[hc] may need to be regenerated.'
update-package-copyright-year: update-package-copyright-year:
$(srcdir)/build-aux/$@ $(srcdir)/configure.ac $(AM_V_GEN)$(srcdir)/build-aux/$@ $(srcdir)/configure.ac
gen_start_date = 2012-01-16 gen_start_date = 2012-01-16
.PHONY: gen-ChangeLog .PHONY: gen-ChangeLog
+371 -60
View File
@@ -2,16 +2,11 @@ GNU Bison NEWS
* Noteworthy changes in release ?.? (????-??-??) [?] * Noteworthy changes in release ?.? (????-??-??) [?]
* Noteworthy changes in release 3.0 (2013-07-25) [stable]
** WARNING: Future backward-incompatibilities! ** WARNING: Future backward-incompatibilities!
Bison will stop adding a semicolon at the end of the actions (as announced
in the release 2.5):
foo.y:2.22: warning: a ';' might be needed at the end of action code
exp: "num" { $$ = $1 }
^
foo.y:2.22: future versions of Bison will not add the ';'
Like other GNU packages, Bison will start using some of the C99 features Like other GNU packages, Bison will start using some of the C99 features
for its own code, especially the definition of variables after statements. for its own code, especially the definition of variables after statements.
The generated C parsers still aim at C90. The generated C parsers still aim at C90.
@@ -28,9 +23,32 @@ GNU Bison NEWS
Support for YYLEX_PARAM and YYPARSE_PARAM is removed (deprecated in Bison Support for YYLEX_PARAM and YYPARSE_PARAM is removed (deprecated in Bison
1.875): use %lex-param, %parse-param, or %param. 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 ** Bug fixes
*** The epilogue is no longer affected by internal #defines *** The epilogue is no longer affected by internal #defines (glr.c)
The glr.c skeleton uses defines such as #define yylval (yystackp->yyval) in The glr.c skeleton uses defines such as #define yylval (yystackp->yyval) in
generated code. These weren't properly undefined before the inclusion of generated code. These weren't properly undefined before the inclusion of
@@ -39,7 +57,7 @@ GNU Bison NEWS
int yylex (YYSTYPE *yylval); int yylex (YYSTYPE *yylval);
This is has been fixed: yylval, yynerrs, yychar, and yylloc are now valid This is fixed: yylval, yynerrs, yychar, and yylloc are now valid
identifiers for user-provided variables. identifiers for user-provided variables.
*** stdio.h is no longer needed when locations are enabled (yacc.c) *** stdio.h is no longer needed when locations are enabled (yacc.c)
@@ -47,6 +65,8 @@ GNU Bison NEWS
Changes in Bison 2.7 introduced a dependency on FILE and fprintf when Changes in Bison 2.7 introduced a dependency on FILE and fprintf when
locations are enabled. This is fixed. locations are enabled. This is fixed.
*** Warnings about useless %pure-parser/%define api.pure are restored
** Diagnostics reported by Bison ** Diagnostics reported by Bison
Most of these features were contributed by Théophile Ranquet and Victor Most of these features were contributed by Théophile Ranquet and Victor
@@ -58,6 +78,29 @@ GNU Bison NEWS
activated by default. The old format can still be used by invoking Bison activated by default. The old format can still be used by invoking Bison
with -fno-caret (or -fnone). 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 *** Enhancements of the -Werror option
The -Werror=CATEGORY option is now recognized, and will treat specified The -Werror=CATEGORY option is now recognized, and will treat specified
@@ -198,12 +241,10 @@ GNU Bison NEWS
bar.y: error: shift/reduce conflicts: 1 found, 0 expected bar.y: error: shift/reduce conflicts: 1 found, 0 expected
bar.y: error: reduce/reduce conflicts: 2 found, 0 expected bar.y: error: reduce/reduce conflicts: 2 found, 0 expected
*** Useless precedence ** Incompatibilities with POSIX Yacc
Bison now warns about symbols with a declared precedence but no declared The 'yacc' category is no longer part of '-Wall', enable it explicitly
associativity (i.e. declared with %precedence), and whose precedence is with '-Wyacc'.
never used. In that case, the symbol can be safely declared with %token
instead, without modifying the parsing tables.
** Additional yylex/yyparse arguments ** Additional yylex/yyparse arguments
@@ -220,13 +261,271 @@ GNU Bison NEWS
%param {arg1_type *arg1} {arg2_type *arg2} %param {arg1_type *arg1} {arg2_type *arg2}
** Java skeleton improvements ** Types of values for %define variables
Contributed by Paolo Bonzini. Bison used to make no difference between '%define foo bar' and '%define
foo "bar"'. The former is now called a 'keyword value', and the latter a
'string value'. A third kind was added: 'code values', such as '%define
foo {bar}'.
Keyword variables are used for fixed value sets, e.g.,
%define lr.type lalr
Code variables are used for value in the target language, e.g.,
%define api.value.type {struct semantic_type}
String variables are used remaining cases, e.g. file names.
** 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 both keyword and code 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"
Code values (in 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
The constants for token names were moved to the Lexer interface. Also, it 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" is possible to add code to the parser's constructors using "%code init"
and "%define init_throws". and "%define init_throws".
Contributed by Paolo Bonzini.
The Java skeleton now supports push parsing.
Contributed by Dennis Heimbigner.
** C++ skeletons improvements ** C++ skeletons improvements
@@ -249,59 +548,66 @@ GNU Bison NEWS
used by the scanner, or rejecting invalid combinations from a used by the scanner, or rejecting invalid combinations from a
factory invoked by the user actions). factory invoked by the user actions).
** Renamed %define variables *** %define api.value.type variant
The following variables have been renamed for consistency. Backward This is based on a submission from Michiel De Wilde. With help
compatibility is ensured, but upgrading is recommended. from Théophile Ranquet.
lr.default-reductions -> lr.default-reduction In this mode, complex C++ objects can be used as semantic values. For
lr.keep-unreachable-states -> lr.keep-unreachable-state instance:
namespace -> api.namespace
stype -> api.value.type
** Variable api.token.prefix %token <::std::string> TEXT;
%token <int> NUMBER;
The variable api.token.prefix changes the way tokens are identified in %token SEMICOLON ";"
the generated files. This is especially useful to avoid collisions %type <::std::string> item;
with identifiers in the target language. For instance %type <::std::list<std::string>> list;
%token FILE for ERROR
%define api.token.prefix "TOK_"
%% %%
start: FILE for ERROR; result:
list { std::cout << $1 << std::endl; }
;
will generate the definition of the symbols TOK_FILE, TOK_for, and list:
TOK_ERROR in the generated sources. In particular, the scanner must %empty { /* Generates an empty string list. */ }
use these prefixed token names, although the grammar itself still | list item ";" { std::swap ($$, $1); $$.push_back ($2); }
uses the short names (as in the sample rule given above). ;
** Variable parse.error item:
TEXT { std::swap ($$, $1); }
| NUMBER { $$ = string_cast ($1); }
;
This variable controls the verbosity of error messages. The use of the *** %define api.token.constructor
%error-verbose directive is deprecated in favor of "%define parse.error
verbose".
** Semantic predicates 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):
Contributed by Paul Hilfinger. 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);
...
}
The new, experimental, semantic-predicate feature allows actions of the *** C++ locations
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 There are operator- and operator-= for 'location'. Negative line/column
increments can no longer underflow the resulting value.
It used to be an error only if used in non GLR mode, _and_ if there are * Noteworthy changes in release 2.7.1 (2013-04-15) [stable]
reduce/reduce conflicts.
** Token numbering has changed to preserve the user-defined order ** Bug fixes
When declaring %token A B, the numbering for A is inferior to B. Up to now, *** Fix compiler attribute portability (yacc.c)
when declaring associativity at the same time, with %left (or %right,
%precedence, %nonassoc), B was inferior to A. With locations enabled, __attribute__ was used unprotected.
*** Fix some compiler warnings (lalr1.cc)
* Noteworthy changes in release 2.7 (2012-12-12) [stable] * Noteworthy changes in release 2.7 (2012-12-12) [stable]
@@ -353,8 +659,8 @@ GNU Bison NEWS
exp: exp '+' exp { $exp = $1 + $3; }; exp: exp '+' exp { $exp = $1 + $3; };
^^^ ^^^
The default behaviour for now is still not to display these unless The default behavior for now is still not to display these unless
explictly asked with -fcaret (or -fall). However, in a later release, it explicitly asked with -fcaret (or -fall). However, in a later release, it
will be made the default behavior (but may still be deactivated with will be made the default behavior (but may still be deactivated with
-fno-caret). -fno-caret).
@@ -441,7 +747,7 @@ GNU Bison NEWS
Other issues in the test suite have been addressed. 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 When possible, yylloc is correctly initialized before calling yylex. It
is no longer necessary to initialize it in the %initial-action. is no longer necessary to initialize it in the %initial-action.
@@ -2357,7 +2663,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
LocalWords: Automake TMPDIR LESSEQ ylwrap endif yydebug YYTOKEN YYLSP ival hh LocalWords: Automake TMPDIR LESSEQ ylwrap endif yydebug YYTOKEN YYLSP ival hh
LocalWords: extern YYTOKENTYPE TOKENTYPE yytokentype tokentype STYPE lval pdf LocalWords: extern YYTOKENTYPE TOKENTYPE yytokentype tokentype STYPE lval pdf
LocalWords: lang yyoutput dvi html ps POSIX lvalp llocp Wother nterm arg init LocalWords: lang yyoutput dvi html ps POSIX lvalp llocp Wother nterm arg init
LocalWords: TOK calc yyo fval Wconflicts 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: Local Variables:
mode: outline mode: outline
+1 -1
View File
@@ -30,7 +30,7 @@ not answer them, please send mail to <[email protected]>.
* Bug reports * Bug reports
Please send bug reports to <[email protected]>. Please include the Please send bug reports to <[email protected]>. 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. test case in each bug report.
* Copyright statements * Copyright statements
+1 -1
View 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 the starting and ending line number and character number associated
with any of the symbols in the current rule. 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 the conflicts if there are N shift/reduce conflicts and no reduce/reduce
conflicts. conflicts.
+7
View File
@@ -25,10 +25,12 @@ Bruce Lilly [email protected]
Bruno Haible [email protected] Bruno Haible [email protected]
Charles-Henri de Boysson [email protected] Charles-Henri de Boysson [email protected]
Christian Burger [email protected] Christian Burger [email protected]
Colin Daley [email protected]
Cris Bailiff [email protected] Cris Bailiff [email protected]
Cris van Pelt [email protected] Cris van Pelt [email protected]
Csaba Raduly [email protected] Csaba Raduly [email protected]
Dagobert Michelsen [email protected] Dagobert Michelsen [email protected]
Daniel Frużyński [email protected]
Daniel Hagerty [email protected] Daniel Hagerty [email protected]
David J. MacKenzie [email protected] David J. MacKenzie [email protected]
David Kastrup [email protected] David Kastrup [email protected]
@@ -37,6 +39,7 @@ Derek M. Jones [email protected]
Di-an Jan [email protected] Di-an Jan [email protected]
Dick Streefland [email protected] Dick Streefland [email protected]
Didier Godefroy [email protected] Didier Godefroy [email protected]
Efi Fogel [email protected]
Enrico Scholz [email protected] Enrico Scholz [email protected]
Eric Blake [email protected] Eric Blake [email protected]
Evgeny Stambulchik [email protected] Evgeny Stambulchik [email protected]
@@ -44,6 +47,7 @@ Fabrice Bauzac [email protected]
Florian Krohm [email protected] Florian Krohm [email protected]
Frank Heckenbach [email protected] Frank Heckenbach [email protected]
Frans Englich [email protected] Frans Englich [email protected]
Gabriel Rassoul [email protected]
Georg Sauthoff [email protected] Georg Sauthoff [email protected]
George Neuner [email protected] George Neuner [email protected]
Gilles Espinasse [email protected] Gilles Espinasse [email protected]
@@ -97,6 +101,7 @@ Peter Eisentraut [email protected]
Peter Fales [email protected] Peter Fales [email protected]
Peter Hamorsky [email protected] Peter Hamorsky [email protected]
Peter Simons [email protected] Peter Simons [email protected]
Petr Machata [email protected]
Piotr Gackiewicz [email protected] Piotr Gackiewicz [email protected]
Quentin Hocquet [email protected] Quentin Hocquet [email protected]
Quoc Peyrot [email protected] Quoc Peyrot [email protected]
@@ -106,6 +111,7 @@ Ralf Wildenhues [email protected]
Richard Stallman [email protected] Richard Stallman [email protected]
Rob Vermaas [email protected] Rob Vermaas [email protected]
Robert Anisko [email protected] Robert Anisko [email protected]
Rob Conde [email protected]
Roland Levillain [email protected] Roland Levillain [email protected]
Satya Kiran Popuri [email protected] Satya Kiran Popuri [email protected]
Sebastian Setzer [email protected] Sebastian Setzer [email protected]
@@ -126,6 +132,7 @@ Tommy Nordgren [email protected]
Troy A. Johnson [email protected] Troy A. Johnson [email protected]
Tys Lefering [email protected] Tys Lefering [email protected]
Valentin Tolmer [email protected] Valentin Tolmer [email protected]
Victor Khomenko [email protected]
Vin Shelton [email protected] Vin Shelton [email protected]
W.C.A. Wijngaards [email protected] W.C.A. Wijngaards [email protected]
Wayne Green [email protected] Wayne Green [email protected]
+23 -12
View File
@@ -1,16 +1,27 @@
* Short term * Short term
** Graphviz display code thoughts ** Graphviz display code thoughts
The code for the --graph option is over two files: print_graph, and 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, graphviz. This is because Bison used to also produce VCG graphs, but since
but since this is no longer true, maybe we could consider these files for this is no longer true, maybe we could consider these files for fusion.
fusion.
Little effort factoring seems to have been given to factoring in these files, An other consideration worth noting is that print_graph.c (correct me if I
and their print-xml and print counterpart. We would very much like to re-use am wrong) should contain generic functions, whereas graphviz.c and other
the pretty format of states from .output in the .dot 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.
Also, the underscore in print_graph.[ch] isn't very fitting considering Little effort seems to have been given to factoring these files and their
the dashes in the other filenames. 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 ** push-parser
Check it too when checking the different kinds of parsers. And be Check it too when checking the different kinds of parsers. And be
@@ -165,13 +176,13 @@ part of $default. Should we make the two reductions explicit, or just
keep $default? See the following point. keep $default? See the following point.
** Disabled Reductions ** 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. what we want to do.
** Documentation ** Documentation
Extend with error productions. The hard part will probably be finding 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 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 presented too. Shall we try to make a single grammar with all these
features, or should we have several very small grammars? features, or should we have several very small grammars?
@@ -232,9 +243,9 @@ into
exp: exp '+' exp | exp '&' exp; exp: exp '+' exp | exp '&' exp;
when there are no actions. This can significantly speed up some 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: 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? this issue. Does anybody have it?
+55 -43
View File
@@ -1,6 +1,6 @@
#! /bin/sh #! /bin/sh
# Print a version string. # Print a version string.
scriptversion=2012-12-28.10; # UTC scriptversion=2013-07-03.20; # UTC
# Bootstrap this package from checked-out sources. # Bootstrap this package from checked-out sources.
@@ -140,20 +140,21 @@ po_download_command_format2=\
"wget --mirror -nd -q -np -A.po -P '%s' \ "wget --mirror -nd -q -np -A.po -P '%s' \
http://translationproject.org/latest/%s/" http://translationproject.org/latest/%s/"
# Prefer a non-empty tarname (4th argument of AC_INIT if given), else
# fall back to the package name (1st argument with munging)
extract_package_name=' extract_package_name='
/^AC_INIT(/{ /^AC_INIT(\[*/{
/.*,.*,.*, */{ s///
s/// /^[^,]*,[^,]*,[^,]*,[ []*\([^][ ,)]\)/{
s/[][]//g s//\1/
s/)$// s/[],)].*//
p p
q q
} }
s/AC_INIT(\[*// s/[],)].*//
s/]*,.*//
s/^GNU // s/^GNU //
y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
s/[^A-Za-z0-9_]/-/g s/[^abcdefghijklmnopqrstuvwxyz0123456789_]/-/g
p p
} }
' '
@@ -255,12 +256,12 @@ esac
# Extra files from gnulib, which override files from other sources. # Extra files from gnulib, which override files from other sources.
test -z "${gnulib_extra_files}" && \ test -z "${gnulib_extra_files}" && \
gnulib_extra_files=" gnulib_extra_files="
$build_aux/install-sh build-aux/install-sh
$build_aux/mdate-sh build-aux/mdate-sh
$build_aux/texinfo.tex build-aux/texinfo.tex
$build_aux/depcomp build-aux/depcomp
$build_aux/config.guess build-aux/config.guess
$build_aux/config.sub build-aux/config.sub
doc/INSTALL doc/INSTALL
" "
@@ -306,34 +307,34 @@ if test -n "$checkout_only_file" && test ! -r "$checkout_only_file"; then
die "Bootstrapping from a non-checked-out distribution is risky." die "Bootstrapping from a non-checked-out distribution is risky."
fi fi
# Ensure that lines starting with ! sort last, per gitignore conventions # Strip blank and comment lines to leave significant entries.
# for whitelisting exceptions after a more generic blacklist pattern. gitignore_entries() {
sort_patterns() { sed '/^#/d; /^$/d' "$@"
sort -u "$@" | sed '/^!/ {
H
d
}
$ {
P
x
s/^\n//
}' | sed '/^$/d'
} }
# If $STR is not already on a line by itself in $FILE, insert it, # If $STR is not already on a line by itself in $FILE, insert it at the start.
# sorting the new contents of the file and replacing $FILE with the result. # Entries are inserted at the start of the ignore list to ensure existing
insert_sorted_if_absent() { # entries starting with ! are not overridden. Such entries support
# whitelisting exceptions after a more generic blacklist pattern.
insert_if_absent() {
file=$1 file=$1
str=$2 str=$2
test -f $file || touch $file test -f $file || touch $file
echo "$str" | sort_patterns - $file | cmp -s - $file > /dev/null \ test -r $file || die "Error: failed to read ignore file: $file"
|| { echo "$str" | sort_patterns - $file > $file.bak \ duplicate_entries=$(gitignore_entries $file | sort | uniq -d)
&& mv $file.bak $file; } \ if [ "$duplicate_entries" ] ; then
|| die "insert_sorted_if_absent $file $str: failed" die "Error: Duplicate entries in $file: " $duplicate_entries
fi
linesold=$(gitignore_entries $file | wc -l)
linesnew=$(echo "$str" | gitignore_entries - $file | sort -u | wc -l)
if [ $linesold != $linesnew ] ; then
{ echo "$str" | cat - $file > $file.bak && mv $file.bak $file; } \
|| die "insert_if_absent $file $str: failed"
fi
} }
# Adjust $PATTERN for $VC_IGNORE_FILE and insert it with # Adjust $PATTERN for $VC_IGNORE_FILE and insert it with
# insert_sorted_if_absent. # insert_if_absent.
insert_vc_ignore() { insert_vc_ignore() {
vc_ignore_file="$1" vc_ignore_file="$1"
pattern="$2" pattern="$2"
@@ -344,7 +345,7 @@ insert_vc_ignore() {
# .gitignore entry. # .gitignore entry.
pattern=$(echo "$pattern" | sed s,^,/,);; pattern=$(echo "$pattern" | sed s,^,/,);;
esac esac
insert_sorted_if_absent "$vc_ignore_file" "$pattern" insert_if_absent "$vc_ignore_file" "$pattern"
} }
# Die if there is no AC_CONFIG_AUX_DIR($build_aux) line in configure.ac. # Die if there is no AC_CONFIG_AUX_DIR($build_aux) line in configure.ac.
@@ -550,7 +551,7 @@ fi
echo "$0: Bootstrapping from checked-out $package sources..." echo "$0: Bootstrapping from checked-out $package sources..."
# See if we can use gnulib's git-merge-changelog merge driver. # See if we can use gnulib's git-merge-changelog merge driver.
if test -d .git && (git --version) >/dev/null 2>/dev/null ; then if $use_git && test -d .git && (git --version) >/dev/null 2>/dev/null ; then
if git config merge.merge-changelog.driver >/dev/null ; then if git config merge.merge-changelog.driver >/dev/null ; then
: :
elif (git-merge-changelog --version) >/dev/null 2>/dev/null ; then elif (git-merge-changelog --version) >/dev/null 2>/dev/null ; then
@@ -573,13 +574,17 @@ git_modules_config () {
test -f .gitmodules && git config --file .gitmodules "$@" test -f .gitmodules && git config --file .gitmodules "$@"
} }
gnulib_path=$(git_modules_config submodule.gnulib.path) if $use_git; then
test -z "$gnulib_path" && gnulib_path=gnulib gnulib_path=$(git_modules_config submodule.gnulib.path)
test -z "$gnulib_path" && gnulib_path=gnulib
fi
# Get gnulib files. # Get gnulib files. Populate $GNULIB_SRCDIR, possibly updating a
# submodule, for use in the rest of the script.
case ${GNULIB_SRCDIR--} in case ${GNULIB_SRCDIR--} in
-) -)
# Note that $use_git is necessarily true in this case.
if git_modules_config submodule.gnulib.url >/dev/null; then if git_modules_config submodule.gnulib.url >/dev/null; then
echo "$0: getting gnulib files..." echo "$0: getting gnulib files..."
git submodule init || exit $? git submodule init || exit $?
@@ -600,8 +605,8 @@ case ${GNULIB_SRCDIR--} in
GNULIB_SRCDIR=$gnulib_path GNULIB_SRCDIR=$gnulib_path
;; ;;
*) *)
# Use GNULIB_SRCDIR as a reference. # Use GNULIB_SRCDIR directly or as a reference.
if test -d "$GNULIB_SRCDIR"/.git && \ if $use_git && test -d "$GNULIB_SRCDIR"/.git && \
git_modules_config submodule.gnulib.url >/dev/null; then git_modules_config submodule.gnulib.url >/dev/null; then
echo "$0: getting gnulib files..." echo "$0: getting gnulib files..."
if git submodule -h|grep -- --reference > /dev/null; then if git submodule -h|grep -- --reference > /dev/null; then
@@ -627,12 +632,19 @@ case ${GNULIB_SRCDIR--} in
;; ;;
esac esac
# $GNULIB_SRCDIR now points to the version of gnulib to use, and
# we no longer need to use git or $gnulib_path below here.
if $bootstrap_sync; then if $bootstrap_sync; then
cmp -s "$0" "$GNULIB_SRCDIR/build-aux/bootstrap" || { cmp -s "$0" "$GNULIB_SRCDIR/build-aux/bootstrap" || {
echo "$0: updating bootstrap and restarting..." echo "$0: updating bootstrap and restarting..."
case $(sh -c 'echo "$1"' -- a) in
a) ignored=--;;
*) ignored=ignored;;
esac
exec sh -c \ exec sh -c \
'cp "$1" "$2" && shift && exec "${CONFIG_SHELL-/bin/sh}" "$@"' \ 'cp "$1" "$2" && shift && exec "${CONFIG_SHELL-/bin/sh}" "$@"' \
-- "$GNULIB_SRCDIR/build-aux/bootstrap" \ $ignored "$GNULIB_SRCDIR/build-aux/bootstrap" \
"$0" "$@" --no-bootstrap-sync "$0" "$@" --no-bootstrap-sync
} }
fi fi
+16
View File
@@ -0,0 +1,16 @@
# Linux seattle 2.6.32-5-amd64 #1 SMP Thu Mar 22 17:26:33 UTC 2012
# x86_64 GNU/Linux
{
index
Memcheck:Cond
fun:index
fun:expand_dynamic_string_token
fun:_dl_map_object
fun:map_doit
fun:_dl_catch_error
fun:do_preload
fun:dl_main
fun:_dl_sysdep_start
fun:_dl_start
obj:/lib/ld-2.11.3.so
}
+1 -2
View File
@@ -1,5 +1,3 @@
## Makefile for Bison testsuite.
# Copyright (C) 2000-2013 Free Software Foundation, Inc. # Copyright (C) 2000-2013 Free Software Foundation, Inc.
# #
# This program is free software: you can redistribute it and/or modify # This program is free software: you can redistribute it and/or modify
@@ -18,6 +16,7 @@
EXTRA_DIST += \ EXTRA_DIST += \
build-aux/cross-options.pl \ build-aux/cross-options.pl \
build-aux/darwin11.4.0.valgrind \ build-aux/darwin11.4.0.valgrind \
build-aux/linux-gnu.valgrind \
build-aux/move-if-change \ build-aux/move-if-change \
build-aux/prev-version.txt \ build-aux/prev-version.txt \
build-aux/update-b4-copyright build-aux/update-b4-copyright
+2 -1
View File
@@ -135,7 +135,7 @@ _sed_rm_comments_q = $(subst ','\'',$(_sed_remove_comments))
_space_before_paren_exempt =? \\n\\$$ _space_before_paren_exempt =? \\n\\$$
_space_before_paren_exempt = \ _space_before_paren_exempt = \
(^ *\#|\\n\\$$|%s\(to %s|(date|group|character)\(s\)) (^ *\#|(LA)?LR\([01]\)|percent_(code|define)|b4_syncline|m4_(define|init)|symbol)
# Ensure that there is a space before each open parenthesis in C code. # Ensure that there is a space before each open parenthesis in C code.
sc_space_before_open_paren: sc_space_before_open_paren:
@if $(VC_LIST_EXCEPT) | grep -l '\.[ch]$$' > /dev/null; then \ @if $(VC_LIST_EXCEPT) | grep -l '\.[ch]$$' > /dev/null; then \
@@ -175,5 +175,6 @@ $(call exclude, \
prohibit_strcmp=^doc/bison\.texi|tests/local\.at$$ \ prohibit_strcmp=^doc/bison\.texi|tests/local\.at$$ \
prohibit_tab_based_indentation=\.(am|mk)$$|^djgpp/|^\.git \ prohibit_tab_based_indentation=\.(am|mk)$$|^djgpp/|^\.git \
require_config_h_first=^(lib/yyerror|data/(glr|yacc))\.c$$ \ require_config_h_first=^(lib/yyerror|data/(glr|yacc))\.c$$ \
space_before_open_paren=^(data/|djgpp/) \
unmarked_diagnostics=^(djgpp/|doc/bison.texi$$|tests/c\+\+\.at$$) \ unmarked_diagnostics=^(djgpp/|doc/bison.texi$$|tests/c\+\+\.at$$) \
) )
+15 -7
View File
@@ -18,7 +18,7 @@
# In order for some versions of Sun Studio to compile our C++ test cases # 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 # 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 # 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. # environment variable.
AC_PREREQ([2.68]) AC_PREREQ([2.68])
m4_pattern_forbid([^gl_[A-Z]]) m4_pattern_forbid([^gl_[A-Z]])
@@ -91,7 +91,7 @@ if test "$enable_gcc_warnings" = yes; then
# -fno-color-diagnostics: Clang's use of colors in the error # -fno-color-diagnostics: Clang's use of colors in the error
# messages is confusing the tests looking at the compiler's output # messages is confusing the tests looking at the compiler's output
# (e.g., synclines.at). # (e.g., synclines.at).
warn_tests='-Wundef -pedantic -fno-color-diagnostics' warn_tests='-Wundef -pedantic -Wsign-compare -fno-color-diagnostics'
AC_LANG_PUSH([C]) AC_LANG_PUSH([C])
# Clang supports many of GCC's -W options, but only issues warnings # Clang supports many of GCC's -W options, but only issues warnings
@@ -143,9 +143,11 @@ if test "$enable_gcc_warnings" = yes; then
gl_WARN_ADD([$i], [WARN_CXXFLAGS_TEST]) gl_WARN_ADD([$i], [WARN_CXXFLAGS_TEST])
done done
# Clang++ 3.2+ reject C code generated by Flex. # Clang++ 3.2+ reject C code generated by Flex.
gl_WARN_ADD([-Wno-null-conversion], [WARN_NO_NULL_CONVERSION_CXXFLAGS]) gl_WARN_ADD([-Wno-null-conversion], [FLEX_SCANNER_CXXFLAGS])
# Variants break strict aliasing analysis. # So does G++ 4.8...
gl_WARN_ADD([-fno-strict-aliasing], [NO_STRICT_ALIAS_CXXFLAGS]) gl_WARN_ADD([-Wno-sign-compare], [FLEX_SCANNER_CXXFLAGS])
# ... possiby in std=c++11 mode.
gl_WARN_ADD([-Wno-zero-as-null-pointer-constant], [FLEX_SCANNER_CXXFLAGS])
CXXFLAGS=$save_CXXFLAGS CXXFLAGS=$save_CXXFLAGS
AC_LANG_POP([C++]) AC_LANG_POP([C++])
fi fi
@@ -228,10 +230,16 @@ case $VALGRIND:$host_os in
'':*) ;; '':*) ;;
*:darwin*) *:darwin*)
# See README-hacking. # See README-hacking.
# VALGRIND+=' --suppressions=$(abs_top_srcdir)/build-aux/darwin11.4.0.valgrind' # VALGRIND+='-q --suppressions=$(abs_top_srcdir)/build-aux/darwin11.4.0.valgrind'
VALGRIND=;; VALGRIND=;;
*:*) *:*)
AC_SUBST([VALGRIND_PREBISON], ["$VALGRIND -q"]);; suppfile=build-aux/$host_os.valgrind
if test -f "$srcdir/$suppfile"; then
VALGRIND="$VALGRIND --gen-suppressions=all"
VALGRIND="$VALGRIND --suppressions=\$(abs_top_srcdir)/$suppfile"
fi
AC_SUBST([VALGRIND_PREBISON], ["$VALGRIND -q"])
;;
esac esac
AM_MISSING_PROG([AUTOM4TE], [autom4te]) AM_MISSING_PROG([AUTOM4TE], [autom4te])
+1 -1
View File
@@ -27,7 +27,7 @@ Currently, the supported skeletons are:
These skeletons are the only ones supported by the Bison team. These skeletons are the only ones supported by the Bison team.
Because the interface between skeletons and the bison program is not Because the interface between skeletons and the bison program is not
finished, *we are not bound to it*. In particular, Bison 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. supported.
* m4sugar * m4sugar
+141 -28
View File
@@ -85,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. ## ## Error handling. ##
## ---------------- ## ## ---------------- ##
@@ -313,7 +327,7 @@ m4_define([b4_define_flag_if],
# _b4_define_flag_if($1, $2, FLAG) # _b4_define_flag_if($1, $2, FLAG)
# -------------------------------- # --------------------------------
# Work around the impossibility to define macros inside macros, # 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. # $$1 a la M5/TeX.
m4_define([_b4_define_flag_if], m4_define([_b4_define_flag_if],
[m4_if([$1$2], $[1]$[2], [], [m4_if([$1$2], $[1]$[2], [],
@@ -347,6 +361,7 @@ b4_define_flag_if([yacc]) # Whether POSIX Yacc is emulated.
# Whether the symbol has an id. # Whether the symbol has an id.
# - id: string # - id: string
# If has_id, the id. Guaranteed to be usable as a C identifier. # If has_id, the id. Guaranteed to be usable as a C identifier.
# Prefixed by api.token.prefix if defined.
# - tag: string. # - tag: string.
# A representat of the symbol. Can be 'foo', 'foo.id', '"foo"' etc. # A representat of the symbol. Can be 'foo', 'foo.id', '"foo"' etc.
# - user_number: integer # - user_number: integer
@@ -357,9 +372,13 @@ b4_define_flag_if([yacc]) # Whether POSIX Yacc is emulated.
# The internalized number (used after yytranslate). # The internalized number (used after yytranslate).
# - has_type: 0, 1 # - has_type: 0, 1
# Whether has a semantic value. # 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 # - type
# If it has a semantic value, its type tag, or, if variant are used, # If it has a semantic value, its type tag, or, if variant are used,
# its type. # its type.
# In the case of api.value.type=union, type is the real type (e.g. int).
# - has_printer: 0, 1 # - has_printer: 0, 1
# - printer: string # - printer: string
# - printer_file: string # - printer_file: string
@@ -442,6 +461,24 @@ m4_define([b4_symbol_destructor], [b4_symbol_action([$1], [destructor])])
m4_define([b4_symbol_printer], [b4_symbol_action([$1], [printer])]) 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) # b4_symbol_case_(SYMBOL-NUM)
# --------------------------- # ---------------------------
# Issue a "case NUM" for SYMBOL-NUM. # Issue a "case NUM" for SYMBOL-NUM.
@@ -577,14 +614,14 @@ m4_define([b4_define_user_code],
# b4_user_initial_action # b4_user_initial_action
# b4_user_post_prologue # b4_user_post_prologue
# b4_user_pre_prologue # b4_user_pre_prologue
# b4_user_stype # b4_user_union_members
# ---------------------- # ----------------------
# Macros that issue user code, ending with synclines. # Macros that issue user code, ending with synclines.
b4_define_user_code([actions]) b4_define_user_code([actions])
b4_define_user_code([initial_action]) b4_define_user_code([initial_action])
b4_define_user_code([post_prologue]) b4_define_user_code([post_prologue])
b4_define_user_code([pre_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) # b4_check_user_names(WHAT, USER-LIST, BISON-NAMESPACE)
@@ -665,9 +702,9 @@ m4_define([b4_percent_define_use],
# b4_percent_define_get([[foo]]) # b4_percent_define_get([[foo]])
m4_define([b4_percent_define_get], m4_define([b4_percent_define_get],
[b4_percent_define_use([$1])dnl [b4_percent_define_use([$1])dnl
m4_ifdef([b4_percent_define(]$1[)], b4_percent_define_ifdef_([$1],
[m4_indir([b4_percent_define(]$1[)])], [m4_indir([b4_percent_define(]$1[)])],
[$2])]) [$2])])
# b4_percent_define_get_loc(VARIABLE) # b4_percent_define_get_loc(VARIABLE)
# ----------------------------------- # -----------------------------------
@@ -686,7 +723,21 @@ m4_define([b4_percent_define_get_loc],
[m4_pushdef([b4_loc], m4_indir([b4_percent_define_loc(]$1[)]))dnl [m4_pushdef([b4_loc], m4_indir([b4_percent_define_loc(]$1[)]))dnl
b4_loc[]dnl b4_loc[]dnl
m4_popdef([b4_loc])], 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) # b4_percent_define_get_syncline(VARIABLE)
# ---------------------------------------- # ----------------------------------------
@@ -703,7 +754,20 @@ m4_popdef([b4_loc])],
m4_define([b4_percent_define_get_syncline], m4_define([b4_percent_define_get_syncline],
[m4_ifdef([b4_percent_define_syncline(]$1[)], [m4_ifdef([b4_percent_define_syncline(]$1[)],
[m4_indir([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])
# ------------------------------------------------------
# If the %define variable VARIABLE is defined, expand IF-TRUE, else expand
# IF-FALSE. Don't record usage of VARIABLE.
#
# For example:
#
# b4_percent_define_ifdef_([[foo]], [[it's defined]], [[it's undefined]])
m4_define([b4_percent_define_ifdef_],
[m4_ifdef([b4_percent_define(]$1[)],
[$2],
[$3])])
# b4_percent_define_ifdef(VARIABLE, IF-TRUE, [IF-FALSE]) # b4_percent_define_ifdef(VARIABLE, IF-TRUE, [IF-FALSE])
# ------------------------------------------------------ # ------------------------------------------------------
@@ -716,9 +780,9 @@ m4_define([b4_percent_define_get_syncline],
# #
# b4_percent_define_ifdef([[foo]], [[it's defined]], [[it's undefined]]) # b4_percent_define_ifdef([[foo]], [[it's defined]], [[it's undefined]])
m4_define([b4_percent_define_ifdef], m4_define([b4_percent_define_ifdef],
[m4_ifdef([b4_percent_define(]$1[)], [b4_percent_define_ifdef_([$1],
[b4_percent_define_use([$1])$2], [b4_percent_define_use([$1])$2],
[$3])]) [$3])])
## --------- ## ## --------- ##
@@ -747,11 +811,11 @@ m4_define([b4_percent_define_flag_if],
[[invalid value for %%define Boolean variable '%s']], [[invalid value for %%define Boolean variable '%s']],
[$1])], [$1])],
[[b4_percent_define_flag_if($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) # b4_percent_define_default(VARIABLE, DEFAULT, [KIND = keyword])
# -------------------------------------------- # --------------------------------------------------------------
# Mimic muscle_percent_define_default in ../src/muscle-tab.h exactly. That is, # Mimic muscle_percent_define_default in ../src/muscle-tab.h exactly. That is,
# if the %define variable VARIABLE is undefined, set its value to DEFAULT. # if the %define variable VARIABLE is undefined, set its value to DEFAULT.
# Don't record this as a Bison usage of VARIABLE as there's no reason to # Don't record this as a Bison usage of VARIABLE as there's no reason to
@@ -761,8 +825,10 @@ m4_define([b4_percent_define_flag_if],
# #
# b4_percent_define_default([[foo]], [[default value]]) # b4_percent_define_default([[foo]], [[default value]])
m4_define([b4_percent_define_default], m4_define([b4_percent_define_default],
[m4_ifndef([b4_percent_define(]$1[)], [b4_percent_define_ifdef_([$1], [],
[m4_define([b4_percent_define(]$1[)], [$2])dnl [m4_define([b4_percent_define(]$1[)], [$2])dnl
m4_define([b4_percent_define_kind(]$1[)],
[m4_default([$3], [keyword])])dnl
m4_define([b4_percent_define_loc(]$1[)], m4_define([b4_percent_define_loc(]$1[)],
[[[[<skeleton default value>:-1.-1]], [[[[<skeleton default value>:-1.-1]],
[[<skeleton default value>:-1.-1]]]])dnl [[<skeleton default value>:-1.-1]]]])dnl
@@ -772,8 +838,8 @@ m4_define([b4_percent_define_default],
# b4_percent_define_if_define(NAME, [VARIABLE = NAME]) # b4_percent_define_if_define(NAME, [VARIABLE = NAME])
# ---------------------------------------------------- # ----------------------------------------------------
# Define b4_NAME_if that executes its $1 or $2 depending whether # Define b4_NAME_if that executes its $1 or $2 depending whether
# VARIABLE was %defined. The characters `.' and `-' in VARIABLE are mapped # VARIABLE was %defined. The characters '.' and `-' in VARIABLE are mapped
# to `_'. # to '_'.
m4_define([b4_percent_define_if_define_], m4_define([b4_percent_define_if_define_],
[m4_define(m4_bpatsubst([b4_$1_if], [[-.]], [_]), [m4_define(m4_bpatsubst([b4_$1_if], [[-.]], [_]),
[b4_percent_define_flag_if(m4_default([$2], [$1]), [b4_percent_define_flag_if(m4_default([$2], [$1]),
@@ -783,6 +849,21 @@ m4_define([b4_percent_define_if_define],
b4_percent_define_if_define_([$1], [$2], $[1], $[2])]) b4_percent_define_if_define_([$1], [$2], $[1], $[2])])
# b4_percent_define_check_kind(VARIABLE, KIND, [DIAGNOSTIC = complain])
# ---------------------------------------------------------------------
m4_define([b4_percent_define_check_kind],
[b4_percent_define_ifdef_([$1],
[m4_if(b4_percent_define_get_kind([$1]), [$2], [],
[b4_error([m4_default([$3], [complain])],
b4_percent_define_get_loc([$1]),
[m4_case([$2],
[code], [[%%define variable '%s' requires '{...}' values]],
[keyword], [[%%define variable '%s' requires keyword values]],
[string], [[%%define variable '%s' requires '"..."' values]])],
[$1])])])dnl
])
# b4_percent_define_check_values(VALUES) # b4_percent_define_check_values(VALUES)
# -------------------------------------- # --------------------------------------
# Mimic muscle_percent_define_check_values in ../src/muscle-tab.h exactly # Mimic muscle_percent_define_check_values in ../src/muscle-tab.h exactly
@@ -804,8 +885,9 @@ m4_define([b4_percent_define_check_values],
[_b4_percent_define_check_values(b4_sublist)])]) [_b4_percent_define_check_values(b4_sublist)])])
m4_define([_b4_percent_define_check_values], m4_define([_b4_percent_define_check_values],
[m4_ifdef([b4_percent_define(]$1[)], [b4_percent_define_ifdef_([$1],
[m4_pushdef([b4_good_value], [0])dnl [b4_percent_define_check_kind(]$1[, [keyword], [deprecated])dnl
m4_pushdef([b4_good_value], [0])dnl
m4_if($#, 1, [], m4_if($#, 1, [],
[m4_foreach([b4_value], m4_dquote(m4_shift($@)), [m4_foreach([b4_value], m4_dquote(m4_shift($@)),
[m4_if(m4_indir([b4_percent_define(]$1[)]), b4_value, [m4_if(m4_indir([b4_percent_define(]$1[)]), b4_value,
@@ -820,7 +902,7 @@ m4_define([_b4_percent_define_check_values],
[[accepted value: '%s']], [[accepted value: '%s']],
m4_dquote(b4_value))])])dnl m4_dquote(b4_value))])])dnl
m4_popdef([b4_good_value])], 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]) # b4_percent_code_get([QUALIFIER])
# -------------------------------- # --------------------------------
@@ -861,10 +943,6 @@ m4_define([b4_percent_code_ifdef],
## Common variables. ## ## 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_assert_if([IF-ASSERTIONS-ARE-USED], [IF-NOT])
# b4_parse_trace_if([IF-DEBUG-TRACES-ARE-ENABLED], [IF-NOT]) # b4_parse_trace_if([IF-DEBUG-TRACES-ARE-ENABLED], [IF-NOT])
@@ -904,9 +982,11 @@ b4_error_verbose_if([m4_define([b4_token_table_flag], [1])])
# b4_variant_if([IF-VARIANT-ARE-USED], [IF-NOT]) # b4_variant_if([IF-VARIANT-ARE-USED], [IF-NOT])
# ---------------------------------------------- # ----------------------------------------------
b4_percent_define_if_define([variant]) b4_percent_define_if_define([variant])
m4_case(b4_percent_define_get([[api.value.type]]), m4_define([b4_variant_flag], [[0]])
[variant], [m4_define([b4_variant_flag], [[1]])], b4_percent_define_ifdef([[api.value.type]],
[m4_define([b4_variant_flag], [[0]])]) [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]) b4_define_flag_if([variant])
@@ -941,10 +1021,43 @@ m4_define_default([b4_parse_param], [])
m4_define_default([b4_location_initial_column], [1]) m4_define_default([b4_location_initial_column], [1])
m4_define_default([b4_location_initial_line], [1]) m4_define_default([b4_location_initial_line], [1])
# Sanity checks.
## --------------- ##
## Sanity checks. ##
## --------------- ##
# api.location.prefix={...} (Java and C++).
b4_percent_define_check_kind([api.location.type], [code], [deprecated])
# api.position.prefix={...} (Java).
b4_percent_define_check_kind([api.position.type], [code], [deprecated])
# api.prefix >< %name-prefix.
b4_percent_define_check_kind([api.prefix], [code], [deprecated])
b4_percent_define_ifdef([api.prefix], b4_percent_define_ifdef([api.prefix],
[m4_ifdef([b4_prefix], [m4_ifdef([b4_prefix],
[b4_complain_at(b4_percent_define_get_loc([api.prefix]), [b4_complain_at(b4_percent_define_get_loc([api.prefix]),
[['%s' and '%s' cannot be used together]], [['%s' and '%s' cannot be used together]],
[%name-prefix], [%name-prefix],
[%define api.prefix])])]) [%define api.prefix])])])
# api.token.prefix={...}
# Make it a warning for those who used betas of Bison 3.0.
b4_percent_define_check_kind([api.token.prefix], [code], [deprecated])
# 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"])])])])
+35 -13
View File
@@ -25,6 +25,12 @@ m4_include(b4_pkgdatadir/[c.m4])
m4_define([b4_comment], m4_define([b4_comment],
[b4_comment_([$1], [$2// ], [$2// ])]) [b4_comment_([$1], [$2// ], [$2// ])])
## -------- ##
## Checks. ##
## -------- ##
b4_percent_define_check_kind([api.namespace], [code], [deprecated])
b4_percent_define_check_kind([parser_class_name], [code], [deprecated])
## ---------------- ## ## ---------------- ##
## Default values. ## ## Default values. ##
@@ -38,6 +44,7 @@ b4_percent_define_default([[parser_class_name]], [[parser]])
# b4_percent_define_default([[api.location.type]], [[location]]) # b4_percent_define_default([[api.location.type]], [[location]])
b4_percent_define_default([[filename_type]], [[std::string]]) b4_percent_define_default([[filename_type]], [[std::string]])
# Make it a warning for those who used betas of Bison 3.0.
b4_percent_define_default([[api.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([[global_tokens_and_yystype]], [[false]])
@@ -54,8 +61,8 @@ b4_percent_define_default([[define_location_comparison]],
m4_define([b4_namespace_ref], [b4_percent_define_get([[api.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 # 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. # would compile as an absolute reference with 'parser' in the global namespace.
# b4_namespace_open would open an anonymous namespace and thus establish # b4_namespace_open would open an anonymous namespace and thus establish
# internal linkage. This would compile. However, it's cryptic, and internal # internal linkage. This would compile. However, it's cryptic, and internal
# linkage for the parser would be specified in all translation units that # linkage for the parser would be specified in all translation units that
@@ -112,19 +119,24 @@ m4_define([b4_token_enums],
## Semantic Values. ## ## Semantic Values. ##
## ----------------- ## ## ----------------- ##
# b4_semantic_type_declare
# ------------------------
# b4_value_type_declare
# ---------------------
# Declare semantic_type. # Declare semantic_type.
m4_define([b4_semantic_type_declare], m4_define([b4_value_type_declare],
[b4_value_type_setup[]dnl
[ /// Symbol semantic values. [ /// Symbol semantic values.
m4_ifdef([b4_stype], ]m4_bmatch(b4_percent_define_get_kind([[api.value.type]]),
[ union semantic_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_stype ]b4_user_union_members[
};], };]])])dnl
[m4_if(b4_tag_seen_flag, 0, ])
[[ typedef int semantic_type;]],
[[ typedef ]b4_api_PREFIX[STYPE semantic_type;]])])])
# b4_public_types_declare # b4_public_types_declare
@@ -133,7 +145,7 @@ b4_user_stype
# Depending on %define token_lex, may be output in the header or source file. # Depending on %define token_lex, may be output in the header or source file.
m4_define([b4_public_types_declare], m4_define([b4_public_types_declare],
[[#ifndef ]b4_api_PREFIX[STYPE [[#ifndef ]b4_api_PREFIX[STYPE
]b4_semantic_type_declare[ ]b4_value_type_declare[
#else #else
typedef ]b4_api_PREFIX[STYPE semantic_type; typedef ]b4_api_PREFIX[STYPE semantic_type;
#endif]b4_locations_if([ #endif]b4_locations_if([
@@ -520,3 +532,13 @@ m4_define([b4_yylloc_default_define],
while (/*CONSTCOND*/ false) while (/*CONSTCOND*/ false)
# endif # 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]))])])
+193 -31
View File
@@ -150,7 +150,7 @@ m4_popdef([$1])dnl
# b4_parse_param_use([VAL], [LOC]) # b4_parse_param_use([VAL], [LOC])
# -------------------------------- # --------------------------------
# `YYUSE' VAL, LOC if locations are enabled, and all the parse-params. # 'YYUSE' VAL, LOC if locations are enabled, and all the parse-params.
m4_define([b4_parse_param_use], m4_define([b4_parse_param_use],
[m4_ifvaln([$1], [ YYUSE ([$1]);])dnl [m4_ifvaln([$1], [ YYUSE ([$1]);])dnl
b4_locations_if([m4_ifvaln([$2], [ YYUSE ([$2]);])])dnl b4_locations_if([m4_ifvaln([$2], [ YYUSE ([$2]);])])dnl
@@ -182,7 +182,7 @@ m4_define([b4_int_type],
# b4_int_type_for(NAME) # b4_int_type_for(NAME)
# --------------------- # ---------------------
# Return the smallest int type able to handle numbers ranging from # 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], m4_define([b4_int_type_for],
[b4_int_type($1_min, $1_max)]) [b4_int_type($1_min, $1_max)])
@@ -199,6 +199,50 @@ m4_define([b4_table_value_equals],
[(!!(($2) == ($3)))])]) [(!!(($2) == ($3)))])])
## ----------------- ##
## Compiler issues. ##
## ----------------- ##
# b4_attribute_define
# -------------------
# Provide portability for __attribute__.
m4_define([b4_attribute_define],
[#ifndef __attribute__
/* This feature is available in gcc versions 2.5 and later. */
# if (! defined __GNUC__ || __GNUC__ < 2 \
|| (__GNUC__ == 2 && __GNUC_MINOR__ < 5))
# define __attribute__(Spec) /* empty */
# endif
#endif
/* Suppress unused-variable warnings by "using" E. */
#if ! defined lint || defined __GNUC__
# define YYUSE(E) ((void) (E))
#else
# define YYUSE(E) /* empty */
#endif
#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
/* Suppress an incorrect diagnostic about yylval being uninitialized. */
# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
_Pragma ("GCC diagnostic push") \
_Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
_Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
_Pragma ("GCC diagnostic pop")
#else
# define YY_INITIAL_VALUE(Value) Value
#endif
#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
# define YY_IGNORE_MAYBE_UNINITIALIZED_END
#endif
#ifndef YY_INITIAL_VALUE
# define YY_INITIAL_VALUE(Value) /* Nothing. */
#endif
])
## ---------## ## ---------##
## Values. ## ## Values. ##
## ---------## ## ---------##
@@ -421,12 +465,9 @@ m4_ifset([b4_parse_param], [, b4_parse_param]))[
yymsg = "Deleting"; yymsg = "Deleting";
YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
switch (yytype) YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
{ ]b4_symbol_actions([destructor])[
]b4_symbol_foreach([b4_symbol_destructor])dnl YY_IGNORE_MAYBE_UNINITIALIZED_END
[ default:
break;
}
}]dnl }]dnl
]) ])
@@ -436,9 +477,9 @@ m4_ifset([b4_parse_param], [, b4_parse_param]))[
# Define the "yy_symbol_print" function. # Define the "yy_symbol_print" function.
m4_define_default([b4_yy_symbol_print_define], m4_define_default([b4_yy_symbol_print_define],
[[ [[
/*--------------------------------. /*----------------------------------------.
| Print this symbol on YYOUTPUT. | | Print this symbol's value on YYOUTPUT. |
`--------------------------------*/ `----------------------------------------*/
]b4_function_define([yy_symbol_value_print], ]b4_function_define([yy_symbol_value_print],
[static void], [static void],
@@ -459,12 +500,7 @@ m4_if(b4_skeleton, ["yacc.c"],
YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
# endif # endif
]])dnl ]])dnl
[ switch (yytype) b4_symbol_actions([printer])[
{
]b4_symbol_foreach([b4_symbol_printer])dnl
[ default:
break;
}
} }
@@ -492,28 +528,154 @@ b4_locations_if([, yylocationp])[]b4_user_args[);
}]dnl }]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. ## ## Declarations. ##
## -------------- ## ## -------------- ##
# b4_value_type_define # b4_value_type_define
# -------------------- # --------------------
m4_define([b4_value_type_define], m4_define([b4_value_type_define],
[[/* Value type. */ [b4_value_type_setup[]dnl
#if ! defined ]b4_api_PREFIX[STYPE && ! defined ]b4_api_PREFIX[STYPE_IS_DECLARED /* Value type. */
]m4_ifdef([b4_stype], m4_bmatch(b4_percent_define_get_kind([[api.value.type]]),
[[typedef union ]b4_union_name[ ]b4_api_PREFIX[STYPE; [code],
union ]b4_union_name[ [[#if ! defined ]b4_api_PREFIX[STYPE && ! defined ]b4_api_PREFIX[STYPE_IS_DECLARED
{ typedef ]b4_percent_define_get([[api.value.type]])[ ]b4_api_PREFIX[STYPE;
]b4_user_stype[ # define ]b4_api_PREFIX[STYPE_IS_TRIVIAL 1
};
# 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_IS_DECLARED 1 # define ]b4_api_PREFIX[STYPE_IS_DECLARED 1
#endif #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_union_members[
};
# define ]b4_api_PREFIX[STYPE_IS_TRIVIAL 1
# define ]b4_api_PREFIX[STYPE_IS_DECLARED 1
#endif
]])])])
# b4_location_type_define # b4_location_type_define
@@ -549,7 +711,7 @@ b4_pure_if([], [[extern ]b4_api_PREFIX[STYPE ]b4_prefix[lval;
# b4_YYDEBUG_define # b4_YYDEBUG_define
# ------------------ # -----------------
m4_define([b4_YYDEBUG_define], m4_define([b4_YYDEBUG_define],
[[/* Debug traces. */ [[/* Debug traces. */
]m4_if(b4_api_prefix, [yy], ]m4_if(b4_api_prefix, [yy],
+1 -18
View File
@@ -246,13 +246,6 @@ b4_percent_code_get[]dnl
# endif # endif
#endif #endif
/* Suppress unused-variable warnings by "using" E. */
#ifdef __GNUC__
# define YYUSE(E) ((void) (E))
#else
# define YYUSE(E) /* empty */
#endif
#ifndef YYFREE #ifndef YYFREE
# define YYFREE free # define YYFREE free
#endif #endif
@@ -281,17 +274,7 @@ b4_percent_code_get[]dnl
# define YYLONGJMP(Env, Val) (longjmp (Env, Val), YYASSERT (0)) # define YYLONGJMP(Env, Val) (longjmp (Env, Val), YYASSERT (0))
#endif #endif
/*-----------------. ]b4_attribute_define[
| GCC extensions. |
`-----------------*/
#ifndef __attribute__
/* This feature is available in gcc versions 2.5 and later. */
# if (! defined __GNUC__ || __GNUC__ < 2 \
|| (__GNUC__ == 2 && __GNUC_MINOR__ < 5))
# define __attribute__(Spec) /* empty */
# endif
#endif
#ifndef YYASSERT #ifndef YYASSERT
# define YYASSERT(Condition) ((void) ((Condition) || (abort (), 0))) # define YYASSERT(Condition) ((void) ((Condition) || (abort (), 0)))
+1 -12
View File
@@ -43,12 +43,6 @@
# user must initialize the first positions (in particular the # user must initialize the first positions (in particular the
# filename member). # filename member).
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]))])])
# We require a pure interface. # We require a pure interface.
m4_define([b4_pure_flag], [1]) m4_define([b4_pure_flag], [1])
@@ -193,12 +187,7 @@ m4_pushdef([b4_parse_param], m4_defn([b4_parse_param_orig]))dnl
std::ostream& yyoutput = debug_stream (); std::ostream& yyoutput = debug_stream ();
std::ostream& yyo = yyoutput; std::ostream& yyo = yyoutput;
YYUSE (yyo); YYUSE (yyo);
switch (yytype) ]b4_symbol_actions([printer])[
{
]b4_symbol_foreach([b4_symbol_printer])dnl
[ default:
break;
}
} }
+17 -1
View File
@@ -103,7 +103,7 @@ m4_define([b4_int_type],
# b4_int_type_for(NAME) # b4_int_type_for(NAME)
# --------------------- # ---------------------
# Return the smallest int type able to handle numbers ranging from # 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], m4_define([b4_int_type_for],
[b4_int_type($1_min, $1_max)]) [b4_int_type($1_min, $1_max)])
@@ -169,6 +169,22 @@ m4_define([b4_predicate_case], [ case $1:
]) ])
## -------- ##
## Checks. ##
## -------- ##
b4_percent_define_check_kind([[api.value.type]], [code], [deprecated])
b4_percent_define_check_kind([[annotations]], [code], [deprecated])
b4_percent_define_check_kind([[extends]], [code], [deprecated])
b4_percent_define_check_kind([[implements]], [code], [deprecated])
b4_percent_define_check_kind([[init_throws]], [code], [deprecated])
b4_percent_define_check_kind([[lex_throws]], [code], [deprecated])
b4_percent_define_check_kind([[parser_class_name]], [code], [deprecated])
b4_percent_define_check_kind([[throws]], [code], [deprecated])
## ---------------- ## ## ---------------- ##
## Default values. ## ## Default values. ##
## ---------------- ## ## ---------------- ##
+14 -18
View File
@@ -17,6 +17,8 @@
m4_include(b4_pkgdatadir/[c++.m4]) m4_include(b4_pkgdatadir/[c++.m4])
# api.value.type=variant is valid.
m4_define([b4_value_type_setup_variant])
# b4_integral_parser_table_declare(TABLE-NAME, CONTENT, COMMENT) # b4_integral_parser_table_declare(TABLE-NAME, CONTENT, COMMENT)
# -------------------------------------------------------------- # --------------------------------------------------------------
@@ -38,13 +40,14 @@ m4_define([b4_integral_parser_table_define],
};dnl };dnl
]) ])
# b4_symbol_value_template(VAL, [TYPE]) # b4_symbol_value_template(VAL, [TYPE])
# ------------------------------------- # -------------------------------------
# Same as b4_symbol_value, but used in a template method. It makes # Same as b4_symbol_value, but used in a template method. It makes
# a difference when using variants. # 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_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]) # b4_lhs_value([TYPE])
# -------------------- # --------------------
@@ -201,6 +204,10 @@ b4_location_define])])[
void error (const syntax_error& err); void error (const syntax_error& err);
private: 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[&);
/// State numbers. /// State numbers.
typedef int state_type; typedef int state_type;
@@ -591,13 +598,7 @@ m4_if(b4_prefix, [yy], [],
YY_SYMBOL_PRINT (yymsg, yysym);]b4_variant_if([], [ YY_SYMBOL_PRINT (yymsg, yysym);]b4_variant_if([], [
// User destructor. // User destructor.
symbol_number_type yytype = yysym.type_get (); b4_symbol_actions([destructor], [yysym.type_get ()])])[
switch (yytype)
{
]b4_symbol_foreach([b4_symbol_destructor])dnl
[ default:
break;
}])[
} }
#if ]b4_api_PREFIX[DEBUG #if ]b4_api_PREFIX[DEBUG
@@ -612,12 +613,7 @@ m4_if(b4_prefix, [yy], [],
yyo << (yytype < yyntokens_ ? "token" : "nterm") yyo << (yytype < yyntokens_ ? "token" : "nterm")
<< ' ' << yytname_[yytype] << " ("]b4_locations_if([ << ' ' << yytname_[yytype] << " ("]b4_locations_if([
<< yysym.location << ": "])[; << yysym.location << ": "])[;
switch (yytype) ]b4_symbol_actions([printer])[
{
]b4_symbol_foreach([b4_symbol_printer])dnl
[ default:
break;
}
yyo << ')'; yyo << ')';
} }
#endif #endif
@@ -737,7 +733,7 @@ b4_dollar_popdef])[]dnl
yynewstate, since the latter expects the semantical and the yynewstate, since the latter expects the semantical and the
location values to have been already stored, initialize these location values to have been already stored, initialize these
stacks with a primary value. */ stacks with a primary value. */
yystack_ = stack_type (0); yystack_.clear ();
yypush_ (YY_NULL, 0, yyla); yypush_ (YY_NULL, 0, yyla);
// A new symbol was pushed on the stack. // A new symbol was pushed on the stack.
@@ -824,7 +820,7 @@ b4_dollar_popdef])[]dnl
variants. */ variants. */
b4_symbol_variant([[yyr1_@{yyn@}]], [yylhs.value], [build])],[ b4_symbol_variant([[yyr1_@{yyn@}]], [yylhs.value], [build])],[
/* If YYLEN is nonzero, implement the default value of the action: /* 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 YYLHS.VALUE to garbage. Otherwise, the following line sets YYLHS.VALUE to garbage.
This behavior is undocumented and Bison This behavior is undocumented and Bison
+260 -71
View File
@@ -20,7 +20,8 @@ m4_include(b4_pkgdatadir/[java.m4])
b4_defines_if([b4_fatal([%s: %%defines does not make sense in Java], b4_defines_if([b4_fatal([%s: %%defines does not make sense in Java],
[b4_skeleton])]) [b4_skeleton])])
# We don't depend on %debug in Java, but pacify warnings about non-used flags. # We do not depend on %debug in Java, but pacify warnings about
# non-used flags.
b4_parse_trace_if([0], [0]) b4_parse_trace_if([0], [0])
m4_define([b4_symbol_no_destructor_assert], m4_define([b4_symbol_no_destructor_assert],
@@ -30,6 +31,57 @@ m4_define([b4_symbol_no_destructor_assert],
[b4_symbol_action_location([$1], [destructor])])])]) [b4_symbol_action_location([$1], [destructor])])])])
b4_symbol_foreach([b4_symbol_no_destructor_assert]) b4_symbol_foreach([b4_symbol_no_destructor_assert])
# Setup some macros for api.push-pull.
b4_percent_define_default([[api.push-pull]], [[pull]])
b4_percent_define_check_values([[[[api.push-pull]],
[[pull]], [[push]], [[both]]]])
# Define m4 conditional macros that encode the value
# of the api.push-pull flag.
b4_define_flag_if([pull]) m4_define([b4_pull_flag], [[1]])
b4_define_flag_if([push]) m4_define([b4_push_flag], [[1]])
m4_case(b4_percent_define_get([[api.push-pull]]),
[pull], [m4_define([b4_push_flag], [[0]])],
[push], [m4_define([b4_pull_flag], [[0]])])
# Define a macro to be true when api.push-pull has the value "both".
m4_define([b4_both_if],[b4_push_if([b4_pull_if([$1],[$2])],[$2])])
# Handle BISON_USE_PUSH_FOR_PULL for the test suite. So that push parsing
# tests function as written, do not let BISON_USE_PUSH_FOR_PULL modify the
# behavior of Bison at all when push parsing is already requested.
b4_define_flag_if([use_push_for_pull])
b4_use_push_for_pull_if([
b4_push_if([m4_define([b4_use_push_for_pull_flag], [[0]])],
[m4_define([b4_push_flag], [[1]])])])
# Define a macro to encapsulate the parse state variables.
# This allows them to be defined either in parse() when doing
# pull parsing, or as class instance variable when doing push parsing.
m4_define([b4_define_state],[[
/* Lookahead and lookahead in internal form. */
int yychar = yyempty_;
int yytoken = 0;
/* State. */
int yyn = 0;
int yylen = 0;
int yystate = 0;
YYStack yystack = new YYStack ();
int label = YYNEWSTATE;
/* Error handling. */
int yynerrs_ = 0;
]b4_locations_if([/* The location where the error started. */
b4_location_type yyerrloc = null;
/* Location. */
b4_location_type yylloc = new b4_location_type (null, null);])[
/* Semantic value of the lookahead. */
]b4_yystype[ yylval = null;
]])
b4_output_begin([b4_parser_file_name]) b4_output_begin([b4_parser_file_name])
b4_copyright([Skeleton implementation for Bison LALR(1) parsers in Java], b4_copyright([Skeleton implementation for Bison LALR(1) parsers in Java],
[2007-2013]) [2007-2013])
@@ -55,7 +107,9 @@ b4_percent_define_get3([implements], [ implements ])[
{ {
]b4_identification[ ]b4_identification[
]b4_error_verbose_if([[ ]b4_error_verbose_if([[
/** True if verbose error messages are enabled. */ /**
* True if verbose error messages are enabled.
*/
private boolean yyErrorVerbose = true; private boolean yyErrorVerbose = true;
/** /**
@@ -76,18 +130,24 @@ b4_locations_if([[
* A class defining a pair of positions. Positions, defined by the * A class defining a pair of positions. Positions, defined by the
* <code>]b4_position_type[</code> class, denote a point in the input. * <code>]b4_position_type[</code> class, denote a point in the input.
* Locations represent a part of the input through the beginning * Locations represent a part of the input through the beginning
* and ending positions. */ * and ending positions.
*/
public class ]b4_location_type[ { public class ]b4_location_type[ {
/** The first, inclusive, position in the range. */ /**
* The first, inclusive, position in the range.
*/
public ]b4_position_type[ begin; public ]b4_position_type[ begin;
/** The first position beyond the range. */ /**
* The first position beyond the range.
*/
public ]b4_position_type[ end; public ]b4_position_type[ end;
/** /**
* Create a <code>]b4_location_type[</code> denoting an empty range located at * Create a <code>]b4_location_type[</code> denoting an empty range located at
* a given point. * a given point.
* @@param loc The position at which the range is anchored. */ * @@param loc The position at which the range is anchored.
*/
public ]b4_location_type[ (]b4_position_type[ loc) { public ]b4_location_type[ (]b4_position_type[ loc) {
this.begin = this.end = loc; this.begin = this.end = loc;
} }
@@ -95,7 +155,8 @@ b4_locations_if([[
/** /**
* Create a <code>]b4_location_type[</code> from the endpoints of the range. * Create a <code>]b4_location_type[</code> from the endpoints of the range.
* @@param begin The first position included in the range. * @@param begin The first position included in the range.
* @@param end The first position beyond the range. */ * @@param end The first position beyond the range.
*/
public ]b4_location_type[ (]b4_position_type[ begin, ]b4_position_type[ end) { public ]b4_location_type[ (]b4_position_type[ begin, ]b4_position_type[ end) {
this.begin = begin; this.begin = begin;
this.end = end; this.end = end;
@@ -104,7 +165,8 @@ b4_locations_if([[
/** /**
* Print a representation of the location. For this to be correct, * Print a representation of the location. For this to be correct,
* <code>]b4_position_type[</code> should override the <code>equals</code> * <code>]b4_position_type[</code> should override the <code>equals</code>
* method. */ * method.
*/
public String toString () { public String toString () {
if (begin.equals (end)) if (begin.equals (end))
return begin.toString (); return begin.toString ();
@@ -136,24 +198,28 @@ b4_locations_if([[
]b4_locations_if([[/** ]b4_locations_if([[/**
* Method to retrieve the beginning position of the last scanned token. * Method to retrieve the beginning position of the last scanned token.
* @@return the position at which the last scanned token starts. */ * @@return the position at which the last scanned token starts.
*/
]b4_position_type[ getStartPos (); ]b4_position_type[ getStartPos ();
/** /**
* Method to retrieve the ending position of the last scanned token. * Method to retrieve the ending position of the last scanned token.
* @@return the first position beyond the last scanned token. */ * @@return the first position beyond the last scanned token.
*/
]b4_position_type[ getEndPos ();]])[ ]b4_position_type[ getEndPos ();]])[
/** /**
* Method to retrieve the semantic value of the last scanned token. * Method to retrieve the semantic value of the last scanned token.
* @@return the semantic value of the last scanned token. */ * @@return the semantic value of the last scanned token.
*/
]b4_yystype[ getLVal (); ]b4_yystype[ getLVal ();
/** /**
* Entry point for the scanner. Returns the token identifier corresponding * Entry point for the scanner. Returns the token identifier corresponding
* to the next token and prepares to return the semantic value * to the next token and prepares to return the semantic value
* ]b4_locations_if([and beginning/ending positions ])[of the token. * ]b4_locations_if([and beginning/ending positions ])[of the token.
* @@return the token identifier corresponding to the next token. */ * @@return the token identifier corresponding to the next token.
*/
int yylex () ]b4_maybe_throws([b4_lex_throws])[; int yylex () ]b4_maybe_throws([b4_lex_throws])[;
/** /**
@@ -162,7 +228,8 @@ b4_locations_if([[
* *
* ]b4_locations_if([[@@param loc The location of the element to which the * ]b4_locations_if([[@@param loc The location of the element to which the
* error message is related]])[ * error message is related]])[
* @@param msg The string for the error message. */ * @@param msg The string for the error message.
*/
void yyerror (]b4_locations_if([b4_location_type[ loc, ]])[String msg);] void yyerror (]b4_locations_if([b4_location_type[ loc, ]])[String msg);]
} }
@@ -170,7 +237,9 @@ b4_locations_if([[
]b4_percent_code_get([[lexer]])[ ]b4_percent_code_get([[lexer]])[
} }
]])[/** The object doing lexical analysis for us. */ ]])[/**
* The object doing lexical analysis for us.
*/
private Lexer yylexer; private Lexer yylexer;
] ]
b4_parse_param_vars b4_parse_param_vars
@@ -336,34 +405,49 @@ b4_lexer_if([[
/** /**
* Returned by a Bison action in order to stop the parsing process and * Returned by a Bison action in order to stop the parsing process and
* return success (<tt>true</tt>). */ * return success (<tt>true</tt>).
*/
public static final int YYACCEPT = 0; public static final int YYACCEPT = 0;
/** /**
* Returned by a Bison action in order to stop the parsing process and * Returned by a Bison action in order to stop the parsing process and
* return failure (<tt>false</tt>). */ * return failure (<tt>false</tt>).
*/
public static final int YYABORT = 1; public static final int YYABORT = 1;
]b4_push_if([
/**
* Returned by a Bison action in order to request a new token.
*/
public static final int YYPUSH_MORE = 4;])[
/** /**
* Returned by a Bison action in order to start error recovery without * Returned by a Bison action in order to start error recovery without
* printing an error message. */ * printing an error message.
*/
public static final int YYERROR = 2; public static final int YYERROR = 2;
// Internal return codes that are not supported for user semantic /**
// actions. * Internal return codes that are not supported for user semantic
* actions.
*/
private static final int YYERRLAB = 3; private static final int YYERRLAB = 3;
private static final int YYNEWSTATE = 4; private static final int YYNEWSTATE = 4;
private static final int YYDEFAULT = 5; private static final int YYDEFAULT = 5;
private static final int YYREDUCE = 6; private static final int YYREDUCE = 6;
private static final int YYERRLAB1 = 7; private static final int YYERRLAB1 = 7;
private static final int YYRETURN = 8; private static final int YYRETURN = 8;
]b4_push_if([[ private static final int YYGETTOKEN = 9; /* Signify that a new token is expected when doing push-parsing. */]])[
private int yyerrstatus_ = 0; private int yyerrstatus_ = 0;
]b4_push_if([dnl
b4_define_state])[
/** /**
* Return whether error recovery is being done. In this state, the parser * Return whether error recovery is being done. In this state, the parser
* reads token until it reaches a known state, and then restarts normal * reads token until it reaches a known state, and then restarts normal
* operation. */ * operation.
*/
public final boolean recovering () public final boolean recovering ()
{ {
return yyerrstatus_ == 0; return yyerrstatus_ == 0;
@@ -375,7 +459,7 @@ b4_lexer_if([[
]b4_locations_if([b4_location_type[ yyloc = yylloc (yystack, yylen);]])[ ]b4_locations_if([b4_location_type[ yyloc = yylloc (yystack, yylen);]])[
/* If YYLEN is nonzero, implement the default value of the action: /* 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 YYVAL to garbage.
This behavior is undocumented and Bison This behavior is undocumented and Bison
@@ -463,6 +547,7 @@ b4_lexer_if([[
+ (yyvaluep == null ? "(null)" : yyvaluep.toString ()) + ")"); + (yyvaluep == null ? "(null)" : yyvaluep.toString ()) + ")");
} }
]b4_push_if([],[[
/** /**
* Parse input from the scanner that was specified at object construction * Parse input from the scanner that was specified at object construction
* time. Return whether the end of the input was reached successfully. * time. Return whether the end of the input was reached successfully.
@@ -470,46 +555,53 @@ b4_lexer_if([[
* @@return <tt>true</tt> if the parsing succeeds. Note that this does not * @@return <tt>true</tt> if the parsing succeeds. Note that this does not
* imply that there were no syntax errors. * imply that there were no syntax errors.
*/ */
public boolean parse () ]b4_maybe_throws([b4_list2([b4_lex_throws], [b4_throws])])[ public boolean parse () ]b4_maybe_throws([b4_list2([b4_lex_throws], [b4_throws])])[]])[
]b4_push_if([
/**
* Push Parse input from external lexer
*
* @@param yylextoken current token
* @@param yylexval current lval
]b4_locations_if([ * @@param yylexloc current position])[
*
* @@return <tt>YYACCEPT, YYABORT, YYPUSH_MORE</tt>
*/
public int push_parse (int yylextoken, b4_yystype yylexval[]b4_locations_if([, b4_location_type yylexloc]))
b4_maybe_throws([b4_list2([b4_lex_throws], [b4_throws])])])[
{ {
/// Lookahead and lookahead in internal form. ]b4_locations_if([/* @@$. */
int yychar = yyempty_; b4_location_type yyloc;])[
int yytoken = 0; ]b4_push_if([],[[
]b4_define_state[
/* State. */
int yyn = 0;
int yylen = 0;
int yystate = 0;
YYStack yystack = new YYStack ();
/* Error handling. */
int yynerrs_ = 0;
]b4_locations_if([/// The location where the error started.
]b4_location_type[ yyerrloc = null;
/// ]b4_location_type[ of the lookahead.
]b4_location_type[ yylloc = new ]b4_location_type[ (null, null);
/// @@$.
]b4_location_type[ yyloc;])
/// Semantic value of the lookahead.
b4_yystype[ yylval = null;
yycdebug ("Starting parse\n"); yycdebug ("Starting parse\n");
yyerrstatus_ = 0; yyerrstatus_ = 0;
/* Initialize the stack. */
yystack.push (yystate, yylval ]b4_locations_if([, yylloc])[);
]m4_ifdef([b4_initial_action], [ ]m4_ifdef([b4_initial_action], [
b4_dollar_pushdef([yylval], [], [yylloc])dnl b4_dollar_pushdef([yylval], [], [yylloc])dnl
/* User initialization code. */ /* User initialization code. */
b4_user_initial_action b4_user_initial_action
b4_dollar_popdef])[]dnl b4_dollar_popdef[]dnl
])[
]])[
]b4_push_if([[
if (!this.push_parse_initialized)
{
push_parse_initialize ();
]m4_ifdef([b4_initial_action], [
b4_dollar_pushdef([yylval], [], [yylloc])dnl
/* User initialization code. */
b4_user_initial_action
b4_dollar_popdef[]dnl
])[
yycdebug ("Starting parse\n");
yyerrstatus_ = 0;
} else
label = YYGETTOKEN;
[ /* Initialize the stack. */ boolean push_token_consumed = true;
yystack.push (yystate, yylval]b4_locations_if([, yylloc])[); ]])[
int label = YYNEWSTATE;
for (;;) for (;;)
switch (label) switch (label)
{ {
@@ -522,7 +614,8 @@ b4_dollar_popdef])[]dnl
/* Accept? */ /* Accept? */
if (yystate == yyfinal_) if (yystate == yyfinal_)
return true; ]b4_push_if([{label = YYACCEPT; break;}],
[return true;])[
/* Take a decision. First try without lookahead. */ /* Take a decision. First try without lookahead. */
yyn = yypact_[yystate]; yyn = yypact_[yystate];
@@ -531,16 +624,27 @@ b4_dollar_popdef])[]dnl
label = YYDEFAULT; label = YYDEFAULT;
break; break;
} }
]b4_push_if([ /* Fall Through */
case YYGETTOKEN:])[
/* Read a lookahead token. */ /* Read a lookahead token. */
if (yychar == yyempty_) if (yychar == yyempty_)
{ {
]b4_push_if([[
if (!push_token_consumed)
return YYPUSH_MORE;
yycdebug ("Reading a token: "); yycdebug ("Reading a token: ");
yychar = yylexer.yylex ();] yychar = yylextoken;
b4_locations_if([[ yylval = yylexval;]b4_locations_if([
yylloc = new ]b4_location_type[(yylexer.getStartPos (), yylloc = yylexloc;])[
yylexer.getEndPos ());]]) push_token_consumed = false;]])[
yylval = yylexer.getLVal ();[ ]b4_push_if([],[[
yycdebug ("Reading a token: ");
yychar = yylexer.yylex ();
yylval = yylexer.getLVal ();]b4_locations_if([
yylloc = new b4_location_type (yylexer.getStartPos (),
yylexer.getEndPos ());])[
]])[
} }
/* Convert token to internal form. */ /* Convert token to internal form. */
@@ -637,10 +741,10 @@ b4_dollar_popdef])[]dnl
{ {
/* Return failure if at end of input. */ /* Return failure if at end of input. */
if (yychar == Lexer.EOF) if (yychar == Lexer.EOF)
return false; ]b4_push_if([{label = YYABORT; break;}],[return false;])[
} }
else else
yychar = yyempty_; yychar = yyempty_;
} }
/* Else will try to reuse lookahead token after shifting the error /* Else will try to reuse lookahead token after shifting the error
@@ -648,9 +752,9 @@ b4_dollar_popdef])[]dnl
label = YYERRLAB1; label = YYERRLAB1;
break; break;
/*---------------------------------------------------. /*-------------------------------------------------.
| errorlab -- error raised explicitly by YYERROR. | | errorlab -- error raised explicitly by YYERROR. |
`---------------------------------------------------*/ `-------------------------------------------------*/
case YYERROR: case YYERROR:
]b4_locations_if([yyerrloc = yystack.locationAt (yylen - 1);])[ ]b4_locations_if([yyerrloc = yystack.locationAt (yylen - 1);])[
@@ -682,9 +786,10 @@ b4_dollar_popdef])[]dnl
} }
} }
/* Pop the current state because it cannot handle the error token. */ /* Pop the current state because it cannot handle the
* error token. */
if (yystack.height == 0) if (yystack.height == 0)
return false; ]b4_push_if([{label = YYABORT; break;}],[return false;])[
]b4_locations_if([yyerrloc = yystack.locationAt (0);])[ ]b4_locations_if([yyerrloc = yystack.locationAt (0);])[
yystack.pop (); yystack.pop ();
@@ -693,7 +798,11 @@ b4_dollar_popdef])[]dnl
yystack.print (yyDebugStream); yystack.print (yyDebugStream);
} }
]b4_locations_if([ if (label == YYABORT)
/* Leave the switch. */
break;
]b4_locations_if([
/* Muck with the stack to setup for yylloc. */ /* Muck with the stack to setup for yylloc. */
yystack.push (0, null, yylloc); yystack.push (0, null, yylloc);
yystack.push (0, null, yyerrloc); yystack.push (0, null, yyerrloc);
@@ -711,13 +820,91 @@ b4_dollar_popdef])[]dnl
/* Accept. */ /* Accept. */
case YYACCEPT: case YYACCEPT:
return true; ]b4_push_if([this.push_parse_initialized = false; return YYACCEPT;],
[return true;])[
/* Abort. */ /* Abort. */
case YYABORT: case YYABORT:
return false; ]b4_push_if([this.push_parse_initialized = false; return YYABORT;],
[return false;])[
} }
}
]b4_push_if([[
boolean push_parse_initialized = false;
/**
* (Re-)Initialize the state of the push parser.
*/
public void push_parse_initialize()
{
/* Lookahead and lookahead in internal form. */
this.yychar = yyempty_;
this.yytoken = 0;
/* State. */
this.yyn = 0;
this.yylen = 0;
this.yystate = 0;
this.yystack = new YYStack ();
this.label = YYNEWSTATE;
/* Error handling. */
this.yynerrs_ = 0;
]b4_locations_if([/* The location where the error started. */
this.yyerrloc = null;
this.yylloc = new b4_location_type (null, null);])[
/* Semantic value of the lookahead. */
this.yylval = null;
yystack.push (this.yystate, this.yylval]b4_locations_if([, this.yylloc])[);
this.push_parse_initialized = true;
} }
]b4_locations_if([
/**
* Push parse given input from an external lexer.
*
* @@param yylextoken current token
* @@param yylexval current lval
* @@param yyylexpos current position
*
* @@return <tt>YYACCEPT, YYABORT, YYPUSH_MORE</tt>
*/
public int push_parse (int yylextoken, b4_yystype yylexval, b4_position_type yylexpos)
b4_maybe_throws([b4_list2([b4_lex_throws], [b4_throws])])
{
return push_parse (yylextoken, yylexval, new b4_location_type (yylexpos));
}
])[]])
b4_both_if([[
/**
* Parse input from the scanner that was specified at object construction
* time. Return whether the end of the input was reached successfully.
* This version of parse () is defined only when api.push-push=both.
*
* @@return <tt>true</tt> if the parsing succeeds. Note that this does not
* imply that there were no syntax errors.
*/
public boolean parse () ]b4_maybe_throws([b4_list2([b4_lex_throws], [b4_throws])])[
{
if (yylexer == null)
throw new NullPointerException("Null Lexer");
int status;
do {
int token = yylexer.yylex();
]b4_yystype[ lval = yylexer.getLVal();
]b4_locations_if([dnl
b4_location_type yyloc = new b4_location_type (yylexer.getStartPos (),
yylexer.getEndPos ());])[
]b4_locations_if([status = push_parse(token,lval,yyloc);],[
status = push_parse(token,lval);])[
} while (status == YYPUSH_MORE);
return (status == YYACCEPT);
}
]])[
// Generate an error message. // Generate an error message.
private String yysyntax_error (int yystate, int tok) private String yysyntax_error (int yystate, int tok)
@@ -752,8 +939,8 @@ b4_dollar_popdef])[]dnl
*/ */
if (tok != yyempty_) if (tok != yyempty_)
{ {
// FIXME: This method of building the message is not compatible /* FIXME: This method of building the message is not compatible
// with internationalization. with internationalization. */
StringBuffer res = StringBuffer res =
new StringBuffer ("syntax error, unexpected "); new StringBuffer ("syntax error, unexpected ");
res.append (yytnamerr_ (yytname_[tok])); res.append (yytnamerr_ (yytname_[tok]));
@@ -802,8 +989,9 @@ b4_dollar_popdef])[]dnl
} }
/** /**
* Whether the given <code>yytable_</code> value indicates a syntax error. * Whether the given <code>yytable_</code>
* @@param yyvalue the value to check * value indicates a syntax error.
* @@param yyvalue the value to check
*/ */
private static boolean yy_table_value_is_error_ (int yyvalue) private static boolean yy_table_value_is_error_ (int yyvalue)
{ {
@@ -825,6 +1013,7 @@ b4_dollar_popdef])[]dnl
]b4_integral_parser_table_define([rline], [b4_rline], ]b4_integral_parser_table_define([rline], [b4_rline],
[[YYRLINE[YYN] -- Source line where rule number YYN was defined.]])[ [[YYRLINE[YYN] -- Source line where rule number YYN was defined.]])[
// Report on the debug stream that the rule yyrule is going to be reduced. // Report on the debug stream that the rule yyrule is going to be reduced.
private void yy_reduce_print (int yyrule, YYStack yystack) private void yy_reduce_print (int yyrule, YYStack yystack)
{ {
+43 -24
View File
@@ -25,8 +25,7 @@ m4_define([b4_position_define],
[[ /// Abstract a position. [[ /// Abstract a position.
class position class position
{ {
public: public:]m4_ifdef([b4_location_constructors], [[
]m4_ifdef([b4_location_constructors], [[
/// Construct a position. /// Construct a position.
explicit position (]b4_percent_define_get([[filename_type]])[* f = YY_NULL, explicit position (]b4_percent_define_get([[filename_type]])[* f = YY_NULL,
unsigned int l = ]b4_location_initial_line[u, unsigned int l = ]b4_location_initial_line[u,
@@ -53,14 +52,17 @@ m4_define([b4_position_define],
/// (line related) Advance to the COUNT next lines. /// (line related) Advance to the COUNT next lines.
void lines (int count = 1) void lines (int count = 1)
{ {
column = ]b4_location_initial_column[u; if (count)
line += count; {
column = ]b4_location_initial_column[u;
line = add_ (line, count, ]b4_location_initial_line[);
}
} }
/// (column related) Advance to the COUNT next columns. /// (column related) Advance to the COUNT next columns.
void columns (int count = 1) void columns (int count = 1)
{ {
column = std::max (]b4_location_initial_column[u, column + count); column = add_ (column, count, ]b4_location_initial_column[);
} }
/** \} */ /** \} */
@@ -70,36 +72,44 @@ m4_define([b4_position_define],
unsigned int line; unsigned int line;
/// Current column number. /// Current column number.
unsigned int column; unsigned int column;
private:
/// Compute max(min, lhs+rhs) (provided min <= lhs).
static unsigned int add_ (unsigned int lhs, int rhs, unsigned int min)
{
return (0 < rhs || -static_cast<unsigned int>(rhs) < lhs
? rhs + lhs
: min);
}
}; };
/// Add and assign a position. /// Add and assign a position.
inline position& inline position&
operator+= (position& res, const int width) operator+= (position& res, int width)
{ {
res.columns (width); res.columns (width);
return res; return res;
} }
/// Add two position objects. /// Add two position objects.
inline const position inline position
operator+ (const position& begin, const int width) operator+ (position res, int width)
{ {
position res = begin;
return res += width; return res += width;
} }
/// Add and assign a position. /// Add and assign a position.
inline position& inline position&
operator-= (position& res, const int width) operator-= (position& res, int width)
{ {
return res += -width; return res += -width;
} }
/// Add two position objects. /// Add two position objects.
inline const position inline position
operator- (const position& begin, const int width) operator- (position res, int width)
{ {
return begin + -width; return res -= width;
} }
]b4_percent_define_flag_if([[define_location_comparison]], [[ ]b4_percent_define_flag_if([[define_location_comparison]], [[
/// Compare two position objects. /// Compare two position objects.
@@ -186,13 +196,13 @@ m4_define([b4_location_define],
} }
/// Extend the current location to the COUNT next columns. /// Extend the current location to the COUNT next columns.
void columns (unsigned int count = 1) void columns (int count = 1)
{ {
end += count; end += count;
} }
/// Extend the current location to the COUNT next lines. /// Extend the current location to the COUNT next lines.
void lines (unsigned int count = 1) void lines (int count = 1)
{ {
end.lines (count); end.lines (count);
} }
@@ -207,26 +217,35 @@ m4_define([b4_location_define],
}; };
/// Join two location objects to create a location. /// Join two location objects to create a location.
inline const location operator+ (const location& begin, const location& end) inline location operator+ (location res, const location& end)
{ {
location res = begin;
res.end = end.end; res.end = end.end;
return res; return res;
} }
/// Add two location objects. /// Change end position in place.
inline const location operator+ (const location& begin, unsigned int width) inline location& operator+= (location& res, int width)
{ {
location res = begin;
res.columns (width); res.columns (width);
return res; return res;
} }
/// Add and assign a location. /// Change end position.
inline location& operator+= (location& res, unsigned int width) inline location operator+ (location res, int width)
{ {
res.columns (width); return res += width;
return res; }
/// Change end position in place.
inline location& operator-= (location& res, int width)
{
return res += -width;
}
/// Change end position.
inline location operator- (const location& begin, int width)
{
return begin + -width;
} }
]b4_percent_define_flag_if([[define_location_comparison]], [[ ]b4_percent_define_flag_if([[define_location_comparison]], [[
/// Compare two location objects. /// Compare two location objects.
+8
View File
@@ -72,6 +72,12 @@ m4_define([b4_stack_define],
seq_.pop_back (); seq_.pop_back ();
} }
void
clear ()
{
seq_.clear ();
}
inline inline
typename S::size_type typename S::size_type
size () const size () const
@@ -94,6 +100,8 @@ m4_define([b4_stack_define],
} }
private: private:
stack (const stack&);
stack& operator= (const stack&);
/// The wrapped container. /// The wrapped container.
S seq_; S seq_;
}; };
+56 -39
View File
@@ -26,7 +26,7 @@
# YYTYPE. # YYTYPE.
m4_define([b4_symbol_variant], m4_define([b4_symbol_variant],
[m4_pushdef([b4_dollar_dollar], [m4_pushdef([b4_dollar_dollar],
[$2.$3< $][3 >(m4_shift3($@))])dnl [$2.$3< $][3 > (m4_shift3($@))])dnl
switch ($1) switch ($1)
{ {
b4_type_foreach([b4_type_action_])[]dnl b4_type_foreach([b4_type_action_])[]dnl
@@ -63,7 +63,7 @@ m4_define([b4_char_sizeof],
[b4_symbol_if([$1], [has_type], [b4_symbol_if([$1], [has_type],
[ [
m4_map([ b4_symbol_tag_comment], [$@])dnl m4_map([ b4_symbol_tag_comment], [$@])dnl
char _b4_char_sizeof_dummy@{sizeof([b4_symbol([$1], [type])])@}; char _b4_char_sizeof_dummy@{sizeof(b4_symbol([$1], [type]))@};
])]) ])])
@@ -95,22 +95,22 @@ m4_define([b4_variant_define],
/// Empty construction. /// Empty construction.
variant ()]b4_parse_assert_if([ variant ()]b4_parse_assert_if([
: tname (YY_NULL)])[ : yytname_ (YY_NULL)])[
{} {}
/// Construct and fill. /// Construct and fill.
template <typename T> template <typename T>
variant (const T& t)]b4_parse_assert_if([ variant (const T& t)]b4_parse_assert_if([
: tname (typeid (T).name ())])[ : yytname_ (typeid (T).name ())])[
{ {
YYASSERT (sizeof (T) <= S); YYASSERT (sizeof (T) <= S);
new (buffer.raw) T (t); new (yyas_<T> ()) T (t);
} }
/// Destruction, allowed only if empty. /// Destruction, allowed only if empty.
~variant () ~variant ()
{]b4_parse_assert_if([ {]b4_parse_assert_if([
YYASSERT (!tname); YYASSERT (!yytname_);
])[} ])[}
/// Instantiate an empty \a T in here. /// Instantiate an empty \a T in here.
@@ -118,10 +118,10 @@ m4_define([b4_variant_define],
T& T&
build () build ()
{]b4_parse_assert_if([ {]b4_parse_assert_if([
YYASSERT (!tname); YYASSERT (!yytname_);
YYASSERT (sizeof (T) <= S); YYASSERT (sizeof (T) <= S);
tname = typeid (T).name ();])[ yytname_ = typeid (T).name ();])[
return *new (buffer.raw) T; return *new (yyas_<T> ()) T;
} }
/// Instantiate a \a T in here from \a t. /// Instantiate a \a T in here from \a t.
@@ -129,10 +129,10 @@ m4_define([b4_variant_define],
T& T&
build (const T& t) build (const T& t)
{]b4_parse_assert_if([ {]b4_parse_assert_if([
YYASSERT (!tname); YYASSERT (!yytname_);
YYASSERT (sizeof (T) <= S); YYASSERT (sizeof (T) <= S);
tname = typeid (T).name ();])[ yytname_ = typeid (T).name ();])[
return *new (buffer.raw) T (t); return *new (yyas_<T> ()) T (t);
} }
/// Accessor to a built \a T. /// Accessor to a built \a T.
@@ -140,9 +140,9 @@ m4_define([b4_variant_define],
T& T&
as () as ()
{]b4_parse_assert_if([ {]b4_parse_assert_if([
YYASSERT (tname == typeid (T).name ()); YYASSERT (yytname_ == typeid (T).name ());
YYASSERT (sizeof (T) <= S);])[ YYASSERT (sizeof (T) <= S);])[
return reinterpret_cast<T&> (buffer.raw); return *yyas_<T> ();
} }
/// Const accessor to a built \a T (for %printer). /// Const accessor to a built \a T (for %printer).
@@ -150,9 +150,9 @@ m4_define([b4_variant_define],
const T& const T&
as () const as () const
{]b4_parse_assert_if([ {]b4_parse_assert_if([
YYASSERT (tname == typeid (T).name ()); YYASSERT (yytname_ == typeid (T).name ());
YYASSERT (sizeof (T) <= S);])[ YYASSERT (sizeof (T) <= S);])[
return reinterpret_cast<const T&> (buffer.raw); return *yyas_<T> ();
} }
/// Swap the content with \a other, of same type. /// Swap the content with \a other, of same type.
@@ -167,9 +167,9 @@ m4_define([b4_variant_define],
void void
swap (self_type& other) swap (self_type& other)
{]b4_parse_assert_if([ {]b4_parse_assert_if([
YYASSERT (tname); YYASSERT (yytname_);
YYASSERT (tname == other.tname);])[ YYASSERT (yytname_ == other.yytname_);])[
std::swap (as<T>(), other.as<T>()); std::swap (as<T> (), other.as<T> ());
} }
/// Move the content of \a other to this. /// Move the content of \a other to this.
@@ -179,10 +179,10 @@ m4_define([b4_variant_define],
void void
move (self_type& other) move (self_type& other)
{]b4_parse_assert_if([ {]b4_parse_assert_if([
YYASSERT (!tname);])[ YYASSERT (!yytname_);])[
build<T>(); build<T> ();
swap<T>(other); swap<T> (other);
other.destroy<T>(); other.destroy<T> ();
} }
/// Copy the content of \a other to this. /// Copy the content of \a other to this.
@@ -199,7 +199,7 @@ m4_define([b4_variant_define],
destroy () destroy ()
{ {
as<T> ().~T ();]b4_parse_assert_if([ as<T> ().~T ();]b4_parse_assert_if([
tname = YY_NULL;])[ yytname_ = YY_NULL;])[
} }
private: private:
@@ -207,17 +207,34 @@ m4_define([b4_variant_define],
self_type& operator=(const self_type&); self_type& operator=(const self_type&);
variant (const self_type&); variant (const self_type&);
/// A buffer large enough to store any of the semantic values. /// Accessor to raw memory as \a T.
/// Long double is chosen as it has the strongest alignment template <typename T>
/// constraints. 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 union
{ {
long double align_me; /// Strongest alignment constraints.
char raw[S]; long double yyalign_me;
} buffer;]b4_parse_assert_if([ /// 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. /// Whether the content is built: if defined, the name of the stored type.
const char* tname;])[ const char *yytname_;])[
}; };
]]) ]])
@@ -227,16 +244,16 @@ m4_define([b4_variant_define],
## -------------------------- ## ## -------------------------- ##
# b4_semantic_type_declare # b4_value_type_declare
# ------------------------ # ---------------------
# Declare semantic_type. # Declare semantic_type.
m4_define([b4_semantic_type_declare], m4_define([b4_value_type_declare],
[ /// An auxiliary type to compute the largest semantic type. [[ /// An auxiliary type to compute the largest semantic type.
union union_type union union_type
{]b4_type_foreach([b4_char_sizeof])[}; {]b4_type_foreach([b4_char_sizeof])[};
/// Symbol semantic values. /// Symbol semantic values.
typedef variant<sizeof(union_type)> semantic_type;dnl typedef variant<sizeof(union_type)> semantic_type;][]dnl
]) ])
@@ -246,7 +263,7 @@ m4_define([b4_semantic_type_declare],
# ---------------------------- # ----------------------------
m4_define([b4_symbol_value], m4_define([b4_symbol_value],
[m4_ifval([$2], [m4_ifval([$2],
[$1.as< $2 >()], [$1.as< $2 > ()],
[$1])]) [$1])])
# b4_symbol_value_template(VAL, [TYPE]) # b4_symbol_value_template(VAL, [TYPE])
@@ -254,7 +271,7 @@ m4_define([b4_symbol_value],
# Same as b4_symbol_value, but used in a template method. # Same as b4_symbol_value, but used in a template method.
m4_define([b4_symbol_value_template], m4_define([b4_symbol_value_template],
[m4_ifval([$2], [m4_ifval([$2],
[$1.template as< $2 >()], [$1.template as< $2 > ()],
[$1])]) [$1])])
@@ -311,7 +328,7 @@ b4_join(b4_symbol_if([$1], [has_type],
# b4_basic_symbol_constructor_declare # b4_basic_symbol_constructor_declare
# ---------------------------------- # -----------------------------------
# Generate a constructor declaration for basic_symbol from given type. # Generate a constructor declaration for basic_symbol from given type.
m4_define([b4_basic_symbol_constructor_declare], m4_define([b4_basic_symbol_constructor_declare],
[[ [[
+1 -1
View File
@@ -373,7 +373,7 @@
</xsl:template> </xsl:template>
<xsl:template match="empty"> <xsl:template match="empty">
<xsl:text> /* empty */</xsl:text> <xsl:text> %empty</xsl:text>
</xsl:template> </xsl:template>
<xsl:template match="lookaheads"> <xsl:template match="lookaheads">
+16 -39
View File
@@ -143,7 +143,6 @@ m4_define([b4_rhs_value],
[b4_symbol_value([yyvsp@{b4_subtract([$2], [$1])@}], [$3])]) [b4_symbol_value([yyvsp@{b4_subtract([$2], [$1])@}], [$3])])
## ----------- ## ## ----------- ##
## Locations. ## ## Locations. ##
## ----------- ## ## ----------- ##
@@ -176,36 +175,19 @@ m4_define([b4_declare_scanner_communication_variables], [[
int yychar; int yychar;
]b4_pure_if([[ ]b4_pure_if([[
#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ /* The semantic value of the lookahead symbol. */
/* Suppress an incorrect diagnostic about yylval being uninitialized. */
# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
_Pragma ("GCC diagnostic push") \
_Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
_Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
_Pragma ("GCC diagnostic pop")
#else
/* Default value used for initialization, for pacifying older GCCs /* Default value used for initialization, for pacifying older GCCs
or non-GCC compilers. */ or non-GCC compilers. */
static YYSTYPE yyval_default; YY_INITIAL_VALUE (static YYSTYPE yyval_default;)
# define YY_INITIAL_VALUE(Value) = Value YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);]b4_locations_if([[
#endif]b4_locations_if([[
static YYLTYPE yyloc_default][]b4_yyloc_default[;]])])[
#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
# define YY_IGNORE_MAYBE_UNINITIALIZED_END
#endif
#ifndef YY_INITIAL_VALUE
# define YY_INITIAL_VALUE(Value) /* Nothing. */
#endif
/* The semantic value of the lookahead symbol. */
YYSTYPE yylval YY_INITIAL_VALUE(yyval_default);]b4_locations_if([[
/* Location data for the lookahead symbol. */ /* Location data for the lookahead symbol. */
YYLTYPE yylloc]b4_pure_if([ = yyloc_default], [b4_yyloc_default])[; static YYLTYPE yyloc_default]b4_yyloc_default[;
]])b4_pure_if([], [[ YYLTYPE yylloc = yyloc_default;]])],
[[/* The semantic value of the lookahead symbol. */
YYSTYPE yylval;]b4_locations_if([[
/* Location data for the lookahead symbol. */
YYLTYPE yylloc]b4_yyloc_default[;]])[
/* Number of syntax errors so far. */ /* Number of syntax errors so far. */
int yynerrs;]])]) int yynerrs;]])])
@@ -223,9 +205,9 @@ m4_define([b4_declare_parser_state_variables], [b4_pure_if([[
int yyerrstatus; int yyerrstatus;
/* The stacks and their tools: /* The stacks and their tools:
`yyss': related to states. 'yyss': related to states.
`yyvs': related to semantic values.]b4_locations_if([[ 'yyvs': related to semantic values.]b4_locations_if([[
`yyls': related to locations.]])[ 'yyls': related to locations.]])[
Refer to the stacks through separate pointers, to allow yyoverflow Refer to the stacks through separate pointers, to allow yyoverflow
to reallocate them elsewhere. */ to reallocate them elsewhere. */
@@ -431,12 +413,7 @@ typedef short int yytype_int16;
# endif # endif
#endif #endif
/* Suppress unused-variable warnings by "using" E. */ ]b4_attribute_define[
#ifdef __GNUC__
# define YYUSE(E) ((void) (E))
#else
# define YYUSE(E) /* empty */
#endif
#if ]b4_lac_if([[1]], [[! defined yyoverflow || YYERROR_VERBOSE]])[ #if ]b4_lac_if([[1]], [[! defined yyoverflow || YYERROR_VERBOSE]])[
@@ -468,7 +445,7 @@ b4_push_if([], [b4_lac_if([], [[
# endif]])])[ # endif]])])[
# ifdef YYSTACK_ALLOC # ifdef YYSTACK_ALLOC
/* Pacify GCC's `empty if-body' warning. */ /* Pacify GCC's 'empty if-body' warning. */
# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) # define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
# ifndef YYSTACK_ALLOC_MAXIMUM # ifndef YYSTACK_ALLOC_MAXIMUM
/* The OS might guarantee only one guard page at the bottom of the stack, /* The OS might guarantee only one guard page at the bottom of the stack,
@@ -1654,7 +1631,7 @@ yyreduce:
yylen = yyr2[yyn]; yylen = yyr2[yyn];
/* If YYLEN is nonzero, implement the default value of the action: /* If YYLEN is nonzero, implement the default value of the action:
`$$ = $1'. '$$ = $1'.
Otherwise, the following line sets YYVAL to garbage. Otherwise, the following line sets YYVAL to garbage.
This behavior is undocumented and Bison This behavior is undocumented and Bison
@@ -1702,7 +1679,7 @@ yyreduce:
*++yyvsp = yyval;]b4_locations_if([ *++yyvsp = yyval;]b4_locations_if([
*++yylsp = yyloc;])[ *++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 that goes to, based on the state we popped back to and the rule
number reduced by. */ number reduced by. */
+702 -302
View File
File diff suppressed because it is too large Load Diff
+2
View File
@@ -0,0 +1,2 @@
This file is a stub, not used by the documentation. If you feel like
contributing ASCII art for example.gv, please step forward!
+15 -14
View File
@@ -23,9 +23,10 @@ doc_bison_TEXINFOS = \
# Cannot express dependencies directly on file names because of Automake. # Cannot express dependencies directly on file names because of Automake.
# Obfuscate with a variable. # Obfuscate with a variable.
doc_bison = doc/bison doc_bison = doc/bison
$(doc_bison).dvi: $(FIGS_DOT:.dot=.eps) $(doc_bison).dvi: $(FIGS_GV:.gv=.eps)
$(doc_bison).pdf: $(FIGS_DOT:.dot=.pdf) $(doc_bison).info: $(FIGS_GV:.gv=.txt)
$(doc_bison).html: $(FIGS_DOT:.dot=.png) $(doc_bison).pdf: $(FIGS_GV:.gv=.pdf)
$(doc_bison).html: $(FIGS_GV:.gv=.png)
TEXI2DVI = texi2dvi --build-dir=doc/bison.t2d -I doc TEXI2DVI = texi2dvi --build-dir=doc/bison.t2d -I doc
CLEANDIRS = doc/bison.t2d CLEANDIRS = doc/bison.t2d
@@ -37,7 +38,7 @@ MOSTLYCLEANFILES += $(top_srcdir)/doc/*.t
CROSS_OPTIONS_PL = $(top_srcdir)/build-aux/cross-options.pl CROSS_OPTIONS_PL = $(top_srcdir)/build-aux/cross-options.pl
CROSS_OPTIONS_TEXI = $(top_srcdir)/doc/cross-options.texi CROSS_OPTIONS_TEXI = $(top_srcdir)/doc/cross-options.texi
$(CROSS_OPTIONS_TEXI): doc/bison.help $(CROSS_OPTIONS_PL) $(CROSS_OPTIONS_TEXI): doc/bison.help $(CROSS_OPTIONS_PL)
# Create $@~ which is the previous contents. Don't use `mv' here so # Create $@~ which is the previous contents. Don't use 'mv' here so
# that even if we are interrupted, the file is still available for # that even if we are interrupted, the file is still available for
# diff in the next run. Note that $@ might not exist yet. # diff in the next run. Note that $@ might not exist yet.
$(AM_V_GEN){ test ! -f $@ || cat $@; } >$@~ $(AM_V_GEN){ test ! -f $@ || cat $@; } >$@~
@@ -124,25 +125,25 @@ nodist_man_MANS = doc/yacc.1
## ----------------------------- ## ## ----------------------------- ##
CLEANDIRS += doc/figs CLEANDIRS += doc/figs
FIGS_DOT = \ FIGS_GV = \
doc/figs/example.dot \ doc/figs/example.gv \
doc/figs/example-reduce.dot doc/figs/example-shift.dot doc/figs/example-reduce.gv doc/figs/example-shift.gv
EXTRA_DIST += \ EXTRA_DIST += \
$(FIGS_DOT) \ $(FIGS_GV) $(FIGS_GV:.gv=.txt) \
$(FIGS_DOT:.dot=.eps) $(FIGS_DOT:.dot=.pdf) $(FIGS_DOT:.dot=.png) $(FIGS_GV:.gv=.eps) $(FIGS_GV:.gv=.pdf) $(FIGS_GV:.gv=.png)
SUFFIXES += .dot .eps .pdf .png SUFFIXES += .gv .eps .pdf .png
.dot.eps: .gv.eps:
$(AM_V_GEN) $(MKDIR_P) `echo "./$@" | sed -e 's,/[^/]*$$,,'` $(AM_V_GEN) $(MKDIR_P) `echo "./$@" | sed -e 's,/[^/]*$$,,'`
$(AM_V_at) $(DOT) -Gmargin=0 -Teps $< >$@.tmp $(AM_V_at) $(DOT) -Gmargin=0 -Teps $< >$@.tmp
$(AM_V_at) mv $@.tmp $@ $(AM_V_at) mv $@.tmp $@
.dot.pdf: .gv.pdf:
$(AM_V_GEN) $(MKDIR_P) `echo "./$@" | sed -e 's,/[^/]*$$,,'` $(AM_V_GEN) $(MKDIR_P) `echo "./$@" | sed -e 's,/[^/]*$$,,'`
$(AM_V_at) $(DOT) -Gmargin=0 -Tpdf $< >$@.tmp $(AM_V_at) $(DOT) -Gmargin=0 -Tpdf $< >$@.tmp
$(AM_V_at) mv $@.tmp $@ $(AM_V_at) mv $@.tmp $@
.dot.png: .gv.png:
$(AM_V_GEN) $(MKDIR_P) `echo "./$@" | sed -e 's,/[^/]*$$,,'` $(AM_V_GEN) $(MKDIR_P) `echo "./$@" | sed -e 's,/[^/]*$$,,'`
$(AM_V_at) $(DOT) -Gmargin=0 -Tpng $< >$@.tmp $(AM_V_at) $(DOT) -Gmargin=0 -Tpng $< >$@.tmp
$(AM_V_at) mv $@.tmp $@ $(AM_V_at) mv $@.tmp $@
+2 -2
View File
@@ -204,9 +204,9 @@ Format the list of directives for Bison for bench named C<$bench>.
sub directives($@) sub directives($@)
{ {
my ($bench, @directive) = @_; my ($bench, @directive) = @_;
my $res = "/* Directives for bench `$bench'. */\n"; my $res = "/* Directives for bench '$bench'. */\n";
$res .= join ("\n", @directive) . "\n"; $res .= join ("\n", @directive) . "\n";
$res .= "/* End of directives for bench `$bench'. */\n"; $res .= "/* End of directives for bench '$bench'. */\n";
return $res; return $res;
} }
+17 -16
View File
@@ -44,32 +44,33 @@ CLEANFILES += \
# Avoid using BUILT_SOURCES which is too global. # Avoid using BUILT_SOURCES which is too global.
$(examples_calc___calc___OBJECTS): $(calc_sources_generated) $(examples_calc___calc___OBJECTS): $(calc_sources_generated)
calc_sources_extracted = \ calc_sources_extracted = \
examples/calc++/calc++-driver.cc \ examples/calc++/calc++-driver.cc \
examples/calc++/calc++-driver.hh \ examples/calc++/calc++-driver.hh \
examples/calc++/calc++-scanner.ll \ examples/calc++/calc++-scanner.ll \
examples/calc++/calc++.cc examples/calc++/calc++.cc
calc_extracted = \ calc_extracted = \
$(calc_sources_extracted) \ $(calc_sources_extracted) \
examples/calc++/calc++-parser.yy examples/calc++/calc++-parser.yy
extracted += $(calc_extracted) extracted += $(calc_extracted)
calc_sources_generated = \ calc_sources_generated = \
examples/calc++/calc++-parser.cc \ examples/calc++/calc++-parser.cc \
examples/calc++/calc++-parser.hh \ examples/calc++/calc++-parser.hh \
examples/calc++/location.hh \ examples/calc++/location.hh \
examples/calc++/position.hh \ examples/calc++/position.hh \
examples/calc++/stack.hh examples/calc++/stack.hh
calc_sources = \ calc_sources = \
$(calc_sources_extracted) \ $(calc_sources_extracted) \
$(calc_sources_generated) $(calc_sources_generated)
if BISON_CXX_WORKS if BISON_CXX_WORKS
check_PROGRAMS += examples/calc++/calc++ check_PROGRAMS += examples/calc++/calc++
nodist_examples_calc___calc___SOURCES = \ nodist_examples_calc___calc___SOURCES = \
$(calc_sources) $(calc_sources)
examples_calc___calc___CPPFLAGS = -I$(top_builddir)/examples/calc++ examples_calc___calc___CPPFLAGS = -I$(top_builddir)/examples/calc++
examples_calc___calc___CXXFLAGS = \ examples_calc___calc___CXXFLAGS = $(AM_CXXFLAGS) $(FLEX_SCANNER_CXXFLAGS)
$(AM_CXXFLAGS) $(WARN_NO_NULL_CONVERSION_CXXFLAGS)
dist_TESTS += examples/calc++/calc++.test dist_TESTS += examples/calc++/calc++.test
else
EXTRA_DIST += examples/calc++/calc++.test
endif endif
-1
View File
@@ -17,7 +17,6 @@ dist_noinst_SCRIPTS = examples/extexi examples/test
TEST_LOG_COMPILER = $(top_srcdir)/examples/test TEST_LOG_COMPILER = $(top_srcdir)/examples/test
AM_CXXFLAGS = \ AM_CXXFLAGS = \
$(NO_STRICT_ALIAS_CXXFLAGS) \
$(WARN_CXXFLAGS) $(WARN_CXXFLAGS_TEST) $(WERROR_CXXFLAGS) $(WARN_CXXFLAGS) $(WARN_CXXFLAGS_TEST) $(WERROR_CXXFLAGS)
## ------------ ## ## ------------ ##
+1 -1
Submodule gnulib updated: c67e3c0414...03e96cc338
+1 -1
View File
@@ -17,7 +17,7 @@
/* Bison depends on libiberty's implementation of bitsets, which /* 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. */ services. */
#ifndef BISON_LIBIBERTY_H_ #ifndef BISON_LIBIBERTY_H_
+1 -1
View File
@@ -36,7 +36,7 @@
Timing variables may be pushed onto the stack; elapsed time is Timing variables may be pushed onto the stack; elapsed time is
attributed to the topmost timing variable on the stack. When attributed to the topmost timing variable on the stack. When
another variable is pushed on, the previous topmost variable is 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. - As a standalone timer, using timevar_start and timevar_stop.
All time elapsed between the two calls is attributed to the All time elapsed between the two calls is attributed to the
+9 -8
View File
@@ -242,7 +242,7 @@ AnnotationList__computePredecessorAnnotations (AnnotationList *self, state *s,
{ {
symbol_number contribution_token = symbol_number contribution_token =
InadequacyList__getContributionToken (self->inadequacyNode, ci) InadequacyList__getContributionToken (self->inadequacyNode, ci)
->number; ->content->number;
if (AnnotationList__isContributionAlways (self, ci)) if (AnnotationList__isContributionAlways (self, ci))
{ {
annotation_node->contributions[ci] = NULL; annotation_node->contributions[ci] = NULL;
@@ -549,7 +549,7 @@ AnnotationList__compute_from_inadequacies (
does discard annotations in the simplest case of a S/R does discard annotations in the simplest case of a S/R
conflict with no token precedence. */ conflict with no token precedence. */
aver (!bitset_test (shift_tokens, conflicted_token) aver (!bitset_test (shift_tokens, conflicted_token)
|| symbols[conflicted_token]->prec); || symbols[conflicted_token]->content->prec);
++annotation_counts[s->number]; ++annotation_counts[s->number];
if (contribution_count > *max_contributionsp) if (contribution_count > *max_contributionsp)
*max_contributionsp = contribution_count; *max_contributionsp = contribution_count;
@@ -595,7 +595,7 @@ AnnotationList__debug (AnnotationList const *self, size_t nitems, int spaces)
{ {
symbol_number token = symbol_number token =
InadequacyList__getContributionToken (a->inadequacyNode, ci) InadequacyList__getContributionToken (a->inadequacyNode, ci)
->number; ->content->number;
{ {
int j; int j;
for (j = 0; j < spaces+2; ++j) for (j = 0; j < spaces+2; ++j)
@@ -644,7 +644,7 @@ AnnotationList__computeLookaheadFilter (AnnotationList const *self,
Sbitset biter; Sbitset biter;
symbol_number token = symbol_number token =
InadequacyList__getContributionToken (self->inadequacyNode, ci) InadequacyList__getContributionToken (self->inadequacyNode, ci)
->number; ->content->number;
SBITSET__FOR_EACH (self->contributions[ci], nitems, biter, item) SBITSET__FOR_EACH (self->contributions[ci], nitems, biter, item)
bitset_set (lookahead_filter[item], token); bitset_set (lookahead_filter[item], token);
} }
@@ -679,7 +679,8 @@ AnnotationList__stateMakesContribution (AnnotationList const *self,
return false; return false;
{ {
symbol_number token = symbol_number token =
InadequacyList__getContributionToken (self->inadequacyNode, ci)->number; InadequacyList__getContributionToken (self->inadequacyNode, ci)
->content->number;
Sbitset__Index item; Sbitset__Index item;
Sbitset biter; Sbitset biter;
SBITSET__FOR_EACH (self->contributions[ci], nitems, biter, item) SBITSET__FOR_EACH (self->contributions[ci], nitems, biter, item)
@@ -709,7 +710,7 @@ AnnotationList__computeDominantContribution (AnnotationList const *self,
ContributionIndex ci; ContributionIndex ci;
int actioni; int actioni;
ContributionIndex ci_rr_dominator = ContributionIndex__none; ContributionIndex ci_rr_dominator = ContributionIndex__none;
int shift_precedence = token->prec; int shift_precedence = token->content->prec;
/* If the token has no precedence set, shift is always chosen. */ /* If the token has no precedence set, shift is always chosen. */
if (!shift_precedence) if (!shift_precedence)
@@ -739,7 +740,7 @@ AnnotationList__computeDominantContribution (AnnotationList const *self,
if (reduce_precedence if (reduce_precedence
&& (reduce_precedence < shift_precedence && (reduce_precedence < shift_precedence
|| (reduce_precedence == shift_precedence || (reduce_precedence == shift_precedence
&& token->assoc == right_assoc))) && token->content->assoc == right_assoc)))
continue; continue;
if (!AnnotationList__stateMakesContribution (self, nitems, ci, if (!AnnotationList__stateMakesContribution (self, nitems, ci,
lookaheads)) lookaheads))
@@ -747,7 +748,7 @@ AnnotationList__computeDominantContribution (AnnotationList const *self,
/* This uneliminated reduction contributes, so see if it can cause /* This uneliminated reduction contributes, so see if it can cause
an error action. */ an error action. */
if (reduce_precedence == shift_precedence if (reduce_precedence == shift_precedence
&& token->assoc == non_assoc) && token->content->assoc == non_assoc)
{ {
/* It's not possible to find split-stable domination over /* It's not possible to find split-stable domination over
shift after a potential %nonassoc. */ shift after a potential %nonassoc. */
+1 -1
View File
@@ -60,7 +60,7 @@ Sbitset__isEmpty (Sbitset self, Sbitset__Index nbits)
} }
void void
Sbitset__fprint(Sbitset self, Sbitset__Index nbits, FILE *file) Sbitset__fprint (Sbitset self, Sbitset__Index nbits, FILE *file)
{ {
Sbitset__Index i; Sbitset__Index i;
Sbitset itr; Sbitset itr;
+6 -6
View File
@@ -44,31 +44,31 @@ void Sbitset__delete (Sbitset self);
bool Sbitset__isEmpty (Sbitset self, Sbitset__Index nbits); bool Sbitset__isEmpty (Sbitset self, Sbitset__Index nbits);
void Sbitset__fprint(Sbitset self, Sbitset__Index nbits, FILE *file); void Sbitset__fprint (Sbitset self, Sbitset__Index nbits, FILE *file);
# define Sbitset__set(SELF, INDEX) \ # define Sbitset__set(SELF, INDEX) \
do { \ do { \
*Sbitset__byteAddress ((SELF), (INDEX)) = \ *Sbitset__byteAddress ((SELF), (INDEX)) = \
*Sbitset__byteAddress ((SELF), (INDEX)) | Sbitset__bit_mask (INDEX); \ *Sbitset__byteAddress ((SELF), (INDEX)) | Sbitset__bit_mask (INDEX); \
} while(0) } while (0)
# define Sbitset__reset(SELF, INDEX) \ # define Sbitset__reset(SELF, INDEX) \
do { \ do { \
*Sbitset__byteAddress ((SELF), (INDEX)) = \ *Sbitset__byteAddress ((SELF), (INDEX)) = \
*Sbitset__byteAddress ((SELF), (INDEX)) & ~Sbitset__bit_mask (INDEX); \ *Sbitset__byteAddress ((SELF), (INDEX)) & ~Sbitset__bit_mask (INDEX); \
} while(0) } while (0)
/* NBITS is the size of the bitset. More than NBITS bits might be reset. */ /* NBITS is the size of the bitset. More than NBITS bits might be reset. */
# define Sbitset__zero(SELF, NBITS) \ # define Sbitset__zero(SELF, NBITS) \
do { \ do { \
memset (SELF, 0, Sbitset__nbytes (NBITS)); \ memset (SELF, 0, Sbitset__nbytes (NBITS)); \
} while(0) } while (0)
/* NBITS is the size of the bitset. More than NBITS bits might be set. */ /* NBITS is the size of the bitset. More than NBITS bits might be set. */
# define Sbitset__ones(SELF, NBITS) \ # define Sbitset__ones(SELF, NBITS) \
do { \ do { \
memset (SELF, UCHAR_MAX, Sbitset__nbytes (NBITS)); \ memset (SELF, UCHAR_MAX, Sbitset__nbytes (NBITS)); \
} while(0) } while (0)
/* NBITS is the size of every bitset. More than NBITS bits might be set. */ /* NBITS is the size of every bitset. More than NBITS bits might be set. */
# define Sbitset__or(SELF, OTHER1, OTHER2, NBITS) \ # define Sbitset__or(SELF, OTHER1, OTHER2, NBITS) \
@@ -79,7 +79,7 @@ void Sbitset__fprint(Sbitset self, Sbitset__Index nbits, FILE *file);
Sbitset end_self = ptr_self + Sbitset__nbytes (NBITS); \ Sbitset end_self = ptr_self + Sbitset__nbytes (NBITS); \
for (; ptr_self < end_self; ++ptr_self, ++ptr_other1, ++ptr_other2) \ for (; ptr_self < end_self; ++ptr_self, ++ptr_other1, ++ptr_other2) \
*ptr_self = *ptr_other1 | *ptr_other2; \ *ptr_self = *ptr_other1 | *ptr_other2; \
} while(0) } while (0)
# define SBITSET__FOR_EACH(SELF, NBITS, ITER, INDEX) \ # define SBITSET__FOR_EACH(SELF, NBITS, ITER, INDEX) \
for ((ITER) = (SELF); (ITER) < (SELF) + Sbitset__nbytes (NBITS); ++(ITER)) \ for ((ITER) = (SELF); (ITER) < (SELF) + Sbitset__nbytes (NBITS); ++(ITER)) \
+388 -77
View File
@@ -22,6 +22,7 @@
#include <config.h> #include <config.h>
#include "system.h" #include "system.h"
#include <argmatch.h>
#include <stdarg.h> #include <stdarg.h>
#include <progname.h> #include <progname.h>
@@ -30,44 +31,287 @@
#include "getargs.h" #include "getargs.h"
#include "quote.h" #include "quote.h"
warnings warnings_flag =
Wconflicts_sr | Wconflicts_rr | Wdeprecated | Wother;
warnings errors_flag;
err_status complaint_status = status_none; 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;
/** Struct to sort the warnings according to location. */
typedef struct
{
location *loc;
char *message;
} warning;
warning **warning_list;
struct obstack obstack_warning;
#define WARNING_LIST_INCREMENT 100
int warning_count = 0;
/** For each warning type, its severity. */
static severity warnings_flag[warnings_size];
static unsigned *indent_ptr = 0; static unsigned *indent_ptr = 0;
void static const location *complain_loc;
warnings_print_categories (warnings warn_flags)
{
if (! (warn_flags & silent))
{
char const *warn_names[] =
{
"midrule-values",
"yacc",
"conflicts-sr",
"conflicts-rr",
"deprecated",
"other"
};
bool any = false; /*------------------------.
int i; | --warnings's handling. |
for (i = 0; i < ARRAY_CARDINALITY (warn_names); ++i) `------------------------*/
if (warn_flags & 1 << i)
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)
{ {
bool err = warn_flags & errors_flag; if (err)
fprintf (stderr, "%s-W", any ? ", " : " ["); {
fprintf (stderr, "%s%s", err ? "error=" : "" , warn_names[i]); /* -Wno-error=foo: if foo enabled as an error,
any = true; make it a warning. */
if (warnings_flag[b] == severity_error)
warnings_flag[b] = severity_warning;
}
else
/* -Wno-foo. */
warnings_flag[b] = severity_disabled;
} }
if (any) }
fprintf (stderr, "]"); 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);
warning_list = xmalloc (WARNING_LIST_INCREMENT * sizeof (*warning_list));
obstack_init (&obstack_warning);
}
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, struct obstack *obs)
{
/* 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]);
obstack_printf (obs, " [-W%s%s]",
s == severity_error ? "error=" : "",
warnings_args[i]);
return;
}
}
static void
start_error (const location *loc, warnings flags, const char *prefix,
const char *message, va_list args)
{
unsigned pos = 0;
if (loc)
pos += location_obstack_print (*loc, &obstack_warning);
else
pos += obstack_printf (&obstack_warning, "%s", current_file ? current_file
: program_name);
pos += obstack_printf (&obstack_warning, ": ");
if (indent_ptr)
{
if (*indent_ptr)
prefix = NULL;
if (!*indent_ptr)
*indent_ptr = pos;
else if (*indent_ptr > pos)
obstack_printf (&obstack_warning, "%*s", *indent_ptr - pos, "");
indent_ptr = 0;
}
if (prefix)
obstack_printf (&obstack_warning, "%s: ", prefix);
obstack_vprintf (&obstack_warning, message, args);
if (! (flags & silent))
warnings_print_categories (flags, &obstack_warning);
{
size_t l = strlen (message);
if (l < 2 || message[l - 2] != ':' || message[l - 1] != ' ')
{
obstack_1grow (&obstack_warning, '\n');
if (loc && feature_flag & feature_caret && !(flags & no_caret))
location_obstack_caret (*loc, &obstack_warning);
}
}
if (!complain_loc)
complain_loc = loc;
}
void
finish_complaint (void)
{
if (!((warning_count + 1) % WARNING_LIST_INCREMENT))
warning_list = xnrealloc (warning_list, warning_count + 1
+ WARNING_LIST_INCREMENT, sizeof (*warning_list));
warning_list[warning_count] = xmalloc (sizeof **warning_list);
warning *w = warning_list[warning_count];
if (complain_loc)
{
w->loc = xmalloc (sizeof *w->loc);
*w->loc = *complain_loc;
}
else
w->loc = NULL;
complain_loc = NULL;
w->message = obstack_finish0 (&obstack_warning);
warning_count ++;
}
/** Report an error message. /** Report an error message.
* *
* \param loc the location, defaulting to the current file, * \param loc the location, defaulting to the current file,
@@ -85,62 +329,62 @@ void
error_message (const location *loc, warnings flags, const char *prefix, error_message (const location *loc, warnings flags, const char *prefix,
const char *message, va_list args) const char *message, va_list args)
{ {
unsigned pos = 0; start_error (loc, flags, prefix, message, args);
finish_complaint ();
if (loc)
pos += location_print (stderr, *loc);
else
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)
fprintf (stderr, "%*s", *indent_ptr - pos, "");
indent_ptr = 0;
}
if (prefix)
fprintf (stderr, "%s: ", prefix);
vfprintf (stderr, message, args);
warnings_print_categories (flags);
{
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 && !(flags & no_caret))
location_caret (stderr, *loc);
}
}
fflush (stderr);
} }
/** Raise a complaint. That can be a fatal error, a complaint or just a
/** Start an error message, but don't conclude it. That can be a fatal error,
an error or just a warning. */
static void
start_complains (const location *loc, warnings flags, const char *message,
va_list args)
{
severity s = warning_severity (flags);
if ((flags & complaint) && complaint_status < status_complaint)
complaint_status = status_complaint;
if (severity_warning <= s)
{
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;
start_error (loc, flags, prefix, message, args);
}
if (flags & fatal)
print_warnings_and_exit (stderr, EXIT_FAILURE);
}
/** Raise a complaint. That can be a fatal error, an error or just a
warning. */ warning. */
static inline void
static void
complains (const location *loc, warnings flags, const char *message, complains (const location *loc, warnings flags, const char *message,
va_list args) va_list args)
{ {
const char* prefix = severity s = warning_severity (flags);
flags & fatal ? _("fatal error")
: flags & (errors_flag | complaint) ? _("error")
: _("warning");
if ((flags & complaint) && complaint_status < status_complaint) if ((flags & complaint) && complaint_status < status_complaint)
complaint_status = status_complaint; complaint_status = status_complaint;
else if ((flags & (warnings_flag & errors_flag)) && ! complaint_status)
complaint_status = status_warning_as_error; if (severity_warning <= s)
if (flags & (warnings_flag | fatal | complaint)) {
error_message (loc, flags, prefix, message, args); 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);
}
if (flags & fatal) if (flags & fatal)
exit (EXIT_FAILURE); print_warnings_and_exit (stderr, EXIT_FAILURE);
} }
void void
@@ -152,6 +396,15 @@ complain (location const *loc, warnings flags, const char *message, ...)
va_end (args); va_end (args);
} }
void
start_complain (location const *loc, warnings flags, const char *message, ...)
{
va_list args;
va_start (args, message);
start_complains (loc, flags, message, args);
va_end (args);
}
void void
complain_indent (location const *loc, warnings flags, unsigned *indent, complain_indent (location const *loc, warnings flags, unsigned *indent,
const char *message, ...) const char *message, ...)
@@ -163,6 +416,17 @@ complain_indent (location const *loc, warnings flags, unsigned *indent,
va_end (args); va_end (args);
} }
void
start_complain_indent (location const *loc, warnings flags, unsigned *indent,
const char *message, ...)
{
va_list args;
indent_ptr = indent;
va_start (args, message);
start_complains (loc, flags, message, args);
va_end (args);
}
void void
complain_args (location const *loc, warnings w, unsigned *indent, complain_args (location const *loc, warnings w, unsigned *indent,
int argc, char *argv[]) int argc, char *argv[])
@@ -189,7 +453,6 @@ complain_args (location const *loc, warnings w, unsigned *indent,
complain (loc, fatal, "too many arguments for complains"); complain (loc, fatal, "too many arguments for complains");
break; break;
} }
} }
void void
@@ -204,3 +467,51 @@ deprecated_directive (location const *loc, char const *old, char const *upd)
_("deprecated directive: %s, use %s"), _("deprecated directive: %s, use %s"),
quote (old), quote_n (1, upd)); quote (old), quote_n (1, upd));
} }
void
duplicate_directive (char const *directive,
location first, location second)
{
unsigned i = 0;
start_complain (&second, complaint, _("only one %s allowed per rule"), directive);
i += SUB_INDENT;
complain_indent (&first, complaint, &i, _("previous declaration"));
}
/** Compare warnings, to sort them. */
static int
warning_cmp (void const *a, void const *b)
{
warning *wa = *(warning * const *)a, *wb = *(warning * const *)b;
if (wa->loc && wb->loc)
return location_cmp (*wa->loc, *wb->loc);
/* Undefined location/line number at the end. */
else if (wa->loc)
return -1;
else if (wb->loc)
return 1;
return 0;
}
void
print_warnings (FILE *f)
{
if (obstack_object_size (&obstack_warning))
finish_complaint ();
qsort (warning_list, warning_count, sizeof *warning_list, warning_cmp);
for (int i = 0; i < warning_count; ++i)
{
fprintf (f, "%s", warning_list[i]->message);
free (warning_list[i]->loc);
free (warning_list[i]);
}
free (warning_list);
obstack_free (&obstack_warning, NULL);
}
void
print_warnings_and_exit (FILE *f, int exit_status)
{
print_warnings (f);
exit (exit_status);
}
+87 -15
View File
@@ -28,15 +28,67 @@
| --warnings. | | --warnings. |
`-------------*/ `-------------*/
/** The bits assigned to each warning type. */
typedef enum typedef enum
{ {
Wnone = 0, /**< Issue no warnings. */ warning_midrule_values, /**< Unset or unused midrule values. */
Wmidrule_values = 1 << 0, /**< Unset or unused midrule values. */ warning_yacc, /**< POSIXME. */
Wyacc = 1 << 1, /**< POSIXME. */ warning_conflicts_sr, /**< S/R conflicts. */
Wconflicts_sr = 1 << 2, /**< S/R conflicts. */ warning_conflicts_rr, /**< R/R conflicts. */
Wconflicts_rr = 1 << 3, /**< R/R conflicts. */ warning_empty_rule, /**< Implicitly empty rules. */
Wdeprecated = 1 << 4, /**< Obsolete constructs. */ warning_deprecated, /**< Obsolete constructs. */
Wother = 1 << 5, /**< All other warnings. */ 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. */ Werror = 1 << 10, /** This bit is no longer used. */
@@ -46,17 +98,19 @@ typedef enum
no_caret = 1 << 14, /**< Do not display caret location. */ no_caret = 1 << 14, /**< Do not display caret location. */
/**< All above warnings. */ /**< All above warnings. */
Wall = ~complaint & ~fatal & ~silent Weverything = ~complaint & ~fatal & ~silent,
Wall = Weverything & ~Wyacc
} warnings; } warnings;
/** What warnings are issued. */ /** Whether the warnings of \a flags are all unset.
extern warnings warnings_flag; (Never enabled, never disabled). */
bool warning_is_unset (warnings flags);
/** What warnings are made errors. */ /** Start a complaint, with maybe a location, but don't finish it until a
extern warnings errors_flag; normal complaint or a call to finish_complaint. */
void start_complain (location const *loc, warnings flags, char const *message,
/** Display a "[-Wyacc]" like message on stderr. */ ...)
void warnings_print_categories (warnings warn_flags); __attribute__ ((__format__ (__printf__, 3, 4)));
/** Make a complaint, with maybe a location. */ /** Make a complaint, with maybe a location. */
void complain (location const *loc, warnings flags, char const *message, ...) void complain (location const *loc, warnings flags, char const *message, ...)
@@ -66,16 +120,28 @@ void complain (location const *loc, warnings flags, char const *message, ...)
void complain_args (location const *loc, warnings w, unsigned *indent, void complain_args (location const *loc, warnings w, unsigned *indent,
int argc, char *arg[]); int argc, char *arg[]);
/** Start a complaint message with location and some indentation, but don't
finish it until a normal complaint or a call to finish_complaint. */
void start_complain_indent (location const *loc, warnings flags, unsigned *indent,
char const *message, ...)
__attribute__ ((__format__ (__printf__, 4, 5)));
/** Make a complaint with location and some indentation. */ /** Make a complaint with location and some indentation. */
void complain_indent (location const *loc, warnings flags, unsigned *indent, void complain_indent (location const *loc, warnings flags, unsigned *indent,
char const *message, ...) char const *message, ...)
__attribute__ ((__format__ (__printf__, 4, 5))); __attribute__ ((__format__ (__printf__, 4, 5)));
/** Finish the current complaint. */
void finish_complaint (void);
/** Report an obsolete syntax, suggest the updated one. */ /** Report an obsolete syntax, suggest the updated one. */
void deprecated_directive (location const *loc, void deprecated_directive (location const *loc,
char const *obsolete, char const *updated); char const *obsolete, char const *updated);
/** Report a repeated directive for a rule. */
void duplicate_directive (char const *directive,
location first, location second);
/** Warnings treated as errors shouldn't stop the execution as regular errors /** 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 should (because due to their nature, it is safe to go on). Thus, there are
three possible execution statuses. */ three possible execution statuses. */
@@ -89,4 +155,10 @@ typedef enum
/** Whether an error was reported. */ /** Whether an error was reported. */
extern err_status complaint_status; extern err_status complaint_status;
/** Sort and print warnings, and free them. */
void print_warnings (FILE *f);
/** Sort and print warnings, free them, then exit. */
void print_warnings_and_exit (FILE *f, int exit_status);
#endif /* !COMPLAIN_H_ */ #endif /* !COMPLAIN_H_ */
+9 -9
View File
@@ -104,7 +104,7 @@ log_resolution (rule *r, symbol_number token,
case shift_resolution: case shift_resolution:
obstack_printf (&solved_conflicts_obstack, obstack_printf (&solved_conflicts_obstack,
" (%s < %s)", " (%s < %s)",
r->prec->tag, r->prec->symbol->tag,
symbols[token]->tag); symbols[token]->tag);
break; break;
@@ -112,7 +112,7 @@ log_resolution (rule *r, symbol_number token,
obstack_printf (&solved_conflicts_obstack, obstack_printf (&solved_conflicts_obstack,
" (%s < %s)", " (%s < %s)",
symbols[token]->tag, symbols[token]->tag,
r->prec->tag); r->prec->symbol->tag);
break; break;
case left_resolution: case left_resolution:
@@ -176,7 +176,7 @@ log_resolution (rule *r, symbol_number token,
case shift_resolution: case shift_resolution:
obstack_printf (&solved_conflicts_xml_obstack, obstack_printf (&solved_conflicts_xml_obstack,
"%s &lt; %s", "%s &lt; %s",
xml_escape_n (0, r->prec->tag), xml_escape_n (0, r->prec->symbol->tag),
xml_escape_n (1, symbols[token]->tag)); xml_escape_n (1, symbols[token]->tag));
break; break;
@@ -184,7 +184,7 @@ log_resolution (rule *r, symbol_number token,
obstack_printf (&solved_conflicts_xml_obstack, obstack_printf (&solved_conflicts_xml_obstack,
"%s &lt; %s", "%s &lt; %s",
xml_escape_n (0, symbols[token]->tag), xml_escape_n (0, symbols[token]->tag),
xml_escape_n (1, r->prec->tag)); xml_escape_n (1, r->prec->symbol->tag));
break; break;
case left_resolution: case left_resolution:
@@ -269,18 +269,18 @@ resolve_sr_conflict (state *s, int ruleno, symbol **errors, int *nerrs)
for (i = 0; i < ntokens; i++) for (i = 0; i < ntokens; i++)
if (bitset_test (lookahead_tokens, i) if (bitset_test (lookahead_tokens, i)
&& bitset_test (lookahead_set, i) && bitset_test (lookahead_set, i)
&& symbols[i]->prec) && symbols[i]->content->prec)
{ {
/* Shift-reduce conflict occurs for token number i /* Shift-reduce conflict occurs for token number i
and it has a precedence. and it has a precedence.
The precedence of shifting is that of token i. */ The precedence of shifting is that of token i. */
if (symbols[i]->prec < redprec) if (symbols[i]->content->prec < redprec)
{ {
register_precedence (redrule->prec->number, i); register_precedence (redrule->prec->number, i);
log_resolution (redrule, i, reduce_resolution); log_resolution (redrule, i, reduce_resolution);
flush_shift (s, i); flush_shift (s, i);
} }
else if (symbols[i]->prec > redprec) else if (symbols[i]->content->prec > redprec)
{ {
register_precedence (i, redrule->prec->number); register_precedence (i, redrule->prec->number);
log_resolution (redrule, i, shift_resolution); log_resolution (redrule, i, shift_resolution);
@@ -294,7 +294,7 @@ resolve_sr_conflict (state *s, int ruleno, symbol **errors, int *nerrs)
For right associativity, keep only the shift. For right associativity, keep only the shift.
For nonassociativity, keep neither. */ For nonassociativity, keep neither. */
switch (symbols[i]->assoc) switch (symbols[i]->content->assoc)
{ {
case undef_assoc: case undef_assoc:
abort (); abort ();
@@ -403,7 +403,7 @@ conflicts_solve (void)
set_conflicts (states[i], errors); set_conflicts (states[i], errors);
/* For uniformity of the code, make sure all the states have a valid /* For uniformity of the code, make sure all the states have a valid
`errs' member. */ 'errs' member. */
if (!states[i]->errs) if (!states[i]->errs)
states[i]->errs = errs_new (0, 0); states[i]->errs = errs_new (0, 0);
} }
+13 -13
View File
@@ -34,7 +34,7 @@
#include "getargs.h" #include "getargs.h"
#include "gram.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 tempting, but don't do that: for the time being our handling of the
%directive vs --option leaves precedence to the options by deciding %directive vs --option leaves precedence to the options by deciding
that if a %directive sets a variable which is really set (i.e., not 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; uniqstr current_file = NULL;
/* If --output=dir/foo.c was specified, /* 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/', 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'. 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, 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 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 If neither --output nor --file was specified, DIR_PREFIX is the
empty string (meaning the current directory); otherwise it is empty string (meaning the current directory); otherwise it is
`dir/'. */ 'dir/'. */
char *all_but_ext; char *all_but_ext;
static char *all_but_tab_ext; static char *all_but_tab_ext;
@@ -79,7 +79,7 @@ char *dir_prefix;
/* C source file extension (the parser source). */ /* C source file extension (the parser source). */
static char *src_extension = NULL; 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; static char *header_extension = NULL;
/*-----------------------------------------------------------------. /*-----------------------------------------------------------------.
@@ -191,7 +191,7 @@ compute_exts_from_src (const char *ext)
*EXT points to the last period in the basename, or NULL if none. *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 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. cannot be equal to *BASE.
None are allocated, they are simply pointers to parts of FILE_NAME. None are allocated, they are simply pointers to parts of FILE_NAME.
@@ -222,7 +222,7 @@ file_name_split (const char *file_name,
*ext = strrchr (*base, '.'); *ext = strrchr (*base, '.');
*tab = NULL; *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. */ before. */
if (*ext) if (*ext)
{ {
@@ -270,7 +270,7 @@ compute_file_name_parts (void)
if (spec_file_prefix) if (spec_file_prefix)
{ {
/* If --file-prefix=foo was specified, ALL_BUT_TAB_EXT = `foo'. */ /* If --file-prefix=foo was specified, ALL_BUT_TAB_EXT = 'foo'. */
dir_prefix = dir_prefix =
xstrndup (spec_file_prefix, xstrndup (spec_file_prefix,
last_component (spec_file_prefix) - spec_file_prefix); last_component (spec_file_prefix) - spec_file_prefix);
@@ -278,14 +278,14 @@ compute_file_name_parts (void)
} }
else if (yacc_flag) else if (yacc_flag)
{ {
/* If --yacc, then the output is `y.tab.c'. */ /* If --yacc, then the output is 'y.tab.c'. */
dir_prefix = xstrdup (""); dir_prefix = xstrdup ("");
all_but_tab_ext = xstrdup ("y"); all_but_tab_ext = xstrdup ("y");
} }
else else
{ {
/* Otherwise, ALL_BUT_TAB_EXT is computed from the input /* Otherwise, ALL_BUT_TAB_EXT is computed from the input
grammar: `foo/bar.yy' => `bar'. */ grammar: 'foo/bar.yy' => 'bar'. */
dir_prefix = xstrdup (""); dir_prefix = xstrdup ("");
all_but_tab_ext = all_but_tab_ext =
xstrndup (base, (strlen (base) - (ext ? strlen (ext) : 0))); xstrndup (base, (strlen (base) - (ext ? strlen (ext) : 0)));
+64 -109
View File
@@ -61,7 +61,6 @@ int skeleton_prio = default_prio;
const char *skeleton = NULL; const char *skeleton = NULL;
int language_prio = default_prio; int language_prio = default_prio;
struct bison_language const *language = &valid_languages[0]; struct bison_language const *language = &valid_languages[0];
const char *include = NULL;
/** Decode an option's key. /** Decode an option's key.
* *
@@ -74,8 +73,6 @@ const char *include = NULL;
* If null, then activate all the flags. * If null, then activate all the flags.
* \param no length of the potential "no-" prefix. * \param no length of the potential "no-" prefix.
* Can be 0 or 3. If 3, negate the action of the subargument. * 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 sets flags and no-KEY clears them.
* If VALUE == 0 then KEY clears all flags from \c all and no-KEY sets all * If VALUE == 0 then KEY clears all flags from \c all and no-KEY sets all
@@ -84,36 +81,23 @@ const char *include = NULL;
static void static void
flag_argmatch (const char *option, flag_argmatch (const char *option,
const char * const keys[], const int values[], const char * const keys[], const int values[],
int all, int *flags, char *arg, size_t no, size_t err) int all, int *flags, char *arg, size_t no)
{ {
int value = 0; int value = XARGMATCH (option, arg + no, keys, values);
if (!err || arg[no + err++] != '\0')
value = XARGMATCH (option, arg + no + err, keys, values);
if (value) /* -rnone == -rno-all, and -rno-none == -rall. */
if (!value)
{ {
if (no) value = all;
*flags &= ~value; no = !no;
else
{
if (err)
warnings_flag |= value;
*flags |= value;
}
} }
if (no)
*flags &= ~value;
else else
{ *flags |= value;
/* With a simpler 'if (no)' version, -Werror means -Werror=all
(or rather, -Werror=no-none, but that syntax is invalid).
The difference is:
- Werror activates all errors, but not the warnings
- Werror=all activates errors, and all warnings */
if (no ? !err : err)
*flags |= all;
else
*flags &= ~all;
}
} }
/** Decode an option's set of keys. /** Decode an option's set of keys.
* *
* \param option option being decoded. * \param option option being decoded.
@@ -133,16 +117,14 @@ flags_argmatch (const char *option,
for (args = strtok (args, ","); args; args = strtok (NULL, ",")) for (args = strtok (args, ","); args; args = strtok (NULL, ","))
{ {
size_t no = STRPREFIX_LIT ("no-", args) ? 3 : 0; size_t no = STRPREFIX_LIT ("no-", args) ? 3 : 0;
size_t err = STRPREFIX_LIT ("error", args + no) ? 5 : 0;
flag_argmatch (option, keys, flag_argmatch (option, keys,
values, all, err ? &errors_flag : flags, values, all, flags, args, no);
args, no, err);
} }
else else
*flags |= all; *flags |= all;
} }
/** Decode a set of sub arguments. /** Decode a set of sub arguments.
* *
* \param FlagName the flag familly to update. * \param FlagName the flag familly to update.
@@ -196,8 +178,6 @@ ARGMATCH_VERIFY (report_args, report_types);
static const char * const trace_args[] = 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", "none - no traces",
"scan - grammar scanner traces", "scan - grammar scanner traces",
"parse - grammar parser traces", "parse - grammar parser traces",
@@ -238,41 +218,6 @@ static const int trace_types[] =
ARGMATCH_VERIFY (trace_args, 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",
"deprecated - obsolete constructs",
"other - all other warnings",
"all - all of the above",
"error - warnings are errors",
0
};
static const int warnings_types[] =
{
Wnone,
Wmidrule_values,
Wyacc,
Wconflicts_sr,
Wconflicts_rr,
Wdeprecated,
Wother,
Wall,
Werror
};
ARGMATCH_VERIFY (warnings_args, warnings_types);
/*-----------------------. /*-----------------------.
| --feature's handling. | | --feature's handling. |
`-----------------------*/ `-----------------------*/
@@ -304,7 +249,7 @@ static void
usage (int status) usage (int status)
{ {
if (status != 0) if (status != 0)
fprintf (stderr, _("Try `%s --help' for more information.\n"), fprintf (stderr, _("Try '%s --help' for more information.\n"),
program_name); program_name);
else else
{ {
@@ -346,7 +291,7 @@ Parser:\n\
-L, --language=LANGUAGE specify the output programming language\n\ -L, --language=LANGUAGE specify the output programming language\n\
-S, --skeleton=FILE specify the skeleton to use\n\ -S, --skeleton=FILE specify the skeleton to use\n\
-t, --debug instrument the parser for tracing\n\ -t, --debug instrument the parser for tracing\n\
same as `-Dparse.trace'\n\ same as '-Dparse.trace'\n\
--locations enable location support\n\ --locations enable location support\n\
-D, --define=NAME[=VALUE] similar to '%define NAME \"VALUE\"'\n\ -D, --define=NAME[=VALUE] similar to '%define NAME \"VALUE\"'\n\
-F, --force-define=NAME[=VALUE] override '%define NAME \"VALUE\"'\n\ -F, --force-define=NAME[=VALUE] override '%define NAME \"VALUE\"'\n\
@@ -365,7 +310,7 @@ Output:\n\
-d likewise but cannot specify FILE (for POSIX Yacc)\n\ -d likewise but cannot specify FILE (for POSIX Yacc)\n\
-r, --report=THINGS also produce details on the automaton\n\ -r, --report=THINGS also produce details on the automaton\n\
--report-file=FILE write report to FILE\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\ -b, --file-prefix=PREFIX specify a PREFIX for output files\n\
-o, --output=FILE leave output to FILE\n\ -o, --output=FILE leave output to FILE\n\
-g, --graph[=FILE] also output a graph of the automaton\n\ -g, --graph[=FILE] also output a graph of the automaton\n\
@@ -376,35 +321,37 @@ Output:\n\
fputs (_("\ fputs (_("\
Warning categories include:\n\ Warning categories include:\n\
`midrule-values' unset or unused midrule values\n\ 'midrule-values' unset or unused midrule values\n\
`yacc' incompatibilities with POSIX Yacc\n\ 'yacc' incompatibilities with POSIX Yacc\n\
`conflicts-sr' S/R conflicts (enabled by default)\n\ 'conflicts-sr' S/R conflicts (enabled by default)\n\
`conflicts-rr' R/R conflicts (enabled by default)\n\ 'conflicts-rr' R/R conflicts (enabled by default)\n\
`deprecated' obsolete constructs\n\ 'deprecated' obsolete constructs\n\
`other' all other warnings (enabled by default)\n\ 'empty-rule' empty rules without %empty\n\
`all' all the warnings\n\ 'precedence' useless precedence and associativity\n\
`no-CATEGORY' turn off warnings in CATEGORY\n\ 'other' all other warnings (enabled by default)\n\
`none' turn off all the warnings\n\ 'all' all the warnings except 'yacc'\n\
`error[=CATEGORY]' treat warnings as errors\n\ 'no-CATEGORY' turn off warnings in CATEGORY\n\
'none' turn off all the warnings\n\
'error[=CATEGORY]' treat warnings as errors\n\
"), stdout); "), stdout);
putc ('\n', stdout); putc ('\n', stdout);
fputs (_("\ fputs (_("\
THINGS is a list of comma separated words that can include:\n\ THINGS is a list of comma separated words that can include:\n\
`state' describe the states\n\ 'state' describe the states\n\
`itemset' complete the core item sets with their closure\n\ 'itemset' complete the core item sets with their closure\n\
`lookahead' explicitly associate lookahead tokens to items\n\ 'lookahead' explicitly associate lookahead tokens to items\n\
`solved' describe shift/reduce conflicts solving\n\ 'solved' describe shift/reduce conflicts solving\n\
`all' include all the above information\n\ 'all' include all the above information\n\
`none' disable the report\n\ 'none' disable the report\n\
"), stdout); "), stdout);
putc ('\n', stdout); putc ('\n', stdout);
fputs (_("\ fputs (_("\
FEATURE is a list of comma separated words that can include:\n\ FEATURE is a list of comma separated words that can include:\n\
`caret' show errors with carets\n\ 'caret' show errors with carets\n\
`all' all of the above\n\ 'all' all of the above\n\
`none' disable all of the above\n\ 'none' disable all of the above\n\
"), stdout); "), stdout);
putc ('\n', stdout); putc ('\n', stdout);
@@ -517,12 +464,10 @@ static char const short_options[] =
"b:" "b:"
"d" "d"
"f::" "f::"
"e"
"g::" "g::"
"h" "h"
"k" "k"
"l" "l"
"n"
"o:" "o:"
"p:" "p:"
"r:" "r:"
@@ -552,7 +497,6 @@ static struct option const long_options[] =
/* Parser. */ /* Parser. */
{ "name-prefix", required_argument, 0, 'p' }, { "name-prefix", required_argument, 0, 'p' },
{ "include", required_argument, 0, 'I' },
/* Output. */ /* Output. */
{ "file-prefix", required_argument, 0, 'b' }, { "file-prefix", required_argument, 0, 'b' },
@@ -581,7 +525,6 @@ static struct option const long_options[] =
{ "force-define", required_argument, 0, 'F' }, { "force-define", required_argument, 0, 'F' },
{ "locations", no_argument, 0, LOCATIONS_OPTION }, { "locations", no_argument, 0, LOCATIONS_OPTION },
{ "no-lines", no_argument, 0, 'l' }, { "no-lines", no_argument, 0, 'l' },
{ "raw", no_argument, 0, 0 },
{ "skeleton", required_argument, 0, 'S' }, { "skeleton", required_argument, 0, 'S' },
{ "language", required_argument, 0, 'L' }, { "language", required_argument, 0, 'L' },
{ "token-table", no_argument, 0, 'k' }, { "token-table", no_argument, 0, 'k' },
@@ -590,7 +533,7 @@ static struct option const long_options[] =
}; };
/* Under DOS, there is no difference on the case. This can be /* 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 #ifdef MSDOS
# define AS_FILE_NAME(File) (strlwr (File), (File)) # define AS_FILE_NAME(File) (strlwr (File), (File))
#else #else
@@ -626,24 +569,36 @@ getargs (int argc, char *argv[])
/* Certain long options cause getopt_long to return 0. */ /* Certain long options cause getopt_long to return 0. */
break; break;
case 'D': /* -DNAME[=VALUE]. */ case 'D': /* -DNAME[=(VALUE|"VALUE"|{VALUE})]. */
case 'F': /* -FNAME[=VALUE]. */ case 'F': /* -FNAME[=(VALUE|"VALUE"|{VALUE})]. */
{ {
char* name = optarg; char *name = optarg;
char* value = strchr (optarg, '='); char *value = strchr (optarg, '=');
muscle_kind kind = muscle_keyword;
if (value) if (value)
*value++ = 0; {
char *end = value + strlen (value) - 1;
*value++ = 0;
if (*value == '{' && *end == '}')
{
kind = muscle_code;
++value;
*end = 0;
}
else if (*value == '"' && *end == '"')
{
kind = muscle_string;
++value;
*end = 0;
}
}
muscle_percent_define_insert (name, command_line_location (), muscle_percent_define_insert (name, command_line_location (),
value ? value : "", kind, value ? value : "",
c == 'D' ? MUSCLE_PERCENT_DEFINE_D c == 'D' ? MUSCLE_PERCENT_DEFINE_D
: MUSCLE_PERCENT_DEFINE_F); : MUSCLE_PERCENT_DEFINE_F);
} }
break; break;
case 'I':
include = AS_FILE_NAME (optarg);
break;
case 'L': case 'L':
language_argmatch (optarg, command_line_prio, language_argmatch (optarg, command_line_prio,
command_line_location ()); command_line_location ());
@@ -667,7 +622,7 @@ getargs (int argc, char *argv[])
break; break;
case 'W': case 'W':
FLAGS_ARGMATCH (warnings, optarg, Wall); warnings_argmatch (optarg);
break; break;
case 'b': case 'b':
@@ -718,7 +673,8 @@ getargs (int argc, char *argv[])
case 't': case 't':
muscle_percent_define_insert ("parse.trace", muscle_percent_define_insert ("parse.trace",
command_line_location (), "", command_line_location (),
muscle_keyword, "",
MUSCLE_PERCENT_DEFINE_D); MUSCLE_PERCENT_DEFINE_D);
break; break;
@@ -736,8 +692,7 @@ getargs (int argc, char *argv[])
break; break;
case 'y': case 'y':
warnings_flag |= Wyacc; warning_argmatch ("error=yacc", 0, 6);
errors_flag |= Wyacc;
yacc_flag = true; yacc_flag = true;
break; break;
+1
View File
@@ -121,6 +121,7 @@ enum feature
/** What additional features to use. */ /** What additional features to use. */
extern int feature_flag; extern int feature_flag;
/** Process the command line arguments. /** Process the command line arguments.
* *
* \param argc size of \a argv * \param argc size of \a argv
+15 -38
View File
@@ -65,19 +65,19 @@ rule_useless_in_parser_p (rule const *r)
} }
void void
rule_lhs_print (rule const *r, symbol const *previous_lhs, FILE *out) rule_lhs_print (rule const *r, sym_content const *previous_lhs, FILE *out)
{ {
fprintf (out, " %3d ", r->number); fprintf (out, " %3d ", r->number);
if (previous_lhs != r->lhs) if (previous_lhs != r->lhs)
fprintf (out, "%s:", r->lhs->tag); fprintf (out, "%s:", r->lhs->symbol->tag);
else else
fprintf (out, "%*s|", (int) strlen (previous_lhs->tag), ""); fprintf (out, "%*s|", (int) strlen (previous_lhs->symbol->tag), "");
} }
void void
rule_lhs_print_xml (rule const *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); xml_printf (out, level, "<lhs>%s</lhs>", r->lhs->symbol->tag);
} }
size_t size_t
@@ -93,16 +93,14 @@ rule_rhs_length (rule const *r)
void void
rule_rhs_print (rule const *r, FILE *out) rule_rhs_print (rule const *r, FILE *out)
{ {
if (*r->rhs >= 0) if (0 <= *r->rhs)
{ {
item_number *rp; item_number *rp;
for (rp = r->rhs; *rp >= 0; rp++) for (rp = r->rhs; *rp >= 0; rp++)
fprintf (out, " %s", symbols[*rp]->tag); fprintf (out, " %s", symbols[*rp]->tag);
} }
else else
{ fputs (" %empty", out);
fprintf (out, " /* %s */", _("empty"));
}
} }
static void static void
@@ -125,13 +123,6 @@ rule_rhs_print_xml (rule const *r, FILE *out, int level)
} }
} }
static void
rule_print (rule const *r, FILE *out)
{
fprintf (out, "%s:", r->lhs->tag);
rule_rhs_print (r, out);
}
void void
ritem_print (FILE *out) ritem_print (FILE *out)
{ {
@@ -167,7 +158,7 @@ grammar_rules_partial_print (FILE *out, const char *title,
{ {
rule_number r; rule_number r;
bool first = true; bool first = true;
symbol *previous_lhs = NULL; sym_content *previous_lhs = NULL;
/* rule # : LHS -> RHS */ /* rule # : LHS -> RHS */
for (r = 0; r < nrules + nuseless_productions; r++) for (r = 0; r < nrules + nuseless_productions; r++)
@@ -218,7 +209,7 @@ grammar_rules_print_xml (FILE *out, int level)
rules[r].number, usefulness); rules[r].number, usefulness);
if (rules[r].precsym) if (rules[r].precsym)
fprintf (out, " percent_prec=\"%s\"", fprintf (out, " percent_prec=\"%s\"",
xml_escape (rules[r].precsym->tag)); xml_escape (rules[r].precsym->symbol->tag));
fputs (">\n", out); fputs (">\n", out);
} }
rule_lhs_print_xml (&rules[r], out, level + 3); rule_lhs_print_xml (&rules[r], out, level + 3);
@@ -248,7 +239,7 @@ grammar_dump (FILE *out, const char *title)
for (i = ntokens; i < nsyms; i++) for (i = ntokens; i < nsyms; i++)
fprintf (out, "%5d %5d %5d %s\n", fprintf (out, "%5d %5d %5d %s\n",
i, i,
symbols[i]->prec, symbols[i]->assoc, symbols[i]->content->prec, symbols[i]->content->assoc,
symbols[i]->tag); symbols[i]->tag);
fprintf (out, "\n\n"); fprintf (out, "\n\n");
} }
@@ -289,8 +280,8 @@ grammar_dump (FILE *out, const char *title)
rule_number r; rule_number r;
for (r = 0; r < nrules + nuseless_productions; r++) for (r = 0; r < nrules + nuseless_productions; r++)
{ {
fprintf (out, "%-5d ", r); fprintf (out, "%-5d %s:", r, rules[r].lhs->symbol->tag);
rule_print (&rules[r], out); rule_rhs_print (&rules[r], out);
fprintf (out, "\n"); fprintf (out, "\n");
} }
} }
@@ -300,24 +291,10 @@ grammar_dump (FILE *out, const char *title)
void void
grammar_rules_useless_report (const char *message) grammar_rules_useless_report (const char *message)
{ {
warnings w = Wother; rule_number r;
if (warnings_flag & w) for (r = 0; r < nrules ; ++r)
{ if (!rules[r].useful)
rule_number r; complain (&rules[r].location, Wother, "%s", message);
for (r = 0; r < nrules ; ++r)
if (!rules[r].useful)
{
if (feature_flag & feature_caret)
complain (&rules[r].location, w, "%s", message);
else
{
complain (&rules[r].location, w | silent, "%s: ", message);
rule_print (&rules[r], stderr);
warnings_print_categories (w);
fprintf (stderr, "\n");
}
}
}
} }
void void
+11 -10
View File
@@ -35,7 +35,7 @@
The rules receive rule numbers 1 to NRULES in the order they are The rules receive rule numbers 1 to NRULES in the order they are
written. More precisely Bison augments the grammar with the 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 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 presented to the user, we subtract 1, so *displayed* rule numbers
are 0, 1, 2... are 0, 1, 2...
@@ -61,7 +61,7 @@
RULES[R].prec -- the symbol providing the precedence level of R. RULES[R].prec -- the symbol providing the precedence level of R.
RULES[R].precsym -- the symbol attached (via %prec) to give its 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 need to distinguish one from the other when reducing: a symbol used
in a %prec is not useless. in a %prec is not useless.
@@ -180,17 +180,17 @@ typedef struct
except if some rules are useless. */ except if some rules are useless. */
rule_number number; rule_number number;
symbol *lhs; sym_content *lhs;
item_number *rhs; item_number *rhs;
/* This symbol provides both the associativity, and the precedence. */ /* This symbol provides both the associativity, and the precedence. */
symbol *prec; sym_content *prec;
int dprec; int dprec;
int merger; int merger;
/* This symbol was attached to the rule via %prec. */ /* This symbol was attached to the rule via %prec. */
symbol *precsym; sym_content *precsym;
location location; location location;
bool useful; bool useful;
@@ -205,11 +205,11 @@ extern rule *rules;
/* A function that selects a rule. */ /* A function that selects a rule. */
typedef bool (*rule_filter) (rule const *); 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. */ useful in the grammar. */
bool rule_useful_in_grammar_p (rule const *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. */ useless in the grammar. */
bool rule_useless_in_grammar_p (rule const *r); bool rule_useless_in_grammar_p (rule const *r);
@@ -220,7 +220,8 @@ bool rule_useless_in_parser_p (rule const *r);
/* Print this rule's number and lhs on OUT. If a PREVIOUS_LHS was /* Print this rule's number and lhs on OUT. If a PREVIOUS_LHS was
already displayed (by a previous call for another rule), avoid already displayed (by a previous call for another rule), avoid
useless repetitions. */ useless repetitions. */
void rule_lhs_print (rule const *r, symbol const *previous_lhs, FILE *out); void rule_lhs_print (rule const *r, sym_content const *previous_lhs,
FILE *out);
void rule_lhs_print_xml (rule const *r, FILE *out, int level); void rule_lhs_print_xml (rule const *r, FILE *out, int level);
/* Return the length of the RHS. */ /* Return the length of the RHS. */
@@ -262,8 +263,8 @@ void grammar_rules_print_xml (FILE *out, int level);
void grammar_dump (FILE *out, const char *title); void grammar_dump (FILE *out, const char *title);
/* Report on STDERR the rules that are not flagged USEFUL, using the /* Report on STDERR the rules that are not flagged USEFUL, using the
MESSAGE (which can be `rule useless in grammar' when invoked after grammar MESSAGE (which can be 'rule useless in grammar' when invoked after grammar
reduction, or `rule useless in parser due to conflicts' after conflicts reduction, or 'rule useless in parser due to conflicts' after conflicts
were taken into account). */ were taken into account). */
void grammar_rules_useless_report (const char *message); void grammar_rules_useless_report (const char *message);
+1 -1
View File
@@ -93,7 +93,7 @@ no_reduce_bitset_init (state const *s, bitset *no_reduce_set)
bitset_set (*no_reduce_set, TRANSITION_SYMBOL (s->transitions, n)); bitset_set (*no_reduce_set, TRANSITION_SYMBOL (s->transitions, n));
for (n = 0; n < s->errs->num; ++n) for (n = 0; n < s->errs->num; ++n)
if (s->errs->symbols[n]) if (s->errs->symbols[n])
bitset_set (*no_reduce_set, s->errs->symbols[n]->number); bitset_set (*no_reduce_set, s->errs->symbols[n]->content->number);
} }
static void static void
+2 -2
View File
@@ -424,7 +424,7 @@ ielr_item_has_lookahead (state *s, symbol_number lhs, size_t item,
if (item_number_is_rule_number (ritem[s->items[item] - 2])) if (item_number_is_rule_number (ritem[s->items[item] - 2]))
{ {
state **predecessor; state **predecessor;
aver (lhs != accept->number); aver (lhs != accept->content->number);
for (predecessor = predecessors[s->number]; for (predecessor = predecessors[s->number];
*predecessor; *predecessor;
++predecessor) ++predecessor)
@@ -580,7 +580,7 @@ typedef struct state_list {
static void static void
ielr_compute_goto_follow_set (bitsetv follow_kernel_items, ielr_compute_goto_follow_set (bitsetv follow_kernel_items,
bitsetv always_follows, state_list *s, bitsetv always_follows, state_list *s,
symbol *n, bitset follow_set) sym_content *n, bitset follow_set)
{ {
goto_number n_goto = map_goto (s->lr0Isocore->state->number, n->number); goto_number n_goto = map_goto (s->lr0Isocore->state->number, n->number);
bitset_copy (follow_set, always_follows[n_goto]); bitset_copy (follow_set, always_follows[n_goto]);
+1 -1
View File
@@ -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 /* We need a lookahead either to distinguish different reductions
(i.e., there are two or more), or to distinguish a reduction from a (i.e., there are two or more), or to distinguish a reduction from a
shift. Otherwise, it is straightforward, and the state is 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 consistent unless it is the accepting state (because there is never
a lookahead token that makes sense there, and so no lookahead token a lookahead token that makes sense there, and so no lookahead token
should be read) if the user has otherwise disabled default should be read) if the user has otherwise disabled default
+103 -5
View File
@@ -96,10 +96,8 @@ location_compute (location *loc, boundary *cur, char const *token, size_t size)
} }
/* Output to OUT the location LOC.
Warning: it uses quotearg's slot 3. */
unsigned unsigned
location_print (FILE *out, location loc) location_print (location loc, FILE *out)
{ {
unsigned res = 0; unsigned res = 0;
int end_col = 0 != loc.end.column ? loc.end.column - 1 : 0; int end_col = 0 != loc.end.column ? loc.end.column - 1 : 0;
@@ -139,6 +137,48 @@ location_print (FILE *out, location loc)
} }
unsigned
location_obstack_print (location loc, struct obstack *obs)
{
unsigned res = 0;
int end_col = 0 != loc.end.column ? loc.end.column - 1 : 0;
res += obstack_printf (obs, "%s",
quotearg_n_style (3, escape_quoting_style, loc.start.file));
if (0 <= loc.start.line)
{
res += obstack_printf (obs, ":%d", loc.start.line);
if (0 <= loc.start.column)
res += obstack_printf (obs, ".%d", loc.start.column);
}
if (loc.start.file != loc.end.file)
{
res += obstack_printf (obs, "-%s",
quotearg_n_style (3, escape_quoting_style,
loc.end.file));
if (0 <= loc.end.line)
{
res += obstack_printf (obs, ":%d", loc.end.line);
if (0 <= end_col)
res += obstack_printf (obs, ".%d", end_col);
}
}
else if (0 <= loc.end.line)
{
if (loc.start.line < loc.end.line)
{
res += obstack_printf (obs, "-%d", loc.end.line);
if (0 <= end_col)
res += obstack_printf (obs, ".%d", end_col);
}
else if (0 <= end_col && loc.start.column < end_col)
res += obstack_printf (obs, "-%d", end_col);
}
return res;
}
/* Persistant data used by location_caret to avoid reopening and rereading the /* Persistant data used by location_caret to avoid reopening and rereading the
same file all over for each error. */ same file all over for each error. */
struct caret_info struct caret_info
@@ -161,7 +201,7 @@ cleanup_caret ()
} }
void 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 /* FIXME: find a way to support multifile locations, and only open once each
file. That would make the procedure future-proof. */ file. That would make the procedure future-proof. */
@@ -217,11 +257,69 @@ location_caret (FILE *out, location loc)
} }
} }
void
location_obstack_caret (location loc, struct obstack *obs)
{
/* FIXME: find a way to support multifile locations, and only open once each
file. That would make the procedure future-proof. */
if (! (caret_info.source
|| (caret_info.source = fopen (loc.start.file, "r")))
|| loc.start.column == -1 || loc.start.line == -1)
return;
/* If the line we want to quote is seekable (the same line as the previous
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
{
caret_info.line = 1;
caret_info.offset = 0;
fseek (caret_info.source, caret_info.offset, SEEK_SET);
}
/* Advance to the line's position, keeping track of the offset. */
while (caret_info.line < loc.start.line)
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 c = getc (caret_info.source);
if (c != EOF)
{
/* Quote the file, indent by a single column. */
obstack_1grow (obs, ' ');
do
obstack_1grow (obs, c);
while ((c = getc (caret_info.source)) != EOF && c != '\n');
obstack_1grow (obs, '\n');
{
/* 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.*/
obstack_printf (obs, " %*s", loc.start.column - 1, "");
for (i = loc.start.column; i == loc.start.column || i < len; ++i)
obstack_1grow (obs, '^');
}
obstack_1grow (obs, '\n');
}
}
}
void void
boundary_set_from_string (boundary *bound, char *loc_str) boundary_set_from_string (boundary *bound, char *loc_str)
{ {
/* Must search in reverse since the file name field may /* Must search in reverse since the file name field may
* contain `.' or `:'. */ * contain '.' or ':'. */
char *delim = strrchr (loc_str, '.'); char *delim = strrchr (loc_str, '.');
aver (delim); aver (delim);
*delim = '\0'; *delim = '\0';
+18 -5
View File
@@ -20,6 +20,12 @@
#ifndef LOCATION_H_ #ifndef LOCATION_H_
# define LOCATION_H_ # define LOCATION_H_
# include <stdbool.h>
# include <stdio.h>
# include <string.h> /* strcmp */
# include "system.h"
# include "uniqstr.h" # include "uniqstr.h"
/* A boundary between two characters. */ /* A boundary between two characters. */
@@ -98,16 +104,23 @@ extern location const empty_location;
void location_compute (location *loc, 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 /* Print location to file.
characters. */ Return number of actually printed characters.
unsigned location_print (FILE *out, location loc); Warning: uses quotearg's slot 3. */
unsigned location_print (location loc, FILE *out);
/* Same as location_print, only to an obstack. */
unsigned location_obstack_print (location loc, struct obstack *obs);
/* Free any allocated ressources and close any open file handles that are /* Free any allocated ressources and close any open file handles that are
left-over by the usage of location_caret. */ left-over by the usage of location_caret. */
void cleanup_caret (void); void cleanup_caret (void);
/* Output to OUT the line and caret corresponding to location LOC. */ /* 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);
/* Same as location_caret, only with an obstack. */
void location_obstack_caret (location loc, struct obstack *obs);
/* Return -1, 0, 1, depending whether a is before, equal, or /* Return -1, 0, 1, depending whether a is before, equal, or
after b. */ after b. */
@@ -120,7 +133,7 @@ location_cmp (location a, location b)
return res; 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); void boundary_set_from_string (boundary *bound, char *loc_str);
#endif /* ! defined LOCATION_H_ */ #endif /* ! defined LOCATION_H_ */
+4 -3
View File
@@ -76,6 +76,7 @@ main (int argc, char *argv[])
uniqstrs_new (); uniqstrs_new ();
muscle_init (); muscle_init ();
complain_init ();
getargs (argc, argv); getargs (argc, argv);
@@ -146,8 +147,6 @@ main (int argc, char *argv[])
print_precedence_warnings (); print_precedence_warnings ();
print_assoc_warnings ();
/* Output file names. */ /* Output file names. */
compute_output_file_names (); compute_output_file_names ();
@@ -204,7 +203,6 @@ main (int argc, char *argv[])
contains things such as user actions, prologue, epilogue etc. */ contains things such as user actions, prologue, epilogue etc. */
gram_scanner_free (); gram_scanner_free ();
muscle_free (); muscle_free ();
uniqstrs_free ();
code_scanner_free (); code_scanner_free ();
skel_scanner_free (); skel_scanner_free ();
quotearg_free (); quotearg_free ();
@@ -219,6 +217,9 @@ main (int argc, char *argv[])
timevar_stop (TV_TOTAL); timevar_stop (TV_TOTAL);
timevar_print (stderr); timevar_print (stderr);
print_warnings (stderr);
uniqstrs_free ();
cleanup_caret (); cleanup_caret ();
return complaint_status ? EXIT_FAILURE : EXIT_SUCCESS; return complaint_status ? EXIT_FAILURE : EXIT_SUCCESS;
+209 -161
View File
@@ -28,6 +28,31 @@
#include "muscle-tab.h" #include "muscle-tab.h"
#include "quote.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 /* A key-value pair, along with storage that can be reclaimed when
this pair is no longer needed. */ this pair is no longer needed. */
typedef struct typedef struct
@@ -35,8 +60,21 @@ typedef struct
char const *key; char const *key;
char const *value; char const *value;
char *storage; char *storage;
muscle_kind kind;
} muscle_entry; } muscle_entry;
/* The name of muscle for the %define variable VAR (corresponding to
FIELD, if defined). */
static uniqstr
muscle_name (char const *var, char const *field)
{
if (field)
return UNIQSTR_CONCAT ("percent_define_", field, "(", var, ")");
else
return UNIQSTR_CONCAT ("percent_define(", var, ")");
}
/* An obstack used to create some entries. */ /* An obstack used to create some entries. */
struct obstack muscle_obstack; struct obstack muscle_obstack;
@@ -60,10 +98,18 @@ hash_muscle (const void *x, size_t tablesize)
return hash_string (m->key, tablesize); return hash_string (m->key, tablesize);
} }
/*-----------------------------------------------------------------. /* Create a fresh muscle name KEY, and insert in the hash table. */
| Create the MUSCLE_TABLE, and initialize it with default values. | static void *
| Also set up the MUSCLE_OBSTACK. | 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 static void
muscle_entry_free (void *entry) muscle_entry_free (void *entry)
@@ -87,10 +133,6 @@ muscle_init (void)
} }
/*------------------------------------------------------------.
| Free all the memory consumed by the muscle machinery only. |
`------------------------------------------------------------*/
void void
muscle_free (void) muscle_free (void)
{ {
@@ -98,71 +140,64 @@ muscle_free (void)
obstack_free (&muscle_obstack, NULL); 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 void
muscle_insert (char const *key, char const *value) muscle_insert (char const *key, char const *value)
{ {
muscle_entry probe; muscle_entry *entry = muscle_lookup (key);
muscle_entry *entry; if (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
free (entry->storage); free (entry->storage);
else
/* First insertion in the hash. */
entry = muscle_entry_new (key);
entry->value = value; entry->value = value;
entry->storage = NULL; entry->storage = NULL;
} }
/*-------------------------------------------------------------------. /* Append VALUE to the current value of KEY. If KEY did not already
| Append VALUE to the current value of KEY. If KEY did not already | exist, create it. Use MUSCLE_OBSTACK. De-allocate the previously
| exist, create it. Use MUSCLE_OBSTACK. De-allocate the previously | associated value. Copy VALUE and SEPARATOR. If VALUE does not end
| associated value. Copy VALUE and SEPARATOR. | with TERMINATOR, append one. */
`-------------------------------------------------------------------*/
void static void
muscle_grow (const char *key, const char *val, const char *separator) muscle_grow (const char *key, const char *val,
const char *separator, const char *terminator)
{ {
muscle_entry probe; muscle_entry *entry = muscle_lookup (key);
muscle_entry *entry = NULL; size_t vals = strlen (val);
size_t terms = strlen (terminator);
probe.key = key; if (entry)
entry = hash_lookup (muscle_table, &probe);
if (!entry)
{ {
/* First insertion in the hash. */ obstack_sgrow (&muscle_obstack, entry->value);
entry = xmalloc (sizeof *entry); obstack_sgrow (&muscle_obstack, separator);
entry->key = key; free (entry->storage);
if (!hash_insert (muscle_table, entry))
xalloc_die ();
entry->value = entry->storage = xstrdup (val);
} }
else else
{ entry = muscle_entry_new (key);
/* Grow the current value. */
char *new_val; obstack_sgrow (&muscle_obstack, val);
obstack_printf (&muscle_obstack, "%s%s%s", entry->value, separator, val);
free (entry->storage); if (terms <= vals
new_val = obstack_finish0 (&muscle_obstack); && STRNEQ (val + vals - terms, terminator))
entry->value = entry->storage = xstrdup (new_val); obstack_sgrow (&muscle_obstack, terminator);
obstack_free (&muscle_obstack, new_val);
} {
char *new_val = obstack_finish0 (&muscle_obstack);
entry->value = entry->storage = xstrdup (new_val);
obstack_free (&muscle_obstack, new_val);
}
} }
/*------------------------------------------------------------------. /*------------------------------------------------------------------.
@@ -179,7 +214,7 @@ muscle_syncline_grow (char const *key, location loc)
quotearg_style (c_quoting_style, loc.start.file)); quotearg_style (c_quoting_style, loc.start.file));
obstack_sgrow (&muscle_obstack, ")["); obstack_sgrow (&muscle_obstack, ")[");
extension = obstack_finish0 (&muscle_obstack); extension = obstack_finish0 (&muscle_obstack);
muscle_grow (key, extension, ""); muscle_grow (key, extension, "", "");
obstack_free (&muscle_obstack, extension); obstack_free (&muscle_obstack, extension);
} }
@@ -193,12 +228,13 @@ void
muscle_code_grow (const char *key, const char *val, location loc) muscle_code_grow (const char *key, const char *val, location loc)
{ {
muscle_syncline_grow (key, loc); muscle_syncline_grow (key, loc);
muscle_grow (key, val, "\n"); muscle_grow (key, val, "\n", "\n");
} }
void muscle_pair_list_grow (const char *muscle, void
const char *a1, const char *a2) muscle_pair_list_grow (const char *muscle,
const char *a1, const char *a2)
{ {
char *pair; char *pair;
obstack_sgrow (&muscle_obstack, "["); obstack_sgrow (&muscle_obstack, "[");
@@ -207,54 +243,33 @@ void muscle_pair_list_grow (const char *muscle,
obstack_quote (&muscle_obstack, a2); obstack_quote (&muscle_obstack, a2);
obstack_sgrow (&muscle_obstack, "]"); obstack_sgrow (&muscle_obstack, "]");
pair = obstack_finish0 (&muscle_obstack); pair = obstack_finish0 (&muscle_obstack);
muscle_grow (muscle, pair, ",\n"); muscle_grow (muscle, pair, ",\n", "");
obstack_free (&muscle_obstack, pair); 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 * char const *
muscle_find_const (char const *key) muscle_find_const (char const *key)
{ {
muscle_entry probe; muscle_entry *entry = muscle_lookup (key);
muscle_entry *result = NULL; return entry ? entry->value : NULL;
probe.key = key;
result = hash_lookup (muscle_table, &probe);
if (result)
return result->value;
return 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 * char *
muscle_find (char const *key) muscle_find (char const *key)
{ {
muscle_entry probe; muscle_entry *entry = muscle_lookup (key);
muscle_entry *result = NULL; if (entry)
probe.key = key;
result = hash_lookup (muscle_table, &probe);
if (result)
{ {
aver (result->value == result->storage); aver (entry->value == entry->storage);
return result->storage; return entry->storage;
} }
return NULL; 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. */ digraphs for special characters in the file name. */
static void static void
@@ -265,12 +280,12 @@ muscle_boundary_grow (char const *key, boundary bound)
obstack_escape (&muscle_obstack, bound.file); obstack_escape (&muscle_obstack, bound.file);
obstack_printf (&muscle_obstack, ":%d.%d]]", bound.line, bound.column); obstack_printf (&muscle_obstack, ":%d.%d]]", bound.line, bound.column);
extension = obstack_finish0 (&muscle_obstack); extension = obstack_finish0 (&muscle_obstack);
muscle_grow (key, extension, ""); muscle_grow (key, extension, "", "");
obstack_free (&muscle_obstack, 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 append LOC to MUSCLE. Use digraphs for special characters in each
file name. */ file name. */
@@ -278,7 +293,7 @@ static void
muscle_location_grow (char const *key, location loc) muscle_location_grow (char const *key, location loc)
{ {
muscle_boundary_grow (key, loc.start); muscle_boundary_grow (key, loc.start);
muscle_grow (key, "", ", "); muscle_grow (key, "", ", ", "");
muscle_boundary_grow (key, loc.end); muscle_boundary_grow (key, loc.end);
} }
@@ -329,10 +344,9 @@ string_decode (char const *key)
/* Reverse of muscle_location_grow. */ /* Reverse of muscle_location_grow. */
static location static location
location_decode (char const *key) location_decode (char const *value)
{ {
location loc; location loc;
char const *value = muscle_find_const (key);
aver (value); aver (value);
aver (*value == '['); aver (*value == '[');
aver (*++value == '['); aver (*++value == '[');
@@ -377,11 +391,11 @@ void
muscle_user_name_list_grow (char const *key, char const *user_name, muscle_user_name_list_grow (char const *key, char const *user_name,
location loc) location loc)
{ {
muscle_grow (key, "[[[[", ","); muscle_grow (key, "[[[[", ",", "");
muscle_grow (key, user_name, ""); muscle_grow (key, user_name, "", "");
muscle_grow (key, "]], ", ""); muscle_grow (key, "]], ", "", "");
muscle_location_grow (key, loc); muscle_location_grow (key, loc);
muscle_grow (key, "]]", ""); muscle_grow (key, "]]", "", "");
} }
@@ -475,16 +489,17 @@ muscle_percent_variable_update (char const *variable, location variable_loc,
void void
muscle_percent_define_insert (char const *var, location variable_loc, muscle_percent_define_insert (char const *var, location variable_loc,
muscle_kind kind,
char const *value, char const *value,
muscle_percent_define_how how) muscle_percent_define_how how)
{ {
/* Backward compatibility. */ /* Backward compatibility. */
char *variable = muscle_percent_variable_update (var, variable_loc, &value); char *variable = muscle_percent_variable_update (var, variable_loc, &value);
char const *name = UNIQSTR_CONCAT ("percent_define(", variable, ")"); uniqstr name = muscle_name (variable, NULL);
char const *loc_name = UNIQSTR_CONCAT ("percent_define_loc(", variable, ")"); uniqstr loc_name = muscle_name (variable, "loc");
char const *syncline_name = uniqstr syncline_name = muscle_name (variable, "syncline");
UNIQSTR_CONCAT ("percent_define_syncline(", variable, ")"); uniqstr how_name = muscle_name (variable, "how");
char const *how_name = UNIQSTR_CONCAT ("percent_define_how(", variable, ")"); uniqstr kind_name = muscle_name (variable, "kind");
/* Command-line options are processed before the grammar file. */ /* Command-line options are processed before the grammar file. */
if (how == MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE if (how == MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE
@@ -494,7 +509,7 @@ muscle_percent_define_insert (char const *var, location variable_loc,
unsigned i = 0; unsigned i = 0;
if (how_old == MUSCLE_PERCENT_DEFINE_F) if (how_old == MUSCLE_PERCENT_DEFINE_F)
goto end; goto end;
complain_indent (&variable_loc, complaint, &i, start_complain_indent (&variable_loc, complaint, &i,
_("%%define variable %s redefined"), _("%%define variable %s redefined"),
quote (variable)); quote (variable));
i += SUB_INDENT; i += SUB_INDENT;
@@ -510,6 +525,7 @@ muscle_percent_define_insert (char const *var, location variable_loc,
muscle_user_name_list_grow ("percent_define_user_variables", variable, muscle_user_name_list_grow ("percent_define_user_variables", variable,
variable_loc); variable_loc);
MUSCLE_INSERT_INT (how_name, how); MUSCLE_INSERT_INT (how_name, how);
MUSCLE_INSERT_STRING (kind_name, muscle_kind_string (kind));
end: end:
free (variable); free (variable);
} }
@@ -520,85 +536,120 @@ void
muscle_percent_define_ensure (char const *variable, location loc, muscle_percent_define_ensure (char const *variable, location loc,
bool value) bool value)
{ {
uniqstr name = muscle_name (variable, NULL);
char const *val = value ? "" : "false"; char const *val = value ? "" : "false";
char const *name = UNIQSTR_CONCAT ("percent_define(", variable, ")");
/* %pure-parser is deprecated in favor of `%define api.pure', so use /* Don't complain is VARIABLE is already defined, but be sure to set
`%define api.pure' in a backward-compatible manner here. First, its value to VAL. */
don't complain if %pure-parser is specified multiple times. */ if (!muscle_find_const (name)
if (!muscle_find_const (name)) || muscle_percent_define_flag_if (variable) != value)
muscle_percent_define_insert (variable, loc, val, muscle_percent_define_insert (variable, loc, muscle_keyword, val,
MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE);
/* In all cases, use api.pure now so that the backend doesn't complain if
the skeleton ignores api.pure, but do warn now if there's a previous
conflicting definition from an actual %define. */
if (muscle_percent_define_flag_if (variable) != value)
muscle_percent_define_insert (variable, loc, val,
MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE); MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE);
} }
/* Mark %define VARIABLE as used. */
static void
muscle_percent_define_use (char const *variable)
{
muscle_insert (muscle_name (variable, "bison_variables"), "");
}
/* The value of %define variable VARIABLE (corresponding to FIELD, if
defined). Do not register as used, but diagnose unset variables. */
static
char const *
muscle_percent_define_get_raw (char const *variable, char const *field)
{
uniqstr name = muscle_name (variable, field);
char const *res = muscle_find_const (name);
if (!res)
complain (NULL, fatal, _("%s: undefined %%define variable %s"),
"muscle_percent_define_get_raw", quote (variable));
return res;
}
char * char *
muscle_percent_define_get (char const *variable) muscle_percent_define_get (char const *variable)
{ {
char const *name = UNIQSTR_CONCAT ("percent_define(", variable, ")"); uniqstr name = muscle_name (variable, NULL);
char const *usage_name =
UNIQSTR_CONCAT ("percent_define_bison_variables(", variable, ")");
char *value = string_decode (name); char *value = string_decode (name);
if (!value) if (!value)
value = xstrdup (""); value = xstrdup ("");
muscle_percent_define_use (variable);
muscle_insert (usage_name, "");
return value; return value;
} }
/* The kind of VARIABLE. An error if undefined. */
static muscle_kind
muscle_percent_define_get_kind (char const *variable)
{
return muscle_kind_new (muscle_percent_define_get_raw (variable, "kind"));
}
/* Check the kind of VARIABLE. An error if undefined. */
static void
muscle_percent_define_check_kind (char const *variable, muscle_kind kind)
{
if (muscle_percent_define_get_kind (variable) != kind)
{
location loc = muscle_percent_define_get_loc (variable);
switch (kind)
{
case muscle_code:
complain (&loc, Wdeprecated,
"%%define variable '%s' requires '{...}' values",
variable);
break;
case muscle_keyword:
complain (&loc, Wdeprecated,
"%%define variable '%s' requires keyword values",
variable);
break;
case muscle_string:
complain (&loc, Wdeprecated,
"%%define variable '%s' requires '\"...\"' values",
variable);
break;
}
}
}
location location
muscle_percent_define_get_loc (char const *variable) muscle_percent_define_get_loc (char const *variable)
{ {
char const *loc_name = UNIQSTR_CONCAT ("percent_define_loc(", variable, ")"); return location_decode (muscle_percent_define_get_raw (variable, "loc"));
if (!muscle_find_const (loc_name))
complain (NULL, fatal, _("%s: undefined %%define variable %s"),
"muscle_percent_define_get_loc", quote (variable));
return location_decode (loc_name);
} }
char const * char const *
muscle_percent_define_get_syncline (char const *variable) muscle_percent_define_get_syncline (char const *variable)
{ {
char const *syncline_name = return muscle_percent_define_get_raw (variable, "syncline");
UNIQSTR_CONCAT ("percent_define_syncline(", variable, ")");
char const *syncline = muscle_find_const (syncline_name);
if (!syncline)
complain (NULL, fatal, _("%s: undefined %%define variable %s"),
"muscle_percent_define_get_syncline", quote (variable));
return syncline;
} }
bool bool
muscle_percent_define_ifdef (char const *variable) muscle_percent_define_ifdef (char const *variable)
{ {
char const *name = UNIQSTR_CONCAT ("percent_define(", variable, ")"); if (muscle_find_const (muscle_name (variable, NULL)))
char const *usage_name =
UNIQSTR_CONCAT ("percent_define_bison_variables(", variable, ")");
char const *value = muscle_find_const (name);
if (value)
{ {
muscle_insert (usage_name, ""); muscle_percent_define_use (variable);
return true; return true;
} }
else
return false; return false;
} }
bool bool
muscle_percent_define_flag_if (char const *variable) muscle_percent_define_flag_if (char const *variable)
{ {
char const *invalid_boolean_name = uniqstr invalid_boolean_name = muscle_name (variable, "invalid_boolean");
UNIQSTR_CONCAT ("percent_define_invalid_boolean(", variable, ")");
bool result = false; bool result = false;
if (muscle_percent_define_ifdef (variable)) if (muscle_percent_define_ifdef (variable))
{ {
char *value = muscle_percent_define_get (variable); char *value = muscle_percent_define_get (variable);
muscle_percent_define_check_kind (variable, muscle_keyword);
if (value[0] == '\0' || STREQ (value, "true")) if (value[0] == '\0' || STREQ (value, "true"))
result = true; result = true;
else if (STREQ (value, "false")) else if (STREQ (value, "false"))
@@ -623,20 +674,21 @@ muscle_percent_define_flag_if (char const *variable)
void void
muscle_percent_define_default (char const *variable, char const *value) muscle_percent_define_default (char const *variable, char const *value)
{ {
char const *name = UNIQSTR_CONCAT ("percent_define(", variable, ")"); uniqstr name = muscle_name (variable, NULL);
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)) if (!muscle_find_const (name))
{ {
location loc;
MUSCLE_INSERT_STRING (name, value); MUSCLE_INSERT_STRING (name, value);
loc.start.file = loc.end.file = "<default value>"; MUSCLE_INSERT_STRING (muscle_name (variable, "kind"), "keyword");
loc.start.line = loc.end.line = -1; {
loc.start.column = loc.end.column = -1; uniqstr loc_name = muscle_name (variable, "loc");
muscle_insert (loc_name, ""); location loc;
muscle_location_grow (loc_name, loc); loc.start.file = loc.end.file = "<default value>";
muscle_insert (syncline_name, ""); loc.start.line = loc.end.line = -1;
loc.start.column = loc.end.column = -1;
muscle_insert (loc_name, "");
muscle_location_grow (loc_name, loc);
}
muscle_insert (muscle_name (variable, "syncline"), "");
} }
} }
@@ -646,8 +698,9 @@ muscle_percent_define_check_values (char const * const *values)
for (; *values; ++values) for (; *values; ++values)
{ {
char const * const *variablep = values; char const * const *variablep = values;
char const *name = UNIQSTR_CONCAT ("percent_define(", *variablep, ")"); uniqstr name = muscle_name (*variablep, NULL);
char *value = string_decode (name); char *value = string_decode (name);
muscle_percent_define_check_kind (*variablep, muscle_keyword);
if (value) if (value)
{ {
for (++values; *values; ++values) for (++values; *values; ++values)
@@ -664,7 +717,7 @@ muscle_percent_define_check_values (char const * const *values)
quote (*variablep), quote_n (1, value)); quote (*variablep), quote_n (1, value));
i += SUB_INDENT; i += SUB_INDENT;
for (values = variablep + 1; *values; ++values) for (values = variablep + 1; *values; ++values)
complain_indent (&loc, complaint | no_caret, &i, complain_indent (&loc, complaint | no_caret | silent, &i,
_("accepted value: %s"), quote (*values)); _("accepted value: %s"), quote (*values));
} }
else else
@@ -711,11 +764,6 @@ muscle_m4_output_processor (void *entry, void *out)
} }
/*----------------------------------------------------------------.
| Output the definition of all the current muscles into a list of |
| m4_defines. |
`----------------------------------------------------------------*/
void void
muscles_m4_output (FILE *out) muscles_m4_output (FILE *out)
{ {
+44 -18
View File
@@ -24,10 +24,41 @@
# include "location.h" # 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); 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); 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); 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); char *muscle_find (char const *key);
/* Free all the memory consumed by the muscle machinery only. */
void muscle_free (void); void muscle_free (void);
@@ -47,14 +78,14 @@ extern struct obstack muscle_obstack;
} while (0) } while (0)
# define MUSCLE_INSERT_INT(Key, Value) \ # define MUSCLE_INSERT_INT(Key, Value) \
MUSCLE_INSERTF(Key, "%d", Value) MUSCLE_INSERTF (Key, "%d", Value)
# define MUSCLE_INSERT_LONG_INT(Key, Value) \ # define MUSCLE_INSERT_LONG_INT(Key, Value) \
MUSCLE_INSERTF(Key, "%ld", Value) MUSCLE_INSERTF (Key, "%ld", Value)
/* Key -> Value, but don't apply escaping to Value. */ /* Key -> Value, but don't apply escaping to Value. */
# define MUSCLE_INSERT_STRING_RAW(Key, Value) \ # define MUSCLE_INSERT_STRING_RAW(Key, Value) \
MUSCLE_INSERTF(Key, "%s", Value) MUSCLE_INSERTF (Key, "%s", Value)
/* Key -> Value, applying M4 escaping to Value. */ /* Key -> Value, applying M4 escaping to Value. */
# define MUSCLE_INSERT_STRING(Key, Value) \ # define MUSCLE_INSERT_STRING(Key, Value) \
@@ -63,23 +94,14 @@ extern struct obstack muscle_obstack;
muscle_insert (Key, obstack_finish0 (&muscle_obstack)); \ muscle_insert (Key, obstack_finish0 (&muscle_obstack)); \
} while (0) } while (0)
/* Key -> Value, applying C escaping to Value (and then M4). */
# define MUSCLE_INSERT_C_STRING(Key, Value) \ # define MUSCLE_INSERT_C_STRING(Key, Value) \
do { \ MUSCLE_INSERT_STRING (Key, quotearg_style (c_quoting_style, Value))
obstack_escape (&muscle_obstack, \
quotearg_style (c_quoting_style, Value)); \
muscle_insert (Key, obstack_finish0 (&muscle_obstack)); \
} while (0)
/* Append VALUE to the current value of KEY. If KEY did not already
exist, create it. Use MUSCLE_OBSTACK. De-allocate the previously
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 /* Append VALUE to the current value of KEY, using muscle_grow. But
in addition, issue a synchronization line for the location LOC. */ in addition, issue a synchronization line for the location LOC.
Be sure to append on a new line. */
void muscle_code_grow (const char *key, const char *value, location loc); void muscle_code_grow (const char *key, const char *value, location loc);
@@ -92,14 +114,15 @@ void muscle_pair_list_grow (const char *muscle,
/* Grow KEY for the occurrence of the name USER_NAME at LOC appropriately for /* 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 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, void muscle_user_name_list_grow (char const *key, char const *user_name,
location loc); location loc);
/* Indicates whether a variable's value was specified with -D/--define, with /* Indicates whether a variable's value was specified with -D/--define, with
-F/--force-define, or in the grammar file. */ -F/--force-define, or in the grammar file. */
typedef enum { 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_GRAMMAR_FILE
} muscle_percent_define_how; } muscle_percent_define_how;
@@ -113,6 +136,7 @@ typedef enum {
this as a user occurrence of VARIABLE by invoking this as a user occurrence of VARIABLE by invoking
muscle_user_name_list_grow. */ muscle_user_name_list_grow. */
void muscle_percent_define_insert (char const *variable, location variable_loc, void muscle_percent_define_insert (char const *variable, location variable_loc,
muscle_kind kind,
char const *value, char const *value,
muscle_percent_define_how how); muscle_percent_define_how how);
@@ -186,6 +210,8 @@ void muscle_percent_define_check_values (char const * const *values);
void muscle_percent_code_grow (char const *qualifier, location qualifier_loc, void muscle_percent_code_grow (char const *qualifier, location qualifier_loc,
char const *code, location code_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); void muscles_m4_output (FILE *out);
#endif /* not MUSCLE_TAB_H_ */ #endif /* not MUSCLE_TAB_H_ */
+32 -31
View File
@@ -90,20 +90,19 @@ Name (char const *name, \
\ \
lmin = min; \ lmin = min; \
lmax = max; \ lmax = max; \
/* Build `NAME_min' and `NAME_max' in the obstack. */ \ /* Build 'NAME_min' and 'NAME_max' in the obstack. */ \
obstack_printf (&format_obstack, "%s_min", name); \ obstack_printf (&format_obstack, "%s_min", name); \
MUSCLE_INSERT_LONG_INT (obstack_finish0 (&format_obstack), lmin); \ MUSCLE_INSERT_LONG_INT (obstack_finish0 (&format_obstack), lmin); \
obstack_printf (&format_obstack, "%s_max", name); \ obstack_printf (&format_obstack, "%s_max", name); \
MUSCLE_INSERT_LONG_INT (obstack_finish0 (&format_obstack), lmax); \ MUSCLE_INSERT_LONG_INT (obstack_finish0 (&format_obstack), lmax); \
} }
GENERATE_MUSCLE_INSERT_TABLE(muscle_insert_unsigned_int_table, unsigned int) GENERATE_MUSCLE_INSERT_TABLE (muscle_insert_unsigned_int_table, unsigned int)
GENERATE_MUSCLE_INSERT_TABLE(muscle_insert_int_table, int) 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_base_table, base_number)
GENERATE_MUSCLE_INSERT_TABLE(muscle_insert_rule_number_table, rule_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_symbol_number_table, symbol_number)
GENERATE_MUSCLE_INSERT_TABLE(muscle_insert_state_number_table, state_number) GENERATE_MUSCLE_INSERT_TABLE (muscle_insert_state_number_table, state_number)
/*----------------------------------------------------------------. /*----------------------------------------------------------------.
| Print to OUT a representation of CP quoted and escaped for M4. | | Print to OUT a representation of CP quoted and escaped for M4. |
@@ -150,7 +149,7 @@ prepare_symbols (void)
MUSCLE_INSERT_INT ("tokens_number", ntokens); MUSCLE_INSERT_INT ("tokens_number", ntokens);
MUSCLE_INSERT_INT ("nterms_number", nvars); MUSCLE_INSERT_INT ("nterms_number", nvars);
MUSCLE_INSERT_INT ("symbols_number", nsyms); MUSCLE_INSERT_INT ("symbols_number", nsyms);
MUSCLE_INSERT_INT ("undef_token_number", undeftoken->number); MUSCLE_INSERT_INT ("undef_token_number", undeftoken->content->number);
MUSCLE_INSERT_INT ("user_token_number_max", max_user_token_number); MUSCLE_INSERT_INT ("user_token_number_max", max_user_token_number);
muscle_insert_symbol_number_table ("translate", muscle_insert_symbol_number_table ("translate",
@@ -198,7 +197,7 @@ prepare_symbols (void)
int i; int i;
int *values = xnmalloc (ntokens, sizeof *values); int *values = xnmalloc (ntokens, sizeof *values);
for (i = 0; i < ntokens; ++i) for (i = 0; i < ntokens; ++i)
values[i] = symbols[i]->user_token_number; values[i] = symbols[i]->content->user_token_number;
muscle_insert_int_table ("toknum", values, muscle_insert_int_table ("toknum", values,
values[0], 1, ntokens); values[0], 1, ntokens);
free (values); free (values);
@@ -227,7 +226,7 @@ prepare_rules (void)
/* LHS of the rule R. */ /* LHS of the rule R. */
r1[r] = rules[r].lhs->number; r1[r] = rules[r].lhs->number;
/* Length of rule R's RHS. */ /* Length of rule R's RHS. */
r2[r] = rule_rhs_length(&rules[r]); r2[r] = rule_rhs_length (&rules[r]);
/* Line where rule was defined. */ /* Line where rule was defined. */
rline[r] = rules[r].location.start.line; rline[r] = rules[r].location.start.line;
/* Dynamic precedence (GLR). */ /* Dynamic precedence (GLR). */
@@ -284,9 +283,9 @@ prepare_states (void)
static int static int
symbol_type_name_cmp (const symbol **lhs, const symbol **rhs) symbol_type_name_cmp (const symbol **lhs, const symbol **rhs)
{ {
int res = uniqstr_cmp ((*lhs)->type_name, (*rhs)->type_name); int res = uniqstr_cmp ((*lhs)->content->type_name, (*rhs)->content->type_name);
if (!res) if (!res)
res = (*lhs)->number - (*rhs)->number; res = (*lhs)->content->number - (*rhs)->content->number;
return res; return res;
} }
@@ -321,8 +320,9 @@ type_names_output (FILE *out)
/* The index of the first symbol of the current type-name. */ /* The index of the first symbol of the current type-name. */
int i0 = i; int i0 = i;
fputs (i ? ",\n[" : "[", out); fputs (i ? ",\n[" : "[", out);
for (; i < nsyms && syms[i]->type_name == syms[i0]->type_name; ++i) for (; i < nsyms
fprintf (out, "%s%d", i != i0 ? ", " : "", syms[i]->number); && syms[i]->content->type_name == syms[i0]->content->type_name; ++i)
fprintf (out, "%s%d", i != i0 ? ", " : "", syms[i]->content->number);
fputs ("]", out); fputs ("]", out);
} }
fputs ("])\n\n", out); fputs ("])\n\n", out);
@@ -417,32 +417,33 @@ prepare_symbol_definitions (void)
/* Whether the symbol has an identifier. */ /* Whether the symbol has an identifier. */
value = symbol_id_get (sym); value = symbol_id_get (sym);
SET_KEY("has_id"); SET_KEY ("has_id");
MUSCLE_INSERT_INT (key, !!value); MUSCLE_INSERT_INT (key, !!value);
/* Its identifier. */ /* Its identifier. */
SET_KEY("id"); SET_KEY ("id");
MUSCLE_INSERT_STRING (key, value ? value : ""); MUSCLE_INSERT_STRING (key, value ? value : "");
/* Its tag. Typically for documentation purpose. */ /* Its tag. Typically for documentation purpose. */
SET_KEY("tag"); SET_KEY ("tag");
MUSCLE_INSERT_STRING (key, sym->tag); MUSCLE_INSERT_STRING (key, sym->tag);
SET_KEY("user_number"); SET_KEY ("user_number");
MUSCLE_INSERT_INT (key, sym->user_token_number); MUSCLE_INSERT_INT (key, sym->content->user_token_number);
SET_KEY("is_token"); SET_KEY ("is_token");
MUSCLE_INSERT_INT (key, MUSCLE_INSERT_INT (key,
i < ntokens && sym != errtoken && sym != undeftoken); i < ntokens && sym != errtoken && sym != undeftoken);
SET_KEY("number"); SET_KEY ("number");
MUSCLE_INSERT_INT (key, sym->number); MUSCLE_INSERT_INT (key, sym->content->number);
SET_KEY("has_type"); SET_KEY ("has_type");
MUSCLE_INSERT_INT (key, !!sym->type_name); MUSCLE_INSERT_INT (key, !!sym->content->type_name);
SET_KEY("type"); SET_KEY ("type");
MUSCLE_INSERT_STRING (key, sym->type_name ? sym->type_name : ""); MUSCLE_INSERT_STRING (key, sym->content->type_name
? sym->content->type_name : "");
{ {
int j; int j;
@@ -451,18 +452,18 @@ prepare_symbol_definitions (void)
/* "printer", not "%printer". */ /* "printer", not "%printer". */
char const *pname = code_props_type_string (j) + 1; char const *pname = code_props_type_string (j) + 1;
code_props const *p = symbol_code_props_get (sym, j); code_props const *p = symbol_code_props_get (sym, j);
SET_KEY2("has", pname); SET_KEY2 ("has", pname);
MUSCLE_INSERT_INT (key, !!p->code); MUSCLE_INSERT_INT (key, !!p->code);
if (p->code) if (p->code)
{ {
SET_KEY2(pname, "file"); SET_KEY2 (pname, "file");
MUSCLE_INSERT_STRING (key, p->location.start.file); MUSCLE_INSERT_STRING (key, p->location.start.file);
SET_KEY2(pname, "line"); SET_KEY2 (pname, "line");
MUSCLE_INSERT_INT (key, p->location.start.line); MUSCLE_INSERT_INT (key, p->location.start.line);
SET_KEY(pname); SET_KEY (pname);
MUSCLE_INSERT_STRING_RAW (key, p->code); MUSCLE_INSERT_STRING_RAW (key, p->code);
} }
} }
+698 -696
View File
File diff suppressed because it is too large Load Diff
+89 -133
View File
@@ -1,4 +1,4 @@
/* A Bison parser, made by GNU Bison 2.7.1021-bb417-dirty. */ /* A Bison parser, made by GNU Bison 3.0. */
/* Bison interface for Yacc-like parsers in C /* Bison interface for Yacc-like parsers in C
@@ -48,10 +48,12 @@
extern int gram_debug; extern int gram_debug;
#endif #endif
/* "%code requires" blocks. */ /* "%code requires" blocks. */
#line 223 "src/parse-gram.y" /* yacc.c:1932 */ #line 21 "src/parse-gram.y" /* yacc.c:1909 */
#include "symlist.h"
#include "symtab.h"
#line 221 "src/parse-gram.y" /* yacc.c:1909 */
# ifndef PARAM_TYPE
# define PARAM_TYPE
typedef enum typedef enum
{ {
param_none = 0, param_none = 0,
@@ -59,10 +61,10 @@ extern int gram_debug;
param_parse = 1 << 1, param_parse = 1 << 1,
param_both = param_lex | param_parse param_both = param_lex | param_parse
} param_type; } param_type;
# endif #line 645 "src/parse-gram.y" /* yacc.c:1909 */
#include "muscle-tab.h"
#line 68 "src/parse-gram.h" /* yacc.c:1909 */
#line 66 "src/parse-gram.h" /* yacc.c:1932 */
/* Token type. */ /* Token type. */
#ifndef GRAM_TOKENTYPE #ifndef GRAM_TOKENTYPE
@@ -71,143 +73,97 @@ extern int gram_debug;
{ {
GRAM_EOF = 0, GRAM_EOF = 0,
STRING = 258, STRING = 258,
INT = 259, PERCENT_TOKEN = 259,
PERCENT_TOKEN = 260, PERCENT_NTERM = 260,
PERCENT_NTERM = 261, PERCENT_TYPE = 261,
PERCENT_TYPE = 262, PERCENT_DESTRUCTOR = 262,
PERCENT_DESTRUCTOR = 263, PERCENT_PRINTER = 263,
PERCENT_PRINTER = 264, PERCENT_LEFT = 264,
PERCENT_LEFT = 265, PERCENT_RIGHT = 265,
PERCENT_RIGHT = 266, PERCENT_NONASSOC = 266,
PERCENT_NONASSOC = 267, PERCENT_PRECEDENCE = 267,
PERCENT_PRECEDENCE = 268, PERCENT_PREC = 268,
PERCENT_PREC = 269, PERCENT_DPREC = 269,
PERCENT_DPREC = 270, PERCENT_MERGE = 270,
PERCENT_MERGE = 271, PERCENT_CODE = 271,
PERCENT_CODE = 272, PERCENT_DEFAULT_PREC = 272,
PERCENT_DEFAULT_PREC = 273, PERCENT_DEFINE = 273,
PERCENT_DEFINE = 274, PERCENT_DEFINES = 274,
PERCENT_DEFINES = 275, PERCENT_ERROR_VERBOSE = 275,
PERCENT_ERROR_VERBOSE = 276, PERCENT_EXPECT = 276,
PERCENT_EXPECT = 277, PERCENT_EXPECT_RR = 277,
PERCENT_EXPECT_RR = 278, PERCENT_FLAG = 278,
PERCENT_FLAG = 279, PERCENT_FILE_PREFIX = 279,
PERCENT_FILE_PREFIX = 280, PERCENT_GLR_PARSER = 280,
PERCENT_GLR_PARSER = 281, PERCENT_INITIAL_ACTION = 281,
PERCENT_INITIAL_ACTION = 282, PERCENT_LANGUAGE = 282,
PERCENT_LANGUAGE = 283, PERCENT_NAME_PREFIX = 283,
PERCENT_NAME_PREFIX = 284, PERCENT_NO_DEFAULT_PREC = 284,
PERCENT_NO_DEFAULT_PREC = 285, PERCENT_NO_LINES = 285,
PERCENT_NO_LINES = 286, PERCENT_NONDETERMINISTIC_PARSER = 286,
PERCENT_NONDETERMINISTIC_PARSER = 287, PERCENT_OUTPUT = 287,
PERCENT_OUTPUT = 288, PERCENT_REQUIRE = 288,
PERCENT_REQUIRE = 289, PERCENT_SKELETON = 289,
PERCENT_SKELETON = 290, PERCENT_START = 290,
PERCENT_START = 291, PERCENT_TOKEN_TABLE = 291,
PERCENT_TOKEN_TABLE = 292, PERCENT_VERBOSE = 292,
PERCENT_VERBOSE = 293, PERCENT_YACC = 293,
PERCENT_YACC = 294, BRACED_CODE = 294,
BRACED_CODE = 295, BRACED_PREDICATE = 295,
BRACED_PREDICATE = 296, BRACKETED_ID = 296,
BRACKETED_ID = 297, CHAR = 297,
CHAR = 298, EPILOGUE = 298,
EPILOGUE = 299, EQUAL = 299,
EQUAL = 300, ID = 300,
ID = 301, ID_COLON = 301,
ID_COLON = 302, PERCENT_PERCENT = 302,
PERCENT_PERCENT = 303, PIPE = 303,
PIPE = 304, PROLOGUE = 304,
PROLOGUE = 305, SEMICOLON = 305,
SEMICOLON = 306, TAG = 306,
TAG = 307, TAG_ANY = 307,
TAG_ANY = 308, TAG_NONE = 308,
TAG_NONE = 309, INT = 309,
PERCENT_PARAM = 310, PERCENT_PARAM = 310,
PERCENT_UNION = 311 PERCENT_UNION = 311,
PERCENT_EMPTY = 312
}; };
#endif #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_PRECEDENCE 268
#define PERCENT_PREC 269
#define PERCENT_DPREC 270
#define PERCENT_MERGE 271
#define PERCENT_CODE 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_FLAG 279
#define PERCENT_FILE_PREFIX 280
#define PERCENT_GLR_PARSER 281
#define PERCENT_INITIAL_ACTION 282
#define PERCENT_LANGUAGE 283
#define PERCENT_NAME_PREFIX 284
#define PERCENT_NO_DEFAULT_PREC 285
#define PERCENT_NO_LINES 286
#define PERCENT_NONDETERMINISTIC_PARSER 287
#define PERCENT_OUTPUT 288
#define PERCENT_REQUIRE 289
#define PERCENT_SKELETON 290
#define PERCENT_START 291
#define PERCENT_TOKEN_TABLE 292
#define PERCENT_VERBOSE 293
#define PERCENT_YACC 294
#define BRACED_CODE 295
#define BRACED_PREDICATE 296
#define BRACKETED_ID 297
#define CHAR 298
#define EPILOGUE 299
#define EQUAL 300
#define ID 301
#define ID_COLON 302
#define PERCENT_PERCENT 303
#define PIPE 304
#define PROLOGUE 305
#define SEMICOLON 306
#define TAG 307
#define TAG_ANY 308
#define TAG_NONE 309
#define PERCENT_PARAM 310
#define PERCENT_UNION 311
/* Value type. */ /* Value type. */
#if ! defined GRAM_STYPE && ! defined GRAM_STYPE_IS_DECLARED #if ! defined GRAM_STYPE && ! defined GRAM_STYPE_IS_DECLARED
typedef union GRAM_STYPE GRAM_STYPE; typedef union GRAM_STYPE GRAM_STYPE;
union GRAM_STYPE union GRAM_STYPE
{ {
#line 109 "src/parse-gram.y" /* yacc.c:1932 */ #line 182 "src/parse-gram.y" /* yacc.c:1909 */
unsigned char character;
assoc assoc; #line 186 "src/parse-gram.y" /* yacc.c:1909 */
char *code; char *code;
char const *chars; #line 191 "src/parse-gram.y" /* yacc.c:1909 */
int integer; uniqstr uniqstr;
named_ref *named_ref; #line 199 "src/parse-gram.y" /* yacc.c:1909 */
symbol *symbol; int integer;
symbol_list *list; #line 203 "src/parse-gram.y" /* yacc.c:1909 */
uniqstr uniqstr; symbol *symbol;
unsigned char character; #line 208 "src/parse-gram.y" /* yacc.c:1909 */
assoc assoc;
#line 247 "src/parse-gram.y" /* yacc.c:1932 */ #line 211 "src/parse-gram.y" /* yacc.c:1909 */
symbol_list *list;
param_type param; #line 214 "src/parse-gram.y" /* yacc.c:1909 */
named_ref *named_ref;
#line 423 "src/parse-gram.y" /* yacc.c:1932 */ #line 241 "src/parse-gram.y" /* yacc.c:1909 */
param_type param;
#line 409 "src/parse-gram.y" /* yacc.c:1909 */
code_props_type code_type; code_props_type code_type;
#line 647 "src/parse-gram.y" /* yacc.c:1909 */
#line 211 "src/parse-gram.h" /* yacc.c:1932 */ struct
{
char const *chars;
muscle_kind kind;
} value;
#line 167 "src/parse-gram.h" /* yacc.c:1909 */
}; };
# define GRAM_STYPE_IS_TRIVIAL 1 # define GRAM_STYPE_IS_TRIVIAL 1
# define GRAM_STYPE_IS_DECLARED 1 # define GRAM_STYPE_IS_DECLARED 1
+184 -145
View File
@@ -1,4 +1,4 @@
%{/* Bison Grammar Parser -*- C -*- /* Bison Grammar Parser -*- C -*-
Copyright (C) 2002-2013 Free Software Foundation, Inc. Copyright (C) 2002-2013 Free Software Foundation, Inc.
@@ -17,45 +17,35 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */ along with this program. If not, see <http://www.gnu.org/licenses/>. */
%code requires
{
#include "symlist.h"
#include "symtab.h"
}
%code top
{
/* On column 0 to please syntax-check. */
#include <config.h> #include <config.h>
#include "system.h" }
#include "c-ctype.h"
#include "complain.h"
#include "conflicts.h"
#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"
#define YYLLOC_DEFAULT(Current, Rhs, N) (Current) = lloc_default (Rhs, N)
static YYLTYPE lloc_default (YYLTYPE const *, int);
#define YY_LOCATION_PRINT(File, Loc) \
location_print (File, Loc)
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 *);
static char const *char_name (char);
%}
%code %code
{ {
#include "system.h"
#include "c-ctype.h"
#include "complain.h"
#include "conflicts.h"
#include "files.h"
#include "getargs.h"
#include "gram.h"
#include "named-ref.h"
#include "quotearg.h"
#include "reader.h"
#include "scan-gram.h"
#include "scan-code.h"
#include "xmemdup0.h"
static int current_prec = 0; static int current_prec = 0;
static location current_lhs_location; static location current_lhs_location;
static named_ref *current_lhs_named_ref; static named_ref *current_lhs_named_ref;
@@ -66,20 +56,37 @@ static char const *char_name (char);
/** Set the new current left-hand side symbol, possibly common /** Set the new current left-hand side symbol, possibly common
* to several right-hand side parts of rule. * to several right-hand side parts of rule.
*/ */
static static void current_lhs (symbol *sym, location loc, named_ref *ref);
void
current_lhs(symbol *sym, location loc, named_ref *ref) #define YYLLOC_DEFAULT(Current, Rhs, N) \
{ (Current) = lloc_default (Rhs, N)
current_lhs_symbol = sym; static YYLTYPE lloc_default (YYLTYPE const *, int);
current_lhs_location = loc;
/* In order to simplify memory management, named references for lhs #define YY_LOCATION_PRINT(File, Loc) \
are always assigned by deep copy into the current symbol_list location_print (Loc, File)
node. This is because a single named-ref in the grammar may
result in several uses when the user factors lhs between several /* Strip initial '{' and final '}' (must be first and last characters).
rules using "|". Therefore free the parser's original copy. */ Return the result. */
free (current_lhs_named_ref); static char *strip_braces (char *code);
current_lhs_named_ref = ref;
} /* Convert CODE by calling code_props_plain_init if PLAIN, otherwise
code_props_symbol_action_init. Call
gram_scanner_last_string_free to release the latest string from
the scanner (should be CODE). */
static char const *translate_code (char *code, location loc, bool plain);
/* Convert CODE by calling code_props_plain_init after having
stripped the first and last characters (expected to be '{', and
'}'). Call gram_scanner_last_string_free to release the latest
string from the scanner (should be CODE). */
static char const *translate_code_braceless (char *code, location loc);
static void version_check (location const *loc, char const *version);
static void gram_error (location const *, char const *);
/* A string that describes a char (e.g., 'a' -> "'a'"). */
static char const *char_name (char);
#define YYTYPE_INT16 int_fast16_t #define YYTYPE_INT16 int_fast16_t
#define YYTYPE_INT8 int_fast8_t #define YYTYPE_INT8 int_fast8_t
@@ -87,8 +94,8 @@ static char const *char_name (char);
#define YYTYPE_UINT8 uint_fast8_t #define YYTYPE_UINT8 uint_fast8_t
} }
%define api.prefix "gram_" %define api.prefix {gram_}
%define api.pure %define api.pure full
%define locations %define locations
%define parse.error verbose %define parse.error verbose
%define parse.lac full %define parse.lac full
@@ -105,23 +112,9 @@ static char const *char_name (char);
boundary_set (&@$.end, current_file, 1, 1); boundary_set (&@$.end, current_file, 1, 1);
} }
%union
{
assoc assoc;
char *code;
char const *chars;
int integer;
named_ref *named_ref;
symbol *symbol;
symbol_list *list;
uniqstr uniqstr;
unsigned char character;
};
/* Define the tokens together with their human representation. */ /* Define the tokens together with their human representation. */
%token GRAM_EOF 0 "end of file" %token GRAM_EOF 0 "end of file"
%token STRING "string" %token STRING "string"
%token INT "integer"
%token PERCENT_TOKEN "%token" %token PERCENT_TOKEN "%token"
%token PERCENT_NTERM "%nterm" %token PERCENT_NTERM "%nterm"
@@ -186,18 +179,16 @@ static char const *char_name (char);
%token TAG_ANY "<*>" %token TAG_ANY "<*>"
%token TAG_NONE "<>" %token TAG_NONE "<>"
%union {unsigned char character;}
%type <character> CHAR %type <character> CHAR
%printer { fputs (char_name ($$), yyo); } CHAR %printer { fputs (char_name ($$), yyo); } CHAR
/* braceless is not to be used for rule or symbol actions, as it %union {char *code;};
calls code_props_plain_init. */ %type <code> "{...}" "%?{...}" "%{...%}" EPILOGUE STRING
%type <chars> STRING "%{...%}" EPILOGUE braceless content.opt %printer { fputs (quotearg_style (c_quoting_style, $$), yyo); } STRING
%type <code> "{...}" "%?{...}" %printer { fprintf (yyo, "{\n%s\n}", $$); } <code>
%printer { fputs (quotearg_style (c_quoting_style, $$), yyo); }
STRING
%printer { fprintf (yyo, "{\n%s\n}", $$); }
braceless content.opt "{...}" "%{...%}" EPILOGUE
%union {uniqstr uniqstr;}
%type <uniqstr> BRACKETED_ID ID ID_COLON PERCENT_FLAG TAG tag variable %type <uniqstr> BRACKETED_ID ID ID_COLON PERCENT_FLAG TAG tag variable
%printer { fputs ($$, yyo); } <uniqstr> %printer { fputs ($$, yyo); } <uniqstr>
%printer { fprintf (yyo, "[%s]", $$); } BRACKETED_ID %printer { fprintf (yyo, "[%s]", $$); } BRACKETED_ID
@@ -205,15 +196,22 @@ static char const *char_name (char);
%printer { fprintf (yyo, "%%%s", $$); } PERCENT_FLAG %printer { fprintf (yyo, "%%%s", $$); } PERCENT_FLAG
%printer { fprintf (yyo, "<%s>", $$); } TAG tag %printer { fprintf (yyo, "<%s>", $$); } TAG tag
%type <integer> INT %union {int integer;};
%token <integer> INT "integer"
%printer { fprintf (yyo, "%d", $$); } <integer> %printer { fprintf (yyo, "%d", $$); } <integer>
%union {symbol *symbol;}
%type <symbol> id id_colon string_as_id symbol symbol.prec %type <symbol> id id_colon string_as_id symbol symbol.prec
%printer { fprintf (yyo, "%s", $$->tag); } <symbol> %printer { fprintf (yyo, "%s", $$->tag); } <symbol>
%printer { fprintf (yyo, "%s:", $$->tag); } id_colon %printer { fprintf (yyo, "%s:", $$->tag); } id_colon
%union {assoc assoc;};
%type <assoc> precedence_declarator %type <assoc> precedence_declarator
%union {symbol_list *list;}
%type <list> symbols.1 symbols.prec generic_symlist generic_symlist_item %type <list> symbols.1 symbols.prec generic_symlist generic_symlist_item
%union {named_ref *named_ref;}
%type <named_ref> named_ref.opt %type <named_ref> named_ref.opt
/*---------. /*---------.
@@ -221,8 +219,6 @@ static char const *char_name (char);
`---------*/ `---------*/
%code requires %code requires
{ {
# ifndef PARAM_TYPE
# define PARAM_TYPE
typedef enum typedef enum
{ {
param_none = 0, param_none = 0,
@@ -230,7 +226,6 @@ static char const *char_name (char);
param_parse = 1 << 1, param_parse = 1 << 1,
param_both = param_lex | param_parse param_both = param_lex | param_parse
} param_type; } param_type;
# endif
}; };
%code %code
{ {
@@ -243,20 +238,17 @@ static char const *char_name (char);
static void add_param (param_type type, char *decl, location loc); static void add_param (param_type type, char *decl, location loc);
static param_type current_param = param_none; static param_type current_param = param_none;
}; };
%union %union {param_type param;}
{
param_type param;
}
%token <param> PERCENT_PARAM "%param"; %token <param> PERCENT_PARAM "%param";
%printer %printer
{ {
switch ($$) switch ($$)
{ {
#define CASE(In, Out) \ #define CASE(In, Out) \
case param_ ## In: fputs ("%" #Out, stderr); break case param_ ## In: fputs ("%" #Out, yyo); break
CASE(lex, lex-param); CASE (lex, lex-param);
CASE(parse, parse-param); CASE (parse, parse-param);
CASE(both, param); CASE (both, param);
#undef CASE #undef CASE
case param_none: aver (false); break; case param_none: aver (false); break;
} }
@@ -278,7 +270,7 @@ input:
`------------------------------------*/ `------------------------------------*/
prologue_declarations: prologue_declarations:
/* Nothing */ %empty
| prologue_declarations prologue_declaration | prologue_declarations prologue_declaration
; ;
@@ -286,21 +278,17 @@ prologue_declaration:
grammar_declaration grammar_declaration
| "%{...%}" | "%{...%}"
{ {
code_props plain_code;
code_props_plain_init (&plain_code, $1, @1);
code_props_translate_code (&plain_code);
gram_scanner_last_string_free ();
muscle_code_grow (union_seen ? "post_prologue" : "pre_prologue", muscle_code_grow (union_seen ? "post_prologue" : "pre_prologue",
plain_code.code, @1); translate_code ($1, @1, true), @1);
code_scanner_last_string_free (); code_scanner_last_string_free ();
} }
| "%<flag>" | "%<flag>"
{ {
muscle_percent_define_ensure ($1, @1, true); muscle_percent_define_ensure ($1, @1, true);
} }
| "%define" variable content.opt | "%define" variable value
{ {
muscle_percent_define_insert ($2, @2, $3, muscle_percent_define_insert ($2, @2, $3.kind, $3.chars,
MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE); MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE);
} }
| "%defines" { defines_flag = true; } | "%defines" { defines_flag = true; }
@@ -311,7 +299,8 @@ prologue_declaration:
} }
| "%error-verbose" | "%error-verbose"
{ {
muscle_percent_define_insert ("parse.error", @1, "verbose", muscle_percent_define_insert ("parse.error", @1, muscle_keyword,
"verbose",
MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE); MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE);
} }
| "%expect" INT { expected_sr_conflicts = $2; } | "%expect" INT { expected_sr_conflicts = $2; }
@@ -324,11 +313,7 @@ prologue_declaration:
} }
| "%initial-action" "{...}" | "%initial-action" "{...}"
{ {
code_props action; muscle_code_grow ("initial_action", translate_code ($2, @2, false), @2);
code_props_symbol_action_init (&action, $2, @2);
code_props_translate_code (&action);
gram_scanner_last_string_free ();
muscle_code_grow ("initial_action", action.code, @2);
code_scanner_last_string_free (); code_scanner_last_string_free ();
} }
| "%language" STRING { language_argmatch ($2, grammar_prio, @1); } | "%language" STRING { language_argmatch ($2, grammar_prio, @1); }
@@ -405,16 +390,17 @@ grammar_declaration:
{ {
default_prec = false; default_prec = false;
} }
| "%code" braceless | "%code" "{...}"
{ {
/* Do not invoke muscle_percent_code_grow here since it invokes /* Do not invoke muscle_percent_code_grow here since it invokes
muscle_user_name_list_grow. */ muscle_user_name_list_grow. */
muscle_code_grow ("percent_code()", $2, @2); muscle_code_grow ("percent_code()",
translate_code_braceless ($2, @2), @2);
code_scanner_last_string_free (); code_scanner_last_string_free ();
} }
| "%code" ID braceless | "%code" ID "{...}"
{ {
muscle_percent_code_grow ($2, @2, $3, @3); muscle_percent_code_grow ($2, @2, translate_code_braceless ($3, @3), @3);
code_scanner_last_string_free (); code_scanner_last_string_free ();
} }
; ;
@@ -434,15 +420,15 @@ code_props_type:
%token PERCENT_UNION "%union"; %token PERCENT_UNION "%union";
union_name: union_name:
/* Nothing. */ {} %empty {}
| ID { muscle_code_grow ("union_name", $1, @1); } | ID { muscle_code_grow ("union_name", $1, @1); }
; ;
grammar_declaration: grammar_declaration:
"%union" union_name braceless "%union" union_name "{...}"
{ {
union_seen = true; union_seen = true;
muscle_code_grow ("stype", $3, @3); muscle_code_grow ("union_members", translate_code_braceless ($3, @3), @3);
code_scanner_last_string_free (); code_scanner_last_string_free ();
} }
; ;
@@ -494,8 +480,8 @@ precedence_declarator:
; ;
tag.opt: tag.opt:
/* Nothing. */ { current_type = NULL; } %empty { current_type = NULL; }
| TAG { current_type = $1; tag_seen = true; } | TAG { current_type = $1; tag_seen = true; }
; ;
/* Just like symbols.1 but accept INT for the sake of POSIX. */ /* Just like symbols.1 but accept INT for the sake of POSIX. */
@@ -507,8 +493,17 @@ symbols.prec:
; ;
symbol.prec: symbol.prec:
symbol { $$ = $1; } symbol
| symbol INT { $$ = $1; symbol_user_token_number_set ($1, $2, @2); } {
$$ = $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. */ /* One or more symbols to be %typed. */
@@ -609,8 +604,9 @@ rhses.1:
| rhses.1 ";" | rhses.1 ";"
; ;
%token PERCENT_EMPTY "%empty";
rhs: rhs:
/* Nothing. */ %empty
{ grammar_current_rule_begin (current_lhs_symbol, current_lhs_location, { grammar_current_rule_begin (current_lhs_symbol, current_lhs_location,
current_lhs_named_ref); } current_lhs_named_ref); }
| rhs symbol named_ref.opt | rhs symbol named_ref.opt
@@ -619,6 +615,8 @@ rhs:
{ grammar_current_rule_action_append ($2, @2, $3, false); } { grammar_current_rule_action_append ($2, @2, $3, false); }
| rhs "%?{...}" | rhs "%?{...}"
{ grammar_current_rule_action_append ($2, @2, NULL, true); } { grammar_current_rule_action_append ($2, @2, NULL, true); }
| rhs "%empty"
{ grammar_current_rule_empty_set (@2); }
| rhs "%prec" symbol | rhs "%prec" symbol
{ grammar_current_rule_prec_set ($3, @3); } { grammar_current_rule_prec_set ($3, @3); }
| rhs "%dprec" INT | rhs "%dprec" INT
@@ -628,44 +626,47 @@ rhs:
; ;
named_ref.opt: named_ref.opt:
/* Nothing. */ { $$ = 0; } %empty { $$ = 0; }
| | BRACKETED_ID { $$ = named_ref_new ($1, @1); }
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. /* 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: variable:
ID ID
| STRING { $$ = uniqstr_new ($1); } | STRING { $$ = uniqstr_new ($1); }
; ;
/* Some content or empty by default. */ /* Some content or empty by default. */
content.opt: %code requires {#include "muscle-tab.h"};
/* Nothing. */ { $$ = ""; } %union
| ID { $$ = $1; } {
| STRING struct
; {
char const *chars;
muscle_kind kind;
/*------------. } value;
| braceless. | };
`------------*/ %type <value> value;
%printer
braceless: {
"{...}" switch ($$.kind)
{ {
code_props plain_code; case muscle_code: fprintf (yyo, "{%s}", $$.chars); break;
$1[strlen ($1) - 1] = '\n'; case muscle_keyword: fprintf (yyo, "%s", $$.chars); break;
code_props_plain_init (&plain_code, $1+1, @1); case muscle_string: fprintf (yyo, "\"%s\"", $$.chars); break;
code_props_translate_code (&plain_code);
gram_scanner_last_string_free ();
$$ = plain_code.code;
} }
} <value>;
value:
%empty { $$.kind = muscle_keyword; $$.chars = ""; }
| ID { $$.kind = muscle_keyword; $$.chars = $1; }
| STRING { $$.kind = muscle_string; $$.chars = $1; }
| "{...}" { $$.kind = muscle_code; $$.chars = strip_braces ($1); }
; ;
@@ -707,14 +708,10 @@ string_as_id:
; ;
epilogue.opt: epilogue.opt:
/* Nothing. */ %empty
| "%%" EPILOGUE | "%%" EPILOGUE
{ {
code_props plain_code; muscle_code_grow ("epilogue", translate_code ($2, @2, true), @2);
code_props_plain_init (&plain_code, $2, @2);
code_props_translate_code (&plain_code);
gram_scanner_last_string_free ();
muscle_code_grow ("epilogue", plain_code.code, @2);
code_scanner_last_string_free (); code_scanner_last_string_free ();
} }
; ;
@@ -750,6 +747,33 @@ lloc_default (YYLTYPE const *rhs, int n)
return loc; return loc;
} }
static
char *strip_braces (char *code)
{
code[strlen (code) - 1] = 0;
return code + 1;
}
static
char const *
translate_code (char *code, location loc, bool plain)
{
code_props plain_code;
if (plain)
code_props_plain_init (&plain_code, code, loc);
else
code_props_symbol_action_init (&plain_code, code, loc);
code_props_translate_code (&plain_code);
gram_scanner_last_string_free ();
return plain_code.code;
}
static
char const *
translate_code_braceless (char *code, location loc)
{
return translate_code (strip_braces (code), loc, true);
}
static void static void
add_param (param_type type, char *decl, location loc) add_param (param_type type, char *decl, location loc)
@@ -832,3 +856,18 @@ char_name (char c)
return quotearg_style (escape_quoting_style, buf); return quotearg_style (escape_quoting_style, buf);
} }
} }
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;
}
+17 -11
View File
@@ -45,7 +45,8 @@ struct escape_buf
char *ptr; char *ptr;
size_t size; size_t size;
}; };
static struct escape_buf escape_bufs[3]; enum { num_escape_bufs = 3 };
static struct escape_buf escape_bufs[num_escape_bufs];
/*--------------------------------. /*--------------------------------.
@@ -209,7 +210,7 @@ print_errs (FILE *out, int level, state *s)
/*-------------------------------------------------------------------------. /*-------------------------------------------------------------------------.
| 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 | | If not ENABLED, the rule is masked by a shift or a reduce (S/R and |
| R/R conflicts). | | R/R conflicts). |
`-------------------------------------------------------------------------*/ `-------------------------------------------------------------------------*/
@@ -259,7 +260,7 @@ print_reductions (FILE *out, int level, state *s)
bitset_set (no_reduce_set, TRANSITION_SYMBOL (trans, i)); bitset_set (no_reduce_set, TRANSITION_SYMBOL (trans, i));
for (i = 0; i < s->errs->num; ++i) for (i = 0; i < s->errs->num; ++i)
if (s->errs->symbols[i]) if (s->errs->symbols[i])
bitset_set (no_reduce_set, s->errs->symbols[i]->number); bitset_set (no_reduce_set, s->errs->symbols[i]->content->number);
if (default_reduction) if (default_reduction)
report = true; report = true;
@@ -387,11 +388,11 @@ print_grammar (FILE *out, int level)
/* Terminals */ /* Terminals */
xml_puts (out, level + 1, "<terminals>"); xml_puts (out, level + 1, "<terminals>");
for (i = 0; i < max_user_token_number + 1; i++) for (i = 0; i < max_user_token_number + 1; i++)
if (token_translations[i] != undeftoken->number) if (token_translations[i] != undeftoken->content->number)
{ {
char const *tag = symbols[token_translations[i]]->tag; char const *tag = symbols[token_translations[i]]->tag;
int precedence = symbols[token_translations[i]]->prec; int precedence = symbols[token_translations[i]]->content->prec;
assoc associativity = symbols[token_translations[i]]->assoc; assoc associativity = symbols[token_translations[i]]->content->assoc;
xml_indent (out, level + 2); xml_indent (out, level + 2);
fprintf (out, fprintf (out,
"<terminal symbol-number=\"%d\" token-number=\"%d\"" "<terminal symbol-number=\"%d\" token-number=\"%d\""
@@ -496,7 +497,6 @@ xml_escape (char const *str)
void void
print_xml (void) print_xml (void)
{ {
state_number i;
int level = 0; int level = 0;
FILE *out = xfopen (spec_xml_file, "w"); FILE *out = xfopen (spec_xml_file, "w");
@@ -522,8 +522,11 @@ print_xml (void)
/* print automaton */ /* print automaton */
fputc ('\n', out); fputc ('\n', out);
xml_puts (out, level + 1, "<automaton>"); xml_puts (out, level + 1, "<automaton>");
for (i = 0; i < nstates; i++) {
print_state (out, level + 2, states[i]); state_number i;
for (i = 0; i < nstates; i++)
print_state (out, level + 2, states[i]);
}
xml_puts (out, level + 1, "</automaton>"); xml_puts (out, level + 1, "</automaton>");
bitset_free (no_reduce_set); bitset_free (no_reduce_set);
@@ -531,8 +534,11 @@ print_xml (void)
xml_puts (out, 0, "</bison-xml-report>"); xml_puts (out, 0, "</bison-xml-report>");
free (escape_bufs[0].ptr); {
free (escape_bufs[1].ptr); int i;
for (i = 0; i < num_escape_bufs; ++i)
free (escape_bufs[i].ptr);
}
xfclose (out); xfclose (out);
} }
+7 -6
View File
@@ -72,7 +72,7 @@ print_core (FILE *out, state *s)
size_t i; size_t i;
item_number *sitems = s->items; item_number *sitems = s->items;
size_t snritems = s->nitems; size_t snritems = s->nitems;
symbol *previous_lhs = NULL; sym_content *previous_lhs = NULL;
/* Output all the items of a state, not only its kernel. */ /* Output all the items of a state, not only its kernel. */
if (report_flag & report_itemsets) if (report_flag & report_itemsets)
@@ -206,7 +206,7 @@ print_errs (FILE *out, state *s)
/*-------------------------------------------------------------------------. /*-------------------------------------------------------------------------.
| 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 | | If not ENABLED, the rule is masked by a shift or a reduce (S/R and |
| R/R conflicts). | | R/R conflicts). |
`-------------------------------------------------------------------------*/ `-------------------------------------------------------------------------*/
@@ -223,7 +223,8 @@ print_reduction (FILE *out, size_t width,
if (!enabled) if (!enabled)
fputc ('[', out); fputc ('[', out);
if (r->number) if (r->number)
fprintf (out, _("reduce using rule %d (%s)"), r->number, r->lhs->tag); fprintf (out, _("reduce using rule %d (%s)"), r->number,
r->lhs->symbol->tag);
else else
fprintf (out, _("accept")); fprintf (out, _("accept"));
if (!enabled) if (!enabled)
@@ -257,7 +258,7 @@ print_reductions (FILE *out, state *s)
bitset_set (no_reduce_set, TRANSITION_SYMBOL (trans, i)); bitset_set (no_reduce_set, TRANSITION_SYMBOL (trans, i));
for (i = 0; i < s->errs->num; ++i) for (i = 0; i < s->errs->num; ++i)
if (s->errs->symbols[i]) if (s->errs->symbols[i])
bitset_set (no_reduce_set, s->errs->symbols[i]->number); bitset_set (no_reduce_set, s->errs->symbols[i]->content->number);
/* Compute the width of the lookahead token column. */ /* Compute the width of the lookahead token column. */
if (default_reduction) if (default_reduction)
@@ -408,7 +409,7 @@ print_grammar (FILE *out)
/* TERMINAL (type #) : rule #s terminal is on RHS */ /* TERMINAL (type #) : rule #s terminal is on RHS */
fprintf (out, "%s\n\n", _("Terminals, with rules where they appear")); fprintf (out, "%s\n\n", _("Terminals, with rules where they appear"));
for (i = 0; i < max_user_token_number + 1; i++) for (i = 0; i < max_user_token_number + 1; i++)
if (token_translations[i] != undeftoken->number) if (token_translations[i] != undeftoken->content->number)
{ {
const char *tag = symbols[token_translations[i]]->tag; const char *tag = symbols[token_translations[i]]->tag;
rule_number r; rule_number r;
@@ -514,7 +515,7 @@ print_results (void)
print_grammar (out); print_grammar (out);
/* If the whole state item sets, not only the kernels, are wanted, /* 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) if (report_flag & report_itemsets)
new_closure (nritems); new_closure (nritems);
/* Storage for print_reductions. */ /* Storage for print_reductions. */
+5 -4
View File
@@ -46,7 +46,7 @@ static void
print_core (struct obstack *oout, state *s) print_core (struct obstack *oout, state *s)
{ {
item_number const *sitems = s->items; item_number const *sitems = s->items;
symbol *previous_lhs = NULL; sym_content *previous_lhs = NULL;
size_t i; size_t i;
size_t snritems = s->nitems; size_t snritems = s->nitems;
@@ -72,11 +72,12 @@ print_core (struct obstack *oout, state *s)
r = &rules[item_number_as_rule_number (*sp)]; r = &rules[item_number_as_rule_number (*sp)];
obstack_printf (oout, "%3d ", r->number); obstack_printf (oout, "%3d ", r->number);
if (previous_lhs && UNIQSTR_EQ (previous_lhs->tag, r->lhs->tag)) if (previous_lhs && UNIQSTR_EQ (previous_lhs->symbol->tag,
r->lhs->symbol->tag))
obstack_printf (oout, "%*s| ", obstack_printf (oout, "%*s| ",
(int) strlen (previous_lhs->tag), ""); (int) strlen (previous_lhs->symbol->tag), "");
else else
obstack_printf (oout, "%s: ", escape (r->lhs->tag)); obstack_printf (oout, "%s: ", escape (r->lhs->symbol->tag));
previous_lhs = r->lhs; previous_lhs = r->lhs;
for (sp = r->rhs; sp < sp1; sp++) for (sp = r->rhs; sp < sp1; sp++)
+107 -67
View File
@@ -129,7 +129,7 @@ record_merge_function_type (int merger, uniqstr type, location declaration_loc)
if (merge_function->type != NULL && !UNIQSTR_EQ (merge_function->type, type)) if (merge_function->type != NULL && !UNIQSTR_EQ (merge_function->type, type))
{ {
unsigned indent = 0; unsigned indent = 0;
complain_indent (&declaration_loc, complaint, &indent, start_complain_indent (&declaration_loc, complaint, &indent,
_("result type clash on merge function %s: " _("result type clash on merge function %s: "
"<%s> != <%s>"), "<%s> != <%s>"),
quote (merge_function->name), type, quote (merge_function->name), type,
@@ -240,13 +240,13 @@ grammar_current_rule_begin (symbol *lhs, location loc,
current_rule = grammar_end; current_rule = grammar_end;
/* Mark the rule's lhs as a nonterminal if not already so. */ /* Mark the rule's lhs as a nonterminal if not already so. */
if (lhs->class == unknown_sym) if (lhs->content->class == unknown_sym)
{ {
lhs->class = nterm_sym; lhs->content->class = nterm_sym;
lhs->number = nvars; lhs->content->number = nvars;
++nvars; ++nvars;
} }
else if (lhs->class == token_sym) else if (lhs->content->class == token_sym)
complain (&loc, complaint, _("rule given for %s, which is a token"), complain (&loc, complaint, _("rule given for %s, which is a token"),
lhs->tag); lhs->tag);
} }
@@ -267,9 +267,9 @@ symbol_should_be_used (symbol_list const *s, bool *midrule_warning)
return true; return true;
if ((s->midrule && s->midrule->action_props.is_value_used) if ((s->midrule && s->midrule->action_props.is_value_used)
|| (s->midrule_parent_rule || (s->midrule_parent_rule
&& symbol_list_n_get (s->midrule_parent_rule, && (symbol_list_n_get (s->midrule_parent_rule,
s->midrule_parent_rhs_index) s->midrule_parent_rhs_index)
->action_props.is_value_used)) ->action_props.is_value_used)))
{ {
*midrule_warning = true; *midrule_warning = true;
return true; return true;
@@ -292,15 +292,15 @@ grammar_rule_check (const symbol_list *r)
Don't worry about the default action if $$ is untyped, since $$'s Don't worry about the default action if $$ is untyped, since $$'s
value can't be used. */ value can't be used. */
if (!r->action_props.code && r->content.sym->type_name) if (!r->action_props.code && r->content.sym->content->type_name)
{ {
symbol *first_rhs = r->next->content.sym; symbol *first_rhs = r->next->content.sym;
/* If $$ is being set in default way, report if any type mismatch. */ /* If $$ is being set in default way, report if any type mismatch. */
if (first_rhs) if (first_rhs)
{ {
char const *lhs_type = r->content.sym->type_name; char const *lhs_type = r->content.sym->content->type_name;
const char *rhs_type = const char *rhs_type =
first_rhs->type_name ? first_rhs->type_name : ""; first_rhs->content->type_name ? first_rhs->content->type_name : "";
if (!UNIQSTR_EQ (lhs_type, rhs_type)) if (!UNIQSTR_EQ (lhs_type, rhs_type))
complain (&r->location, Wother, complain (&r->location, Wother,
_("type clash on default action: <%s> != <%s>"), _("type clash on default action: <%s> != <%s>"),
@@ -321,7 +321,7 @@ grammar_rule_check (const symbol_list *r)
bool midrule_warning = false; bool midrule_warning = false;
if (!l->action_props.is_value_used if (!l->action_props.is_value_used
&& symbol_should_be_used (l, &midrule_warning) && 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))) && (r->action_props.code || (n != 0 && n != 1)))
{ {
warnings warn_flag = midrule_warning ? Wmidrule_values : Wother; warnings warn_flag = midrule_warning ? Wmidrule_values : Wother;
@@ -333,12 +333,25 @@ grammar_rule_check (const symbol_list *r)
} }
} }
/* 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 /* See comments in grammar_current_rule_prec_set for how POSIX
mandates this complaint. It's only for identifiers, so skip mandates this complaint. It's only for identifiers, so skip
it for char literals and strings, which are always tokens. */ it for char literals and strings, which are always tokens. */
if (r->ruleprec if (r->ruleprec
&& r->ruleprec->tag[0] != '\'' && r->ruleprec->tag[0] != '"' && r->ruleprec->tag[0] != '\'' && r->ruleprec->tag[0] != '"'
&& r->ruleprec->status != declared && !r->ruleprec->prec) && r->ruleprec->content->status != declared
&& !r->ruleprec->content->prec)
complain (&r->location, Wother, complain (&r->location, Wother,
_("token for %%prec is not defined: %s"), r->ruleprec->tag); _("token for %%prec is not defined: %s"), r->ruleprec->tag);
} }
@@ -430,8 +443,26 @@ grammar_current_rule_prec_set (symbol *precsym, location loc)
token. */ token. */
symbol_class_set (precsym, token_sym, loc, false); symbol_class_set (precsym, token_sym, loc, false);
if (current_rule->ruleprec) if (current_rule->ruleprec)
complain (&loc, complaint, _("only one %s allowed per rule"), "%prec"); duplicate_directive ("%prec",
current_rule->ruleprec = precsym; 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. */ /* Attach dynamic precedence DPREC to the current rule. */
@@ -446,8 +477,13 @@ grammar_current_rule_dprec_set (int dprec, location loc)
complain (&loc, complaint, _("%s must be followed by positive number"), complain (&loc, complaint, _("%s must be followed by positive number"),
"%dprec"); "%dprec");
else if (current_rule->dprec != 0) else if (current_rule->dprec != 0)
complain (&loc, complaint, _("only one %s allowed per rule"), "%dprec"); duplicate_directive ("%dprec",
current_rule->dprec = 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 /* Attach a merge function NAME with argument type TYPE to current
@@ -460,9 +496,13 @@ grammar_current_rule_merge_set (uniqstr name, location loc)
complain (&loc, Wother, _("%s affects only GLR parsers"), complain (&loc, Wother, _("%s affects only GLR parsers"),
"%merge"); "%merge");
if (current_rule->merger != 0) if (current_rule->merger != 0)
complain (&loc, complaint, _("only one %s allowed per rule"), "%merge"); duplicate_directive ("%merge",
current_rule->merger = get_merge_function (name); current_rule->merger_declaration_location, loc);
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 /* Attach SYM to the current rule. If needed, move the previous
@@ -477,9 +517,9 @@ grammar_current_rule_symbol_append (symbol *sym, location loc,
grammar_midrule_action (); grammar_midrule_action ();
p = grammar_symbol_append (sym, loc); p = grammar_symbol_append (sym, loc);
if (name) if (name)
assign_named_ref(p, name); assign_named_ref (p, name);
if (sym->status == undeclared || sym->status == used) if (sym->content->status == undeclared || sym->content->status == used)
sym->status = needed; sym->content->status = needed;
} }
/* Attach an ACTION to the current rule. */ /* Attach an ACTION to the current rule. */
@@ -507,7 +547,7 @@ packgram (void)
{ {
unsigned int itemno = 0; unsigned int itemno = 0;
rule_number ruleno = 0; rule_number ruleno = 0;
symbol_list *p = grammar; symbol_list *p;
ritem = xnmalloc (nritems + 1, sizeof *ritem); ritem = xnmalloc (nritems + 1, sizeof *ritem);
@@ -516,15 +556,14 @@ packgram (void)
rules = xnmalloc (nrules, sizeof *rules); rules = xnmalloc (nrules, sizeof *rules);
while (p) for (p = grammar; p; p = p->next)
{ {
int rule_length = 0;
symbol *ruleprec = p->ruleprec; symbol *ruleprec = p->ruleprec;
record_merge_function_type (p->merger, p->content.sym->type_name, record_merge_function_type (p->merger, p->content.sym->content->type_name,
p->merger_declaration_location); p->merger_declaration_location);
rules[ruleno].user_number = ruleno; rules[ruleno].user_number = ruleno;
rules[ruleno].number = ruleno; rules[ruleno].number = ruleno;
rules[ruleno].lhs = p->content.sym; rules[ruleno].lhs = p->content.sym->content;
rules[ruleno].rhs = ritem + itemno; rules[ruleno].rhs = ritem + itemno;
rules[ruleno].prec = NULL; rules[ruleno].prec = NULL;
rules[ruleno].dprec = p->dprec; rules[ruleno].dprec = p->dprec;
@@ -536,14 +575,14 @@ packgram (void)
rules[ruleno].action_location = p->action_props.location; rules[ruleno].action_location = p->action_props.location;
rules[ruleno].is_predicate = p->action_props.is_predicate; rules[ruleno].is_predicate = p->action_props.is_predicate;
/* If the midrule's $$ is set or its $n is used, remove the `$' from the /* 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 symbol name so that it's a user-defined symbol so that the default
%destructor and %printer apply. */ %destructor and %printer apply. */
if (p->midrule_parent_rule if (p->midrule_parent_rule
&& (p->action_props.is_value_used && (p->action_props.is_value_used
|| symbol_list_n_get (p->midrule_parent_rule, || (symbol_list_n_get (p->midrule_parent_rule,
p->midrule_parent_rhs_index) p->midrule_parent_rhs_index)
->action_props.is_value_used)) ->action_props.is_value_used)))
p->content.sym->tag += 1; p->content.sym->tag += 1;
/* Don't check the generated rule 0. It has no action, so some rhs /* Don't check the generated rule 0. It has no action, so some rhs
@@ -552,40 +591,40 @@ packgram (void)
if (p != grammar) if (p != grammar)
grammar_rule_check (p); grammar_rule_check (p);
for (p = p->next; p && p->content.sym; p = p->next) {
{ size_t rule_length = 0;
++rule_length; for (p = p->next; p->content.sym; p = p->next)
{
++rule_length;
/* Don't allow rule_length == INT_MAX, since that might /* Don't allow rule_length == INT_MAX, since that might
cause confusion with strtol if INT_MAX == LONG_MAX. */ cause confusion with strtol if INT_MAX == LONG_MAX. */
if (rule_length == INT_MAX) if (rule_length == INT_MAX)
complain (&rules[ruleno].location, fatal, _("rule is too long")); complain (&rules[ruleno].location, fatal, _("rule is too long"));
/* item_number = symbol_number. /* item_number = symbol_number.
But the former needs to contain more: negative rule numbers. */ But the former needs to contain more: negative rule numbers. */
ritem[itemno++] = ritem[itemno++] =
symbol_number_as_item_number (p->content.sym->number); symbol_number_as_item_number (p->content.sym->content->number);
/* A rule gets by default the precedence and associativity /* A rule gets by default the precedence and associativity
of its last token. */ of its last token. */
if (p->content.sym->class == token_sym && default_prec) if (p->content.sym->content->class == token_sym && default_prec)
rules[ruleno].prec = p->content.sym; rules[ruleno].prec = p->content.sym->content;
} }
}
/* If this rule has a %prec, /* If this rule has a %prec,
the specified symbol's precedence replaces the default. */ the specified symbol's precedence replaces the default. */
if (ruleprec) if (ruleprec)
{ {
rules[ruleno].precsym = ruleprec; rules[ruleno].precsym = ruleprec->content;
rules[ruleno].prec = ruleprec; rules[ruleno].prec = ruleprec->content;
} }
/* An item ends by the rule number (negated). */ /* An item ends by the rule number (negated). */
ritem[itemno++] = rule_number_as_item_number (ruleno); ritem[itemno++] = rule_number_as_item_number (ruleno);
aver (itemno < ITEM_NUMBER_MAX); aver (itemno < ITEM_NUMBER_MAX);
++ruleno; ++ruleno;
aver (ruleno < RULE_NUMBER_MAX); aver (ruleno < RULE_NUMBER_MAX);
if (p)
p = p->next;
} }
aver (itemno == nritems); aver (itemno == nritems);
@@ -609,19 +648,19 @@ reader (void)
/* Construct the accept symbol. */ /* Construct the accept symbol. */
accept = symbol_get ("$accept", empty_location); accept = symbol_get ("$accept", empty_location);
accept->class = nterm_sym; accept->content->class = nterm_sym;
accept->number = nvars++; accept->content->number = nvars++;
/* Construct the error token */ /* Construct the error token */
errtoken = symbol_get ("error", empty_location); errtoken = symbol_get ("error", empty_location);
errtoken->class = token_sym; errtoken->content->class = token_sym;
errtoken->number = ntokens++; errtoken->content->number = ntokens++;
/* Construct a token that represents all undefined literal tokens. /* Construct a token that represents all undefined literal tokens.
It is always token number 2. */ It is always token number 2. */
undeftoken = symbol_get ("$undefined", empty_location); undeftoken = symbol_get ("$undefined", empty_location);
undeftoken->class = token_sym; undeftoken->content->class = token_sym;
undeftoken->number = ntokens++; undeftoken->content->number = ntokens++;
gram_in = xfopen (grammar_file, "r"); gram_in = xfopen (grammar_file, "r");
@@ -683,10 +722,10 @@ check_and_convert_grammar (void)
if (!endtoken) if (!endtoken)
{ {
endtoken = symbol_get ("$end", empty_location); endtoken = symbol_get ("$end", empty_location);
endtoken->class = token_sym; endtoken->content->class = token_sym;
endtoken->number = 0; endtoken->content->number = 0;
/* Value specified by POSIX. */ /* Value specified by POSIX. */
endtoken->user_token_number = 0; endtoken->content->user_token_number = 0;
} }
/* Report any undefined symbols and consider them nonterminals. */ /* Report any undefined symbols and consider them nonterminals. */
@@ -713,7 +752,7 @@ check_and_convert_grammar (void)
/* Insert the initial rule, whose line is that of the first rule /* Insert the initial rule, whose line is that of the first rule
(not that of the start symbol): (not that of the start symbol):
accept: %start EOF. */ $accept: %start $end. */
{ {
symbol_list *p = symbol_list_sym_new (accept, empty_location); symbol_list *p = symbol_list_sym_new (accept, empty_location);
p->location = grammar->location; p->location = grammar->location;
@@ -726,7 +765,8 @@ check_and_convert_grammar (void)
grammar = p; 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 /* Assign the symbols their symbol numbers. Write #defines for the
token symbols into FDEFINES if requested. */ token symbols into FDEFINES if requested. */
@@ -737,11 +777,11 @@ check_and_convert_grammar (void)
action type checking. action type checking.
Before invoking grammar_rule_check (in packgram below) on any rule, make 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 Otherwise, checking that a midrule's $$ should be set will not always work
properly because the check must forward-reference the midrule's parent properly because the check must forward-reference the midrule's parent
rule. For the same reason, all the `used' flags must be set before rule. For the same reason, all the 'used' flags must be set before
checking whether to remove `$' from any midrule symbol name (also in checking whether to remove '$' from any midrule symbol name (also in
packgram). */ packgram). */
{ {
symbol_list *sym; symbol_list *sym;
+2
View File
@@ -47,6 +47,8 @@ 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_current_rule_end (location loc);
void grammar_midrule_action (void); 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_prec_set (symbol *precsym, location loc);
void grammar_current_rule_dprec_set (int dprec, 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_merge_set (uniqstr name, location loc);
+10 -10
View File
@@ -49,7 +49,7 @@ static bitset P;
static bitset V; static bitset V;
/* Set of symbols used to define rule precedence (so they are /* 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 bitset V1;
static rule_number nuseful_productions; static rule_number nuseful_productions;
@@ -163,9 +163,9 @@ inaccessable_symbols (void)
Pp = bitset_create (nrules, BITSET_FIXED); Pp = bitset_create (nrules, BITSET_FIXED);
/* If the start symbol isn't useful, then nothing will be useful. */ /* If the start symbol isn't useful, then nothing will be useful. */
if (bitset_test (N, accept->number - ntokens)) if (bitset_test (N, accept->content->number - ntokens))
{ {
bitset_set (V, accept->number); bitset_set (V, accept->content->number);
while (1) while (1)
{ {
@@ -196,9 +196,9 @@ inaccessable_symbols (void)
V = Vp; V = Vp;
/* Tokens 0, 1, and 2 are internal to Bison. Consider them useful. */ /* Tokens 0, 1, and 2 are internal to Bison. Consider them useful. */
bitset_set (V, endtoken->number); /* end-of-input token */ bitset_set (V, endtoken->content->number); /* end-of-input token */
bitset_set (V, errtoken->number); /* error token */ bitset_set (V, errtoken->content->number); /* error token */
bitset_set (V, undeftoken->number); /* some undefined token */ bitset_set (V, undeftoken->content->number); /* some undefined token */
bitset_free (P); bitset_free (P);
P = Pp; P = Pp;
@@ -298,7 +298,7 @@ nonterminals_reduce (void)
if (!bitset_test (V, i)) if (!bitset_test (V, i))
{ {
nontermmap[i - ntokens] = n++; nontermmap[i - ntokens] = n++;
if (symbols[i]->status != used) if (symbols[i]->content->status != used)
complain (&symbols[i]->location, Wother, complain (&symbols[i]->location, Wother,
_("nonterminal useless in grammar: %s"), _("nonterminal useless in grammar: %s"),
symbols[i]->tag); symbols[i]->tag);
@@ -310,7 +310,7 @@ nonterminals_reduce (void)
symbol **symbols_sorted = xnmalloc (nvars, sizeof *symbols_sorted); symbol **symbols_sorted = xnmalloc (nvars, sizeof *symbols_sorted);
for (i = ntokens; i < nsyms; i++) for (i = ntokens; i < nsyms; i++)
symbols[i]->number = nontermmap[i - ntokens]; symbols[i]->content->number = nontermmap[i - ntokens];
for (i = ntokens; i < nsyms; i++) for (i = ntokens; i < nsyms; i++)
symbols_sorted[nontermmap[i - ntokens] - ntokens] = symbols[i]; symbols_sorted[nontermmap[i - ntokens] - ntokens] = symbols[i];
for (i = ntokens; i < nsyms; i++) for (i = ntokens; i < nsyms; i++)
@@ -328,7 +328,7 @@ nonterminals_reduce (void)
*rhsp = symbol_number_as_item_number (nontermmap[*rhsp *rhsp = symbol_number_as_item_number (nontermmap[*rhsp
- ntokens]); - ntokens]);
} }
accept->number = nontermmap[accept->number - ntokens]; accept->content->number = nontermmap[accept->content->number - ntokens];
} }
nsyms -= nuseless_nonterminals; nsyms -= nuseless_nonterminals;
@@ -415,7 +415,7 @@ reduce_grammar (void)
reduce_print (); reduce_print ();
if (!bitset_test (N, accept->number - ntokens)) if (!bitset_test (N, accept->content->number - ntokens))
complain (&startsymbol_location, fatal, complain (&startsymbol_location, fatal,
_("start symbol %s does not derive any sentence"), _("start symbol %s does not derive any sentence"),
startsymbol->tag); startsymbol->tag);
+21 -92
View File
@@ -78,8 +78,9 @@ static bool untyped_var_seen;
/* POSIX says that a tag must be both an id and a C union member, but /* 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 historically almost any character is allowed in a tag. We disallow
NUL and newline, as this simplifies our implementation. */ NUL and newline, as this simplifies our implementation. We allow
tag [^\0\n>]+ "->" as a means to dereference a pointer. */
tag ([^\0\n>]|->)+
/* Zero or more instances of backslash-newline. Following GCC, allow /* Zero or more instances of backslash-newline. Following GCC, allow
white space between the backslash and the newline. */ white space between the backslash and the newline. */
@@ -95,26 +96,6 @@ 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 /* This scanner is special: it is invoked only once, henceforth
is expected to return only once. This initialization is is expected to return only once. This initialization is
therefore done once per action to translate. */ therefore done once per action to translate. */
@@ -167,32 +148,14 @@ ref -?[0-9]+|{id}|"["{id}"]"|"$"
<SC_RULE_ACTION,SC_SYMBOL_ACTION> <SC_RULE_ACTION,SC_SYMBOL_ACTION>
{ {
"'" { "'" STRING_GROW; BEGIN SC_CHARACTER;
STRING_GROW; "\"" STRING_GROW; BEGIN SC_STRING;
BEGIN SC_CHARACTER; "/"{splice}"*" STRING_GROW; BEGIN SC_COMMENT;
need_semicolon = true; "/"{splice}"/" STRING_GROW; BEGIN SC_LINE_COMMENT;
}
"\"" {
STRING_GROW;
BEGIN SC_STRING;
need_semicolon = true;
}
"/"{splice}"*" {
STRING_GROW;
BEGIN SC_COMMENT;
}
"/"{splice}"/" {
STRING_GROW;
BEGIN SC_LINE_COMMENT;
}
[$@] { [$@] {
complain (loc, Wother, _("stray '%s'"), yytext); complain (loc, Wother, _("stray '%s'"), yytext);
obstack_escape (&obstack_for_string, yytext); obstack_escape (&obstack_for_string, yytext);
need_semicolon = true;
}
[\[\]] {
obstack_escape (&obstack_for_string, yytext);
need_semicolon = true;
} }
} }
@@ -203,51 +166,13 @@ ref -?[0-9]+|{id}|"["{id}"]"|"$"
handle_action_dollar (self->rule, yytext, *loc); handle_action_dollar (self->rule, yytext, *loc);
if (ref_tail_fields) if (ref_tail_fields)
obstack_sgrow (&obstack_for_string, ref_tail_fields); obstack_sgrow (&obstack_for_string, ref_tail_fields);
need_semicolon = true;
} }
"@"{ref} { "@"{ref} {
ref_tail_fields = NULL; ref_tail_fields = NULL;
handle_action_at (self->rule, yytext, *loc); handle_action_at (self->rule, yytext, *loc);
if (ref_tail_fields) if (ref_tail_fields)
obstack_sgrow (&obstack_for_string, 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;
complain_indent (loc, Wdeprecated, &indent,
_("a ';' might be needed at the end of action code"));
indent += SUB_INDENT;
complain_indent (loc, Wdeprecated | silent | no_caret, &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;
. STRING_GROW; need_semicolon = true;
} }
<SC_SYMBOL_ACTION> <SC_SYMBOL_ACTION>
@@ -410,7 +335,7 @@ show_sub_message (warnings warning,
const char *at_spec = get_at_spec (var->symbol_index); const char *at_spec = get_at_spec (var->symbol_index);
if (var->err == 0) if (var->err == 0)
complain_indent (&var->loc, warning, &indent, start_complain_indent (&var->loc, warning, &indent,
_("refers to: %c%s at %s"), dollar_or_at, _("refers to: %c%s at %s"), dollar_or_at,
var->id, at_spec); var->id, at_spec);
else else
@@ -447,7 +372,7 @@ show_sub_message (warnings warning,
_(", cannot be accessed from mid-rule action at $%d"), _(", cannot be accessed from mid-rule action at $%d"),
midrule_rhs_index); midrule_rhs_index);
complain_indent (&id_loc, warning, &indent, "%s", start_complain_indent (&id_loc, warning, &indent, "%s",
obstack_finish0 (&msg_buf)); obstack_finish0 (&msg_buf));
obstack_free (&msg_buf, 0); obstack_free (&msg_buf, 0);
} }
@@ -590,7 +515,7 @@ parse_ref (char *cp, symbol_list *rule, int rule_length,
cp_end - cp : ref_tail_fields - cp; cp_end - cp : ref_tail_fields - cp;
unsigned indent = 0; unsigned indent = 0;
complain_indent (&text_loc, complaint, &indent, start_complain_indent (&text_loc, complaint, &indent,
_("invalid reference: %s"), quote (text)); _("invalid reference: %s"), quote (text));
indent += SUB_INDENT; indent += SUB_INDENT;
if (len == 0) if (len == 0)
@@ -598,18 +523,18 @@ parse_ref (char *cp, symbol_list *rule, int rule_length,
location sym_loc = text_loc; location sym_loc = text_loc;
sym_loc.start.column += 1; sym_loc.start.column += 1;
sym_loc.end = sym_loc.start; sym_loc.end = sym_loc.start;
complain_indent (&sym_loc, complaint, &indent, start_complain_indent (&sym_loc, complaint, &indent,
_("syntax error after '%c', expecting integer, " _("syntax error after '%c', expecting integer, "
"letter, '_', '[', or '$'"), "letter, '_', '[', or '$'"),
dollar_or_at); dollar_or_at);
} }
else if (midrule_rhs_index) else if (midrule_rhs_index)
complain_indent (&rule->location, complaint, &indent, start_complain_indent (&rule->location, complaint, &indent,
_("symbol not found in production before $%d: " _("symbol not found in production before $%d: "
"%.*s"), "%.*s"),
midrule_rhs_index, len, cp); midrule_rhs_index, len, cp);
else else
complain_indent (&rule->location, complaint, &indent, start_complain_indent (&rule->location, complaint, &indent,
_("symbol not found in production: %.*s"), _("symbol not found in production: %.*s"),
len, cp); len, cp);
@@ -617,6 +542,7 @@ parse_ref (char *cp, symbol_list *rule, int rule_length,
show_sub_messages (complaint, show_sub_messages (complaint,
cp, explicit_bracketing, midrule_rhs_index, cp, explicit_bracketing, midrule_rhs_index,
dollar_or_at, indent); dollar_or_at, indent);
finish_complaint ();
return INVALID_REF; return INVALID_REF;
} }
case 1: case 1:
@@ -624,11 +550,12 @@ parse_ref (char *cp, symbol_list *rule, int rule_length,
unsigned indent = 0; unsigned indent = 0;
if (variant_count > 1) if (variant_count > 1)
{ {
complain_indent (&text_loc, Wother, &indent, start_complain_indent (&text_loc, Wother, &indent,
_("misleading reference: %s"), quote (text)); _("misleading reference: %s"), quote (text));
show_sub_messages (Wother, show_sub_messages (Wother,
cp, explicit_bracketing, midrule_rhs_index, cp, explicit_bracketing, midrule_rhs_index,
dollar_or_at, indent + SUB_INDENT); dollar_or_at, indent + SUB_INDENT);
finish_complaint ();
} }
{ {
unsigned symbol_index = unsigned symbol_index =
@@ -640,11 +567,12 @@ parse_ref (char *cp, symbol_list *rule, int rule_length,
default: default:
{ {
unsigned indent = 0; unsigned indent = 0;
complain_indent (&text_loc, complaint, &indent, start_complain_indent (&text_loc, complaint, &indent,
_("ambiguous reference: %s"), quote (text)); _("ambiguous reference: %s"), quote (text));
show_sub_messages (complaint, show_sub_messages (complaint,
cp, explicit_bracketing, midrule_rhs_index, cp, explicit_bracketing, midrule_rhs_index,
dollar_or_at, indent + SUB_INDENT); dollar_or_at, indent + SUB_INDENT);
finish_complaint ();
return INVALID_REF; return INVALID_REF;
} }
} }
@@ -671,7 +599,8 @@ fetch_type_name (char *cp, char const **type_name,
if (*cp == '<') if (*cp == '<')
{ {
*type_name = ++cp; *type_name = ++cp;
while (*cp != '>') /* Series of non-'>' or "->". */
while (*cp != '>' || cp[-1] == '-')
++cp; ++cp;
/* The '>' symbol will be later replaced by '\0'. Original /* The '>' symbol will be later replaced by '\0'. Original
+16 -23
View File
@@ -112,7 +112,12 @@ static void unexpected_newline (boundary, char const *);
/* A identifier was just read in directives/rules. Special state /* A identifier was just read in directives/rules. Special state
to capture the sequence 'identifier :'. */ to capture the sequence 'identifier :'. */
%x SC_AFTER_IDENTIFIER %x SC_AFTER_IDENTIFIER
/* A complex tag, with nested angles brackets. */
/* 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 %x SC_TAG
/* Four types of user code: /* Four types of user code:
@@ -133,13 +138,6 @@ notletter [^.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_]{-}[%\{]
id {letter}({letter}|[-0-9])* id {letter}({letter}|[-0-9])*
int [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, as this simplifies our implementation. We disallow angle
bracket to match them in nested pairs: several languages use them
for generics/template types. */
tag [^\0<>]+
/* Zero or more instances of backslash-newline. Following GCC, allow /* Zero or more instances of backslash-newline. Following GCC, allow
white space between the backslash and the newline. */ white space between the backslash and the newline. */
splice (\\[ \f\t\v]*\n)* splice (\\[ \f\t\v]*\n)*
@@ -217,6 +215,7 @@ eqopt ([[:space:]]*=)?
"%defines" return PERCENT_DEFINES; "%defines" return PERCENT_DEFINES;
"%destructor" return PERCENT_DESTRUCTOR; "%destructor" return PERCENT_DESTRUCTOR;
"%dprec" return PERCENT_DPREC; "%dprec" return PERCENT_DPREC;
"%empty" return PERCENT_EMPTY;
"%error-verbose" return PERCENT_ERROR_VERBOSE; "%error-verbose" return PERCENT_ERROR_VERBOSE;
"%expect" return PERCENT_EXPECT; "%expect" return PERCENT_EXPECT;
"%expect-rr" return PERCENT_EXPECT_RR; "%expect-rr" return PERCENT_EXPECT_RR;
@@ -324,13 +323,6 @@ eqopt ([[:space:]]*=)?
/* A type. */ /* A type. */
"<*>" return TAG_ANY; "<*>" return TAG_ANY;
"<>" return TAG_NONE; "<>" return TAG_NONE;
"<"{tag}">" {
obstack_grow (&obstack_for_string, yytext + 1, yyleng - 2);
STRING_FINISH;
val->uniqstr = uniqstr_new (last_string);
STRING_FREE;
return TAG;
}
"<" { "<" {
nesting = 0; nesting = 0;
token_start = loc->start; token_start = loc->start;
@@ -520,7 +512,7 @@ eqopt ([[:space:]]*=)?
"\"" { "\"" {
STRING_FINISH; STRING_FINISH;
loc->start = token_start; loc->start = token_start;
val->chars = last_string; val->code = last_string;
BEGIN INITIAL; BEGIN INITIAL;
return STRING; return STRING;
} }
@@ -558,10 +550,11 @@ eqopt ([[:space:]]*=)?
<<EOF>> unexpected_eof (token_start, "'"); <<EOF>> unexpected_eof (token_start, "'");
} }
/*-----------------------------------------------------------.
| Scanning a Bison nested tag. The initial angle bracket is |
| already eaten. | /*--------------------------------------------------------------.
`-----------------------------------------------------------*/ | Scanning a tag. The initial angle bracket is already eaten. |
`--------------------------------------------------------------*/
<SC_TAG> <SC_TAG>
{ {
@@ -579,7 +572,7 @@ eqopt ([[:space:]]*=)?
STRING_GROW; STRING_GROW;
} }
[^<>]+ STRING_GROW; ([^<>]|->)+ STRING_GROW;
"<"+ STRING_GROW; nesting += yyleng; "<"+ STRING_GROW; nesting += yyleng;
<<EOF>> unexpected_eof (token_start, ">"); <<EOF>> unexpected_eof (token_start, ">");
@@ -758,7 +751,7 @@ eqopt ([[:space:]]*=)?
"%}" { "%}" {
STRING_FINISH; STRING_FINISH;
loc->start = code_start; loc->start = code_start;
val->chars = last_string; val->code = last_string;
BEGIN INITIAL; BEGIN INITIAL;
return PROLOGUE; return PROLOGUE;
} }
@@ -777,7 +770,7 @@ eqopt ([[:space:]]*=)?
<<EOF>> { <<EOF>> {
STRING_FINISH; STRING_FINISH;
loc->start = code_start; loc->start = code_start;
val->chars = last_string; val->code = last_string;
BEGIN INITIAL; BEGIN INITIAL;
return EPILOGUE; return EPILOGUE;
} }
+5 -3
View File
@@ -72,7 +72,7 @@ static void fail_for_invalid_at (char const *at);
"@@" fputc ('@', yyout); "@@" fputc ('@', yyout);
"@{" fputc ('[', yyout); "@{" 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; @\n continue;
"@oline@" fprintf (yyout, "%d", out_lineno + 1); "@oline@" fprintf (yyout, "%d", out_lineno + 1);
@@ -83,7 +83,7 @@ static void fail_for_invalid_at (char const *at);
"@output(" at_init (&argc, argv, &at_ptr, &at_output); "@output(" at_init (&argc, argv, &at_ptr, &at_output);
/* This pattern must not match more than the previous @ patterns. */ /* This pattern must not match more than the previous @ patterns. */
@[^@{}`(\n]* fail_for_invalid_at (yytext); @[^@{}\'(\n]* fail_for_invalid_at (yytext);
\n out_lineno++; ECHO; \n out_lineno++; ECHO;
[^@\n]+ ECHO; [^@\n]+ ECHO;
@@ -103,7 +103,7 @@ static void fail_for_invalid_at (char const *at);
"@@" obstack_1grow (&obstack_for_string, '@'); "@@" obstack_1grow (&obstack_for_string, '@');
"@{" obstack_1grow (&obstack_for_string, '['); "@{" 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; @\n continue;
@[,)] { @[,)] {
@@ -183,6 +183,8 @@ flag (const char *arg)
/* compare with values issued from b4_error */ /* compare with values issued from b4_error */
if (STREQ (arg, "complain")) if (STREQ (arg, "complain"))
return complaint; return complaint;
else if (STREQ (arg, "deprecated"))
return Wdeprecated;
else if (STREQ (arg, "fatal")) else if (STREQ (arg, "fatal"))
return fatal; return fatal;
else if (STREQ (arg, "note")) else if (STREQ (arg, "note"))
+1 -1
View File
@@ -135,7 +135,7 @@ typedef struct
/* Is the TRANSITIONS->states[Num] labelled by the error token? */ /* 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) (TRANSITION_SYMBOL (Transitions, Num) == errtoken->content->number)
/* When resolving a SR conflicts, if the reduction wins, the shift is /* When resolving a SR conflicts, if the reduction wins, the shift is
disabled. */ disabled. */
+17 -10
View File
@@ -36,18 +36,20 @@ symbol_list_sym_new (symbol *sym, location loc)
res->content_type = SYMLIST_SYMBOL; res->content_type = SYMLIST_SYMBOL;
res->content.sym = sym; res->content.sym = sym;
res->location = res->sym_loc = loc; res->location = res->sym_loc = loc;
res->named_ref = NULL;
res->midrule = NULL; res->midrule = NULL;
res->midrule_parent_rule = NULL; res->midrule_parent_rule = NULL;
res->midrule_parent_rhs_index = 0; res->midrule_parent_rhs_index = 0;
code_props_none_init (&res->action_props); /* Members used for LHS only. */
res->ruleprec = NULL; res->ruleprec = NULL;
res->percent_empty_loc = empty_location;
code_props_none_init (&res->action_props);
res->dprec = 0; res->dprec = 0;
res->dprec_location = empty_location;
res->merger = 0; res->merger = 0;
res->merger_declaration_location = empty_location;
res->named_ref = NULL;
res->next = NULL; res->next = NULL;
@@ -85,12 +87,17 @@ symbol_list_type_new (uniqstr type_name, location loc)
void void
symbol_list_syms_print (const symbol_list *l, FILE *f) symbol_list_syms_print (const symbol_list *l, FILE *f)
{ {
char const *sep = "";
for (/* Nothing. */; l && l->content.sym; l = l->next) 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); symbol_print (l->content.sym, f);
fprintf (stderr, l->action_props.is_value_used ? " used" : " unused"); fputs (l->action_props.is_value_used ? " used" : " unused", f);
if (l && l->content.sym) sep = ", ";
fprintf (f, ", ");
} }
} }
@@ -198,7 +205,7 @@ symbol_list_n_type_name_get (symbol_list *l, location loc, int n)
return NULL; return NULL;
} }
aver (l->content_type == SYMLIST_SYMBOL); aver (l->content_type == SYMLIST_SYMBOL);
return l->content.sym->type_name; return l->content.sym->content->type_name;
} }
bool bool
@@ -216,8 +223,8 @@ symbol_list_code_props_set (symbol_list *node, code_props_type kind,
{ {
case SYMLIST_SYMBOL: case SYMLIST_SYMBOL:
symbol_code_props_set (node->content.sym, kind, cprops); symbol_code_props_set (node->content.sym, kind, cprops);
if (node->content.sym->status == undeclared) if (node->content.sym->content->status == undeclared)
node->content.sym->status = used; node->content.sym->content->status = used;
break; break;
case SYMLIST_TYPE: case SYMLIST_TYPE:
semantic_type_code_props_set semantic_type_code_props_set
+15 -5
View File
@@ -50,6 +50,9 @@ typedef struct symbol_list
} content; } content;
location location; location location;
/* Named reference. */
named_ref *named_ref;
/* Proper location of the symbol, not all the rule */ /* Proper location of the symbol, not all the rule */
location sym_loc; location sym_loc;
@@ -64,19 +67,26 @@ typedef struct symbol_list
struct symbol_list *midrule_parent_rule; struct symbol_list *midrule_parent_rule;
int midrule_parent_rhs_index; 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 /* The action is attached to the LHS of a rule, but action properties for
* each RHS are also stored here. */ * each RHS are also stored here. */
code_props action_props; code_props action_props;
/* Precedence/associativity. */ /* The location of the first %empty for this rule, or \a
symbol *ruleprec; empty_location. */
location percent_empty_loc;
int dprec; int dprec;
location dprec_location;
int merger; int merger;
location merger_declaration_location; location merger_declaration_location;
/* Named reference. */
named_ref *named_ref;
/* The list. */ /* The list. */
struct symbol_list *next; struct symbol_list *next;
} symbol_list; } symbol_list;
+203 -186
View File
@@ -58,6 +58,35 @@ static symgraph **prec_nodes;
bool *used_assoc = NULL; bool *used_assoc = NULL;
/*--------------------------.
| Create a new sym_content. |
`--------------------------*/
static sym_content *
sym_content_new (symbol *s)
{
sym_content *res = xmalloc (sizeof *res);
res->symbol = s;
res->type_name = NULL;
{
int i;
for (i = 0; i < CODE_PROPS_SIZE; ++i)
code_props_none_init (&res->props[i]);
}
res->number = NUMBER_UNDEFINED;
res->prec = 0;
res->assoc = undef_assoc;
res->user_token_number = USER_NUMBER_UNDEFINED;
res->class = unknown_sym;
res->status = undeclared;
return res;
}
/*---------------------------------. /*---------------------------------.
| Create a new symbol, named TAG. | | Create a new symbol, named TAG. |
`---------------------------------*/ `---------------------------------*/
@@ -76,22 +105,9 @@ symbol_new (uniqstr tag, location loc)
res->tag = tag; res->tag = tag;
res->location = loc; res->location = loc;
res->type_name = NULL;
{
int i;
for (i = 0; i < CODE_PROPS_SIZE; ++i)
code_props_none_init (&res->props[i]);
}
res->number = NUMBER_UNDEFINED;
res->prec = 0;
res->assoc = undef_assoc;
res->user_token_number = USER_NUMBER_UNDEFINED;
res->alias = NULL; res->alias = NULL;
res->class = unknown_sym; res->content = sym_content_new (res);
res->status = undeclared; res->is_alias = false;
if (nsyms == SYMBOL_NUMBER_MAXIMUM) if (nsyms == SYMBOL_NUMBER_MAXIMUM)
complain (NULL, fatal, _("too many symbols in input grammar (limit is %d)"), complain (NULL, fatal, _("too many symbols in input grammar (limit is %d)"),
@@ -100,6 +116,30 @@ symbol_new (uniqstr tag, location loc)
return res; return res;
} }
/*--------------------.
| Free a sym_content. |
`--------------------*/
static void
sym_content_free (sym_content *sym)
{
free (sym);
}
/*---------------------------------------------------------.
| Free a symbol and its associated content if appropriate. |
`---------------------------------------------------------*/
static void
symbol_free (void *ptr)
{
symbol *sym = (symbol *)ptr;
if (!sym->is_alias)
sym_content_free (sym->content);
free (sym);
}
char const * char const *
code_props_type_string (code_props_type kind) code_props_type_string (code_props_type kind)
{ {
@@ -141,25 +181,25 @@ semantic_type_new (uniqstr tag, const location *loc)
`-----------------*/ `-----------------*/
#define SYMBOL_ATTR_PRINT(Attr) \ #define SYMBOL_ATTR_PRINT(Attr) \
if (s->Attr) \ if (s->content->Attr) \
fprintf (f, " %s { %s }", #Attr, s->Attr) fprintf (f, " %s { %s }", #Attr, s->content->Attr)
#define SYMBOL_CODE_PRINT(Attr) \ #define SYMBOL_CODE_PRINT(Attr) \
if (s->props[Attr].code) \ if (s->content->props[Attr].code) \
fprintf (f, " %s { %s }", #Attr, s->props[Attr].code) fprintf (f, " %s { %s }", #Attr, s->content->props[Attr].code)
void void
symbol_print (symbol const *s, FILE *f) symbol_print (symbol const *s, FILE *f)
{ {
if (s) if (s)
{ {
fprintf (f, "\"%s\"", s->tag); fputs (s->tag, f);
SYMBOL_ATTR_PRINT (type_name); SYMBOL_ATTR_PRINT (type_name);
SYMBOL_CODE_PRINT (destructor); SYMBOL_CODE_PRINT (destructor);
SYMBOL_CODE_PRINT (printer); SYMBOL_CODE_PRINT (printer);
} }
else else
fprintf (f, "<NULL>"); fputs ("<NULL>", f);
} }
#undef SYMBOL_ATTR_PRINT #undef SYMBOL_ATTR_PRINT
@@ -193,7 +233,7 @@ is_identifier (uniqstr s)
uniqstr uniqstr
symbol_id_get (symbol const *sym) symbol_id_get (symbol const *sym)
{ {
aver (sym->user_token_number != USER_NUMBER_HAS_STRING_ALIAS); aver (sym->content->user_token_number != USER_NUMBER_HAS_STRING_ALIAS);
if (sym->alias) if (sym->alias)
sym = sym->alias; sym = sym->alias;
return is_identifier (sym->tag) ? sym->tag : 0; return is_identifier (sym->tag) ? sym->tag : 0;
@@ -210,7 +250,7 @@ symbol_redeclaration (symbol *s, const char *what, location first,
location second) location second)
{ {
unsigned i = 0; unsigned i = 0;
complain_indent (&second, complaint, &i, start_complain_indent (&second, complaint, &i,
_("%s redeclaration for %s"), what, s->tag); _("%s redeclaration for %s"), what, s->tag);
i += SUB_INDENT; i += SUB_INDENT;
complain_indent (&first, complaint, &i, complain_indent (&first, complaint, &i,
@@ -222,7 +262,7 @@ semantic_type_redeclaration (semantic_type *s, const char *what, location first,
location second) location second)
{ {
unsigned i = 0; unsigned i = 0;
complain_indent (&second, complaint, &i, start_complain_indent (&second, complaint, &i,
_("%s redeclaration for <%s>"), what, s->tag); _("%s redeclaration for <%s>"), what, s->tag);
i += SUB_INDENT; i += SUB_INDENT;
complain_indent (&first, complaint, &i, complain_indent (&first, complaint, &i,
@@ -241,11 +281,14 @@ symbol_type_set (symbol *sym, uniqstr type_name, location loc)
{ {
if (type_name) if (type_name)
{ {
if (sym->type_name) if (sym->content->type_name)
symbol_redeclaration (sym, "%type", sym->type_location, loc); symbol_redeclaration (sym, "%type", sym->content->type_location, loc);
uniqstr_assert (type_name); else
sym->type_name = type_name; {
sym->type_location = loc; uniqstr_assert (type_name);
sym->content->type_name = type_name;
sym->content->type_location = loc;
}
} }
} }
@@ -257,11 +300,12 @@ void
symbol_code_props_set (symbol *sym, code_props_type kind, symbol_code_props_set (symbol *sym, code_props_type kind,
code_props const *code) code_props const *code)
{ {
if (sym->props[kind].code) if (sym->content->props[kind].code)
symbol_redeclaration (sym, code_props_type_string (kind), symbol_redeclaration (sym, code_props_type_string (kind),
sym->props[kind].location, sym->content->props[kind].location,
code->location); code->location);
sym->props[kind] = *code; else
sym->content->props[kind] = *code;
} }
/*-----------------------------------------------------. /*-----------------------------------------------------.
@@ -277,7 +321,8 @@ semantic_type_code_props_set (semantic_type *type,
semantic_type_redeclaration (type, code_props_type_string (kind), semantic_type_redeclaration (type, code_props_type_string (kind),
type->props[kind].location, type->props[kind].location,
code->location); code->location);
type->props[kind] = *code; else
type->props[kind] = *code;
} }
/*---------------------------------------------------. /*---------------------------------------------------.
@@ -288,14 +333,14 @@ code_props *
symbol_code_props_get (symbol *sym, code_props_type kind) symbol_code_props_get (symbol *sym, code_props_type kind)
{ {
/* Per-symbol code props. */ /* Per-symbol code props. */
if (sym->props[kind].code) if (sym->content->props[kind].code)
return &sym->props[kind]; return &sym->content->props[kind];
/* Per-type code props. */ /* Per-type code props. */
if (sym->type_name) if (sym->content->type_name)
{ {
code_props *code = code_props *code =
&semantic_type_get (sym->type_name, NULL)->props[kind]; &semantic_type_get (sym->content->type_name, NULL)->props[kind];
if (code->code) if (code->code)
return code; return code;
} }
@@ -303,8 +348,8 @@ symbol_code_props_get (symbol *sym, code_props_type kind)
/* Apply default code props's only to user-defined symbols. */ /* Apply default code props's only to user-defined symbols. */
if (sym->tag[0] != '$' && sym != errtoken) if (sym->tag[0] != '$' && sym != errtoken)
{ {
code_props *code = code_props *code = &semantic_type_get (sym->content->type_name ? "*" : "",
&semantic_type_get (sym->type_name ? "*" : "", NULL)->props[kind]; NULL)->props[kind];
if (code->code) if (code->code)
return code; return code;
} }
@@ -319,14 +364,18 @@ symbol_code_props_get (symbol *sym, code_props_type kind)
void void
symbol_precedence_set (symbol *sym, int prec, assoc a, location loc) symbol_precedence_set (symbol *sym, int prec, assoc a, location loc)
{ {
sym_content *s = sym->content;
if (a != undef_assoc) if (a != undef_assoc)
{ {
if (sym->prec != 0) if (s->prec)
symbol_redeclaration (sym, assoc_to_string (a), sym->prec_location, symbol_redeclaration (sym, assoc_to_string (a),
loc); s->prec_location, loc);
sym->prec = prec; else
sym->assoc = a; {
sym->prec_location = loc; s->prec = prec;
s->assoc = a;
s->prec_location = loc;
}
} }
/* Only terminals have a precedence. */ /* Only terminals have a precedence. */
@@ -342,25 +391,26 @@ void
symbol_class_set (symbol *sym, symbol_class class, location loc, bool declaring) symbol_class_set (symbol *sym, symbol_class class, location loc, bool declaring)
{ {
bool warned = false; bool warned = false;
if (sym->class != unknown_sym && sym->class != class) if (sym->content->class != unknown_sym && sym->content->class != class)
{ {
complain (&loc, complaint, _("symbol %s redefined"), sym->tag); complain (&loc, complaint, _("symbol %s redefined"), sym->tag);
/* Don't report both "redefined" and "redeclared". */ /* Don't report both "redefined" and "redeclared". */
warned = true; warned = true;
} }
if (class == nterm_sym && sym->class != nterm_sym) if (class == nterm_sym && sym->content->class != nterm_sym)
sym->number = nvars++; sym->content->number = nvars++;
else if (class == token_sym && sym->number == NUMBER_UNDEFINED) else if (class == token_sym && sym->content->number == NUMBER_UNDEFINED)
sym->number = ntokens++; sym->content->number = ntokens++;
sym->class = class; sym->content->class = class;
if (declaring) if (declaring)
{ {
if (sym->status == declared && !warned) if (sym->content->status == declared && !warned)
complain (&loc, Wother, _("symbol %s redeclared"), sym->tag); complain (&loc, Wother, _("symbol %s redeclared"), sym->tag);
sym->status = declared; else
sym->content->status = declared;
} }
} }
@@ -374,10 +424,7 @@ symbol_user_token_number_set (symbol *sym, int user_token_number, location loc)
{ {
int *user_token_numberp; int *user_token_numberp;
if (sym->user_token_number != USER_NUMBER_HAS_STRING_ALIAS) user_token_numberp = &sym->content->user_token_number;
user_token_numberp = &sym->user_token_number;
else
user_token_numberp = &sym->alias->user_token_number;
if (*user_token_numberp != USER_NUMBER_UNDEFINED if (*user_token_numberp != USER_NUMBER_UNDEFINED
&& *user_token_numberp != user_token_number) && *user_token_numberp != user_token_number)
complain (&loc, complaint, _("redefining user token number of %s"), complain (&loc, complaint, _("redefining user token number of %s"),
@@ -387,12 +434,12 @@ symbol_user_token_number_set (symbol *sym, int user_token_number, location loc)
/* User defined $end token? */ /* User defined $end token? */
if (user_token_number == 0) if (user_token_number == 0)
{ {
endtoken = sym; endtoken = sym->content->symbol;
/* It is always mapped to 0, so it was already counted in /* It is always mapped to 0, so it was already counted in
NTOKENS. */ NTOKENS. */
if (endtoken->number != NUMBER_UNDEFINED) if (endtoken->content->number != NUMBER_UNDEFINED)
--ntokens; --ntokens;
endtoken->number = 0; endtoken->content->number = 0;
} }
} }
@@ -405,16 +452,17 @@ symbol_user_token_number_set (symbol *sym, int user_token_number, location loc)
static inline bool static inline bool
symbol_check_defined (symbol *sym) symbol_check_defined (symbol *sym)
{ {
if (sym->class == unknown_sym) sym_content *s = sym->content;
if (s->class == unknown_sym)
{ {
assert (sym->status != declared); assert (s->status != declared);
complain (&sym->location, complain (&sym->location,
sym->status == needed ? complaint : Wother, s->status == needed ? complaint : Wother,
_("symbol %s is used, but is not defined as a token" _("symbol %s is used, but is not defined as a token"
" and has no rules"), " and has no rules"),
sym->tag); sym->tag);
sym->class = nterm_sym; s->class = nterm_sym;
sym->number = nvars++; s->number = nvars++;
} }
{ {
@@ -425,9 +473,9 @@ symbol_check_defined (symbol *sym)
/* Set the semantic type status associated to the current symbol to /* Set the semantic type status associated to the current symbol to
'declared' so that we could check semantic types unnecessary uses. */ 'declared' so that we could check semantic types unnecessary uses. */
if (sym->type_name) if (s->type_name)
{ {
semantic_type *sem_type = semantic_type_get (sym->type_name, NULL); semantic_type *sem_type = semantic_type_get (s->type_name, NULL);
if (sem_type) if (sem_type)
sem_type->status = declared; sem_type->status = declared;
} }
@@ -441,7 +489,7 @@ semantic_type_check_defined (semantic_type *sem_type)
/* <*> and <> do not have to be "declared". */ /* <*> and <> do not have to be "declared". */
if (sem_type->status == declared if (sem_type->status == declared
|| !*sem_type->tag || !*sem_type->tag
|| STREQ(sem_type->tag, "*")) || STREQ (sem_type->tag, "*"))
{ {
int i; int i;
for (i = 0; i < 2; ++i) for (i = 0; i < 2; ++i)
@@ -484,71 +532,16 @@ symbol_make_alias (symbol *sym, symbol *str, location loc)
_("symbol %s given more than one literal string"), sym->tag); _("symbol %s given more than one literal string"), sym->tag);
else else
{ {
str->class = token_sym; sym_content_free (str->content);
str->user_token_number = sym->user_token_number; str->content = sym->content;
sym->user_token_number = USER_NUMBER_HAS_STRING_ALIAS; str->content->symbol = str;
str->is_alias = true;
str->alias = sym; str->alias = sym;
sym->alias = str; sym->alias = str;
str->number = sym->number;
symbol_type_set (str, sym->type_name, loc);
} }
} }
/*---------------------------------------------------------.
| Check that THIS, and its alias, have same precedence and |
| associativity. |
`---------------------------------------------------------*/
static inline void
symbol_check_alias_consistency (symbol *this)
{
symbol *sym = this;
symbol *str = this->alias;
/* Check only the symbol in the symbol-string pair. */
if (!(this->alias
&& this->user_token_number == USER_NUMBER_HAS_STRING_ALIAS))
return;
if (str->type_name != sym->type_name)
{
if (str->type_name)
symbol_type_set (sym, str->type_name, str->type_location);
else
symbol_type_set (str, sym->type_name, sym->type_location);
}
{
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);
else
symbol_precedence_set (str, sym->prec, sym->assoc,
sym->prec_location);
}
}
static bool
symbol_check_alias_consistency_processor (void *this,
void *null ATTRIBUTE_UNUSED)
{
symbol_check_alias_consistency (this);
return true;
}
/*-------------------------------------------------------------------. /*-------------------------------------------------------------------.
| Assign a symbol number, and write the definition of the token name | | Assign a symbol number, and write the definition of the token name |
| into FDEFINES. Put in SYMBOLS. | | into FDEFINES. Put in SYMBOLS. |
@@ -557,13 +550,13 @@ symbol_check_alias_consistency_processor (void *this,
static inline bool static inline bool
symbol_pack (symbol *this) symbol_pack (symbol *this)
{ {
aver (this->number != NUMBER_UNDEFINED); aver (this->content->number != NUMBER_UNDEFINED);
if (this->class == nterm_sym) if (this->content->class == nterm_sym)
this->number += ntokens; this->content->number += ntokens;
else if (this->user_token_number == USER_NUMBER_HAS_STRING_ALIAS) else if (this->content->user_token_number == USER_NUMBER_HAS_STRING_ALIAS)
return true; return true;
symbols[this->number] = this; symbols[this->content->number] = this->content->symbol;
return true; return true;
} }
@@ -573,7 +566,6 @@ symbol_pack_processor (void *this, void *null ATTRIBUTE_UNUSED)
return symbol_pack (this); return symbol_pack (this);
} }
static void static void
user_token_number_redeclaration (int num, symbol *first, symbol *second) user_token_number_redeclaration (int num, symbol *first, symbol *second)
{ {
@@ -589,7 +581,7 @@ user_token_number_redeclaration (int num, symbol *first, symbol *second)
first = second; first = second;
second = tmp; second = tmp;
} }
complain_indent (&second->location, complaint, &i, start_complain_indent (&second->location, complaint, &i,
_("user token number %d redeclaration for %s"), _("user token number %d redeclaration for %s"),
num, second->tag); num, second->tag);
i += SUB_INDENT; i += SUB_INDENT;
@@ -606,17 +598,18 @@ static inline bool
symbol_translation (symbol *this) symbol_translation (symbol *this)
{ {
/* Non-terminal? */ /* Non-terminal? */
if (this->class == token_sym if (this->content->class == token_sym
&& this->user_token_number != USER_NUMBER_HAS_STRING_ALIAS) && !this->is_alias)
{ {
/* A token which translation has already been set? */ /* A token which translation has already been set?*/
if (token_translations[this->user_token_number] != undeftoken->number) if (token_translations[this->content->user_token_number]
!= undeftoken->content->number)
user_token_number_redeclaration user_token_number_redeclaration
(this->user_token_number, (this->content->user_token_number,
symbols[token_translations[this->user_token_number]], symbols[token_translations[this->content->user_token_number]], this);
this); else
token_translations[this->content->user_token_number]
token_translations[this->user_token_number] = this->number; = this->content->number;
} }
return true; return true;
@@ -702,7 +695,7 @@ symbols_new (void)
NULL, NULL,
hash_symbol_hasher, hash_symbol_hasher,
hash_symbol_comparator, hash_symbol_comparator,
free); symbol_free);
semantic_type_table = hash_initialize (HT_INITIAL_CAPACITY, semantic_type_table = hash_initialize (HT_INITIAL_CAPACITY,
NULL, NULL,
hash_semantic_type_hasher, hash_semantic_type_hasher,
@@ -802,8 +795,8 @@ dummy_symbol_get (location loc)
sprintf (buf, "$@%d", ++dummy_count); sprintf (buf, "$@%d", ++dummy_count);
sym = symbol_get (buf, loc); sym = symbol_get (buf, loc);
sym->class = nterm_sym; sym->content->class = nterm_sym;
sym->number = nvars++; sym->content->number = nvars++;
return sym; return sym;
} }
@@ -893,7 +886,7 @@ symbols_token_translations_init (void)
max_user_token_number = 0; max_user_token_number = 0;
for (i = 0; i < ntokens; ++i) for (i = 0; i < ntokens; ++i)
{ {
symbol *this = symbols[i]; sym_content *this = symbols[i]->content;
if (this->user_token_number != USER_NUMBER_UNDEFINED) if (this->user_token_number != USER_NUMBER_UNDEFINED)
{ {
if (this->user_token_number > max_user_token_number) if (this->user_token_number > max_user_token_number)
@@ -905,8 +898,8 @@ symbols_token_translations_init (void)
/* If 256 is not used, assign it to error, to follow POSIX. */ /* If 256 is not used, assign it to error, to follow POSIX. */
if (num_256_available_p if (num_256_available_p
&& errtoken->user_token_number == USER_NUMBER_UNDEFINED) && errtoken->content->user_token_number == USER_NUMBER_UNDEFINED)
errtoken->user_token_number = 256; errtoken->content->user_token_number = 256;
/* Set the missing user numbers. */ /* Set the missing user numbers. */
if (max_user_token_number < 256) if (max_user_token_number < 256)
@@ -914,7 +907,7 @@ symbols_token_translations_init (void)
for (i = 0; i < ntokens; ++i) for (i = 0; i < ntokens; ++i)
{ {
symbol *this = symbols[i]; sym_content *this = symbols[i]->content;
if (this->user_token_number == USER_NUMBER_UNDEFINED) 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) if (this->user_token_number > max_user_token_number)
@@ -927,7 +920,7 @@ symbols_token_translations_init (void)
/* Initialize all entries for literal tokens to the internal token /* Initialize all entries for literal tokens to the internal token
number for $undefined, which represents all invalid inputs. */ number for $undefined, which represents all invalid inputs. */
for (i = 0; i < max_user_token_number + 1; i++) for (i = 0; i < max_user_token_number + 1; i++)
token_translations[i] = undeftoken->number; token_translations[i] = undeftoken->content->number;
symbols_do (symbol_translation_processor, NULL, symbols_do (symbol_translation_processor, NULL,
symbol_table, &symbols_sorted); symbol_table, &symbols_sorted);
} }
@@ -941,9 +934,6 @@ symbols_token_translations_init (void)
void void
symbols_pack (void) symbols_pack (void)
{ {
symbols_do (symbol_check_alias_consistency_processor, NULL,
symbol_table, &symbols_sorted);
symbols = xcalloc (nsyms, sizeof *symbols); symbols = xcalloc (nsyms, sizeof *symbols);
symbols_do (symbol_pack_processor, NULL, symbol_table, &symbols_sorted); symbols_do (symbol_pack_processor, NULL, symbol_table, &symbols_sorted);
@@ -962,9 +952,7 @@ symbols_pack (void)
else else
{ {
symbols[writei] = symbols[readi]; symbols[writei] = symbols[readi];
symbols[writei]->number = writei; symbols[writei]->content->number = writei;
if (symbols[writei]->alias)
symbols[writei]->alias->number = writei;
writei += 1; writei += 1;
} }
} }
@@ -973,11 +961,11 @@ symbols_pack (void)
symbols_token_translations_init (); symbols_token_translations_init ();
if (startsymbol->class == unknown_sym) if (startsymbol->content->class == unknown_sym)
complain (&startsymbol_location, fatal, complain (&startsymbol_location, fatal,
_("the start symbol %s is undefined"), _("the start symbol %s is undefined"),
startsymbol->tag); startsymbol->tag);
else if (startsymbol->class == token_sym) else if (startsymbol->content->class == token_sym)
complain (&startsymbol_location, fatal, complain (&startsymbol_location, fatal,
_("the start symbol %s is a token"), _("the start symbol %s is a token"),
startsymbol->tag); startsymbol->tag);
@@ -1057,27 +1045,40 @@ register_precedence (graphid first, graphid snd)
} }
/*--------------------------------------------------. /*---------------------------------------.
| Print a warning for unused precedence relations. | | Deep clear a linked / adjacency list). |
`--------------------------------------------------*/ `---------------------------------------*/
void static void
print_precedence_warnings (void) linkedlist_free (symgraphlink *node)
{
if (node)
{
while (node->next)
{
symgraphlink *tmp = node->next;
free (node);
node = tmp;
}
free (node);
}
}
/*----------------------------------------------.
| Clear and destroy association tracking table. |
`----------------------------------------------*/
static void
assoc_free (void)
{ {
int i; int i;
if (!prec_nodes)
init_prec_nodes ();
for (i = 0; i < nsyms; ++i) for (i = 0; i < nsyms; ++i)
{ {
symbol *s = symbols[i]; linkedlist_free (prec_nodes[i]->pred);
if (s linkedlist_free (prec_nodes[i]->succ);
&& s->prec != 0 free (prec_nodes[i]);
&& !prec_nodes[i]->pred
&& !prec_nodes[i]->succ
&& s->assoc == precedence_assoc)
complain (&s->location, Wother,
_("useless precedence for %s"), s->tag);
} }
free (prec_nodes);
} }
/*---------------------------------------. /*---------------------------------------.
@@ -1088,7 +1089,7 @@ static void
init_assoc (void) init_assoc (void)
{ {
graphid i; graphid i;
used_assoc = xcalloc(nsyms, sizeof(*used_assoc)); used_assoc = xcalloc (nsyms, sizeof *used_assoc);
for (i = 0; i < nsyms; ++i) for (i = 0; i < nsyms; ++i)
used_assoc[i] = false; used_assoc[i] = false;
} }
@@ -1101,9 +1102,9 @@ static inline bool
is_assoc_useless (symbol *s) is_assoc_useless (symbol *s)
{ {
return s return s
&& s->assoc != undef_assoc && s->content->assoc != undef_assoc
&& s->assoc != precedence_assoc && s->content->assoc != precedence_assoc
&& !used_assoc[s->number]; && !used_assoc[s->content->number];
} }
/*-------------------------------. /*-------------------------------.
@@ -1119,21 +1120,37 @@ register_assoc (graphid i, graphid j)
used_assoc[j] = true; used_assoc[j] = true;
} }
/*------------------------------------------------------. /*--------------------------------------------------.
| Print a warning for each unused symbol associativity. | | Print a warning for unused precedence relations. |
`------------------------------------------------------*/ `--------------------------------------------------*/
void void
print_assoc_warnings (void) print_precedence_warnings (void)
{ {
graphid i; int i;
if (!prec_nodes)
init_prec_nodes ();
if (!used_assoc) if (!used_assoc)
init_assoc (); init_assoc ();
for (i = 0; i < nsyms; ++i) for (i = 0; i < nsyms; ++i)
{ {
symbol *s = symbols[i]; symbol *s = symbols[i];
if (is_assoc_useless (s)) if (s
complain (&s->location, Wother, && s->content->prec != 0
_("useless associativity for %s"), s->tag); && !prec_nodes[i]->pred
&& !prec_nodes[i]->succ)
{
if (is_assoc_useless (s))
complain (&s->content->prec_location, Wprecedence,
_("useless precedence and associativity for %s"), s->tag);
else if (s->content->assoc == precedence_assoc)
complain (&s->content->prec_location, Wprecedence,
_("useless precedence for %s"), s->tag);
}
else if (is_assoc_useless (s))
complain (&s->content->prec_location, Wprecedence,
_("useless associativity for %s, use %%precedence"), s->tag);
} }
free (used_assoc);
assoc_free ();
} }
+21 -13
View File
@@ -50,6 +50,7 @@ typedef int symbol_number;
typedef struct symbol symbol; typedef struct symbol symbol;
typedef struct sym_content sym_content;
/* Declaration status of a symbol. /* Declaration status of a symbol.
@@ -82,8 +83,6 @@ enum code_props_type
enum { CODE_PROPS_SIZE = 2 }; enum { CODE_PROPS_SIZE = 2 };
/* When extending this structure, be sure to complete
symbol_check_alias_consistency. */
struct symbol struct symbol
{ {
/** The key, name of the symbol. */ /** The key, name of the symbol. */
@@ -91,6 +90,20 @@ struct symbol
/** The location of its first occurrence. */ /** The location of its first occurrence. */
location location; location location;
/* Points to the other in the symbol-string pair for an alias. */
symbol *alias;
/** Whether this symbol is the alias of another or not. */
bool is_alias;
/** All the info about the pointed symbol is there. */
sym_content *content;
};
struct sym_content
{
symbol *symbol;
/** Its \c \%type. /** Its \c \%type.
Beware that this is the type_name as was entered by the user, Beware that this is the type_name as was entered by the user,
@@ -117,10 +130,6 @@ struct symbol
assoc assoc; assoc assoc;
int user_token_number; int user_token_number;
/* Points to the other in the symbol-string pair for an alias.
Special value USER_NUMBER_HAS_STRING_ALIAS in the symbol half of the
symbol-string pair for an alias. */
symbol *alias;
symbol_class class; symbol_class class;
status status; status status;
}; };
@@ -128,9 +137,9 @@ struct symbol
/** Undefined user number. */ /** Undefined user number. */
# define USER_NUMBER_UNDEFINED -1 # define USER_NUMBER_UNDEFINED -1
/* `symbol->user_token_number == USER_NUMBER_HAS_STRING_ALIAS' means /* 'symbol->user_token_number == USER_NUMBER_HAS_STRING_ALIAS' means
this symbol has a literal string alias. For instance, `%token foo this symbol has a literal string alias. For instance, '%token foo
"foo"' has `"foo"' numbered regularly, and `foo' numbered as "foo"' has '"foo"' numbered regularly, and 'foo' numbered as
USER_NUMBER_HAS_STRING_ALIAS. */ USER_NUMBER_HAS_STRING_ALIAS. */
# define USER_NUMBER_HAS_STRING_ALIAS -9991 # define USER_NUMBER_HAS_STRING_ALIAS -9991
@@ -266,7 +275,8 @@ struct symgraph
void register_precedence (graphid first, graphid snd); void register_precedence (graphid first, graphid snd);
/** Print a warning for each symbol whose precedence is useless. */ /** Print a warning for each symbol whose precedence and/or associativity
* is useless. */
void print_precedence_warnings (void); void print_precedence_warnings (void);
@@ -274,9 +284,7 @@ void print_precedence_warnings (void);
| Symbol associativity | | Symbol associativity |
`----------------------*/ `----------------------*/
void register_assoc (int i, int j); void register_assoc (graphid i, graphid j);
void print_assoc_warnings (void);
/*-----------------. /*-----------------.
| Semantic types. | | Semantic types. |
+1 -1
View File
@@ -99,7 +99,7 @@ typedef size_t uintptr_t;
# endif # endif
# 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. */ are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) # if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
# define __format__ format # define __format__ format
+9 -9
View File
@@ -35,7 +35,7 @@
#include "tables.h" #include "tables.h"
/* Several tables are indexed both by state and nonterminal numbers. /* 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. or a nonterminal number.
Of course vector_number_t ought to be wide enough to contain Of course vector_number_t ought to be wide enough to contain
@@ -90,18 +90,18 @@ static base_number *width;
/* For a given state, N = ACTROW[SYMBOL]: /* For a given state, N = ACTROW[SYMBOL]:
If N = 0, stands for `run the default action'. If N = 0, stands for 'run the default action'.
If N = MIN, stands for `raise a syntax error'. 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 'shift SYMBOL and go to n'.
If N < 0, stands for `reduce -N'. */ If N < 0, stands for 'reduce -N'. */
typedef int action_number; typedef int action_number;
#define ACTION_NUMBER_MINIMUM INT_MIN #define ACTION_NUMBER_MINIMUM INT_MIN
static action_number *actrow; static action_number *actrow;
/* FROMS and TOS are reordered to be compressed. ORDER[VECTOR] is the /* FROMS and TOS are reordered to be compressed. ORDER[VECTOR] is the
new vector number of VECTOR. We skip `empty' vectors (i.e., new vector number of VECTOR. We skip 'empty' vectors (i.e.,
TALLY[VECTOR] = 0), and call these `entries'. */ TALLY[VECTOR] = 0), and call these 'entries'. */
static vector_number *order; static vector_number *order;
static int nentries; static int nentries;
@@ -290,7 +290,7 @@ action_row (state *s)
/* Do not use any default reduction if there is a shift for /* Do not use any default reduction if there is a shift for
error */ error */
if (sym == errtoken->number) if (sym == errtoken->content->number)
nodefault = true; nodefault = true;
} }
@@ -300,7 +300,7 @@ action_row (state *s)
for (i = 0; i < errp->num; i++) for (i = 0; i < errp->num; i++)
{ {
symbol *sym = errp->symbols[i]; symbol *sym = errp->symbols[i];
actrow[sym->number] = ACTION_NUMBER_MINIMUM; actrow[sym->content->number] = ACTION_NUMBER_MINIMUM;
} }
/* Turn off default reductions where requested by the user. See /* Turn off default reductions where requested by the user. See
+1 -1
View File
@@ -105,7 +105,7 @@ uniqstr_print_processor (void *ustr, void *null ATTRIBUTE_UNUSED)
int int
uniqstr_cmp(uniqstr l, uniqstr r) uniqstr_cmp (uniqstr l, uniqstr r)
{ {
return (l == r ? 0 return (l == r ? 0
: !l ? -1 : !l ? -1
+1 -1
View File
@@ -40,7 +40,7 @@ uniqstr uniqstr_vsprintf (char const *format, ...)
/* Compare two uniqstr a la strcmp: negative for <, nul for =, and /* Compare two uniqstr a la strcmp: negative for <, nul for =, and
positive for >. Undefined order, relies on addresses. */ positive for >. Undefined order, relies on addresses. */
int uniqstr_cmp(uniqstr u1, uniqstr u2); int uniqstr_cmp (uniqstr u1, uniqstr u2);
/* Die if STR is not a uniqstr. */ /* Die if STR is not a uniqstr. */
void uniqstr_assert (char const *str); void uniqstr_assert (char const *str);
+129 -125
View File
@@ -64,6 +64,119 @@ AT_PARSER_CHECK([./input], 0,
AT_CLEANUP 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. ## ## Initial location. ##
@@ -173,8 +286,8 @@ m4_popdef([AT_TEST])
## Location Print. ## ## Location Print. ##
## ---------------- ## ## ---------------- ##
# AT_TEST(SKELETON-NAME, DIRECTIVES, [MORE-DIRECTIVES], [LOCATION = 1.1]) # AT_TEST(SKELETON-NAME, DIRECTIVES, [MORE-DIRECTIVES])
# ----------------------------------------------------------------------- # -----------------------------------------------------
# Check that the initial location is correct. # Check that the initial location is correct.
m4_pushdef([AT_TEST], m4_pushdef([AT_TEST],
[AT_SETUP([Location print: $1 $2]) [AT_SETUP([Location print: $1 $2])
@@ -192,7 +305,7 @@ AT_DATA_GRAMMAR([[input.y]],
]AT_YYLEX_DECLARE[ ]AT_YYLEX_DECLARE[
} }
%% %%
exp: /* empty */; exp: %empty;
%% %%
]AT_YYERROR_DEFINE[ ]AT_YYERROR_DEFINE[
]AT_YYLEX_DEFINE[ ]AT_YYLEX_DEFINE[
@@ -415,7 +528,7 @@ AT_LALR1_CC_IF([typedef yy::location YYLTYPE;])[
%% %%
/* /*
This grammar is made to exercise error recovery. 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 ')' as synchronizing token. Lines starting with 'x' can never
be recovered from if in error. be recovered from if in error.
*/ */
@@ -492,11 +605,11 @@ static
{ {
static unsigned int counter = 0; static unsigned int counter = 0;
int c = ]AT_VAL[]m4_ifval([$6], [.ival])[ = counter++; unsigned int c = ]AT_VAL[]m4_ifval([$6], [.ival])[ = counter++;
/* As in BASIC, line numbers go from 10 to 10. */ /* As in BASIC, line numbers go from 10 to 10. */
]AT_LOC_FIRST_LINE[ = ]AT_LOC_FIRST_COLUMN[ = 10 * c; ]AT_LOC_FIRST_LINE[ = ]AT_LOC_FIRST_COLUMN[ = 10 * c;
]AT_LOC_LAST_LINE[ = ]AT_LOC_LAST_COLUMN[ = ]AT_LOC_FIRST_LINE[ + 9; ]AT_LOC_LAST_LINE[ = ]AT_LOC_LAST_COLUMN[ = ]AT_LOC_FIRST_LINE[ + 9;
assert (0 <= c && c <= strlen (source)); assert (c <= strlen (source));
if (source[c]) if (source[c])
fprintf (stderr, "sending: '%c'", source[c]); fprintf (stderr, "sending: '%c'", source[c]);
else else
@@ -578,7 +691,7 @@ Successful parse.
# Syntax errors caught by the parser # 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. # can be reduced.
# #
# '(', 'x', 'x', 'x', 'x', 'x', ')', # '(', 'x', 'x', 'x', 'x', 'x', ')',
@@ -735,13 +848,13 @@ AT_CLEANUP
AT_CHECK_PRINTER_AND_DESTRUCTOR([]) 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"])
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])
AT_CHECK_PRINTER_AND_DESTRUCTOR([%glr-parser], [with union]) AT_CHECK_PRINTER_AND_DESTRUCTOR([%glr-parser], [ with union])
@@ -1174,7 +1287,7 @@ AT_SETUP([Default %printer and %destructor are not for $accept])
# - The %printer and %destructor code generated for $accept would always be # - The %printer and %destructor code generated for $accept would always be
# dead code because $accept is currently never shifted onto the stack. # dead code because $accept is currently never shifted onto the stack.
# - $$ for $accept would always be of type YYSTYPE because it's not possible # - $$ 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 # - Thus, the compiler might complain that the user code assumes the wrong
# type for $$ since the code might assume the type associated with a # type for $$ since the code might assume the type associated with a
# specific union field, which is especially reasonable in C++ since that # specific union field, which is especially reasonable in C++ since that
@@ -1272,8 +1385,8 @@ AT_BISON_OPTION_POPDEFS
AT_BISON_CHECK([-o input.c input.y], 0,, AT_BISON_CHECK([-o input.c input.y], 0,,
[[input.y:24.70-72: warning: useless %destructor for type <*> [-Wother] [[input.y:24.70-72: warning: useless %destructor for type <*> [-Wother]
input.y:24.70-72: warning: useless %printer 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] input.y:32.3-23: warning: unused value: $3 [-Wother]
input.y:33.3-23: warning: unset value: $$ [-Wother]
]]) ]])
AT_BISON_CHECK([-fcaret -o input.c input.y], 0,, AT_BISON_CHECK([-fcaret -o input.c input.y], 0,,
@@ -1283,12 +1396,12 @@ AT_BISON_CHECK([-fcaret -o input.c input.y], 0,,
input.y:24.70-72: warning: useless %printer for type <*> [-Wother] input.y:24.70-72: warning: useless %printer for type <*> [-Wother]
%printer { fprintf (yyoutput, "<*> printer should not be called"); } <*> %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 [-Wother] input.y:32.3-23: warning: unused value: $3 [-Wother]
{ USE ($$); @$ = 3; } // Only set. { USE ($$); @$ = 3; } // Only set.
^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^
input.y:33.3-23: warning: unset value: $$ [-Wother]
{ @$ = 4; } // Only used.
^^^^^^^^^^^^^^^^^^^^^
]]) ]])
AT_COMPILE([input]) AT_COMPILE([input])
@@ -1494,115 +1607,6 @@ AT_TEST([glr.cc])
m4_popdef([AT_TEST]) 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 [-Wdeprecated]
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 [-Wdeprecated]
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 [-Wdeprecated]
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 [-Wdeprecated]
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 [-Wdeprecated]
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 [-Wdeprecated]
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 [-Wdeprecated]
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 [-Wdeprecated]
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 [-Wdeprecated]
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 [-Wdeprecated]
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 [-Wdeprecated]
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 [-Wdeprecated]
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 [-Wdeprecated]
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 [-Wdeprecated]
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 [-Wdeprecated]
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 [-Wdeprecated]
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 [-Wdeprecated]
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 [-Wdeprecated]
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. ## ## Destroying lookahead assigned by semantic action. ##
## -------------------------------------------------- ## ## -------------------------------------------------- ##
@@ -1637,7 +1641,7 @@ AT_DATA_GRAMMAR([input.y],
// that has set yychar might not always return normally. Instead, // that has set yychar might not always return normally. Instead,
// skeletons must translate before every use of yytoken. // skeletons must translate before every use of yytoken.
start: 'a' accept { USE($1); } ; start: 'a' accept { USE($1); } ;
accept: /*empty*/ { accept: %empty {
assert (yychar == YYEMPTY); assert (yychar == YYEMPTY);
yychar = 'b'; yychar = 'b';
YYACCEPT; YYACCEPT;
+32 -4
View File
@@ -16,7 +16,7 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # 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@" CPPFLAGS="-I$abs_top_builddir/lib @CPPFLAGS@"
# Don't just check if $POSIXLY_CORRECT is set, as Bash, when launched # Don't just check if $POSIXLY_CORRECT is set, as Bash, when launched
@@ -47,12 +47,40 @@ NO_WERROR_CXXFLAGS='@CXXFLAGS@ @WARN_CXXFLAGS@ @WARN_CXXFLAGS_TEST@'
CFLAGS="$NO_WERROR_CFLAGS @WERROR_CFLAGS@" CFLAGS="$NO_WERROR_CFLAGS @WERROR_CFLAGS@"
CXXFLAGS="$NO_WERROR_CXXFLAGS @WERROR_CXXFLAGS@" CXXFLAGS="$NO_WERROR_CXXFLAGS @WERROR_CXXFLAGS@"
# C++ variants break strict aliasing analysis.
NO_STRICT_ALIAS_CXXFLAGS='@NO_STRICT_ALIAS_CXXFLAGS@'
# If 'exit 77'; skip all C++ tests; otherwise ':'. # If 'exit 77'; skip all C++ tests; otherwise ':'.
BISON_CXX_WORKS='@BISON_CXX_WORKS@' BISON_CXX_WORKS='@BISON_CXX_WORKS@'
# Be sure that the C++ compiler is not broken because of gnulib. This
# cannot be checked in configure (gnulib is not parameterized yet),
# and checking this in every C++ test in AC_COMPILE_CXX is too costly.
#
# http://lists.gnu.org/archive/html/bug-bison/2013-06/msg00001.html
#
# FIXME: Check (say 2014) whether this is still needed.
if $BISON_CXX_WORKS; then
# See AT_DATA_SOURCE_PROLOGUE.
cat >conftest.cc <<EOF
#include <config.h>
/* We don't need perfect functions for these tests. */
#undef malloc
#undef memcmp
#undef realloc
#include <iostream>
int main ()
{
std::cout << "Works" << std::endl;
}
EOF
ls
$CXX $CXXFLAGS $CPPFLAGS $LDFLAGS $LIBS -o conftest conftest.cc
case $? in
0);;
*) BISON_CXX_WORKS="as_fn_error 77 cannot-compile-simple-program";;
esac
rm -f conftest*
fi
# Whether the compiler supports POSIXLY_CORRECT defined. # Whether the compiler supports POSIXLY_CORRECT defined.
: ${C_COMPILER_POSIXLY_CORRECT='@C_COMPILER_POSIXLY_CORRECT@'} : ${C_COMPILER_POSIXLY_CORRECT='@C_COMPILER_POSIXLY_CORRECT@'}
: ${CXX_COMPILER_POSIXLY_CORRECT='@CXX_COMPILER_POSIXLY_CORRECT@'} : ${CXX_COMPILER_POSIXLY_CORRECT='@CXX_COMPILER_POSIXLY_CORRECT@'}
+110 -42
View File
@@ -18,6 +18,68 @@
AT_BANNER([[C++ Features.]]) AT_BANNER([[C++ Features.]])
## --------------- ##
## C++ Locations. ##
## --------------- ##
AT_SETUP([C++ Locations])
AT_BISON_OPTION_PUSHDEFS([%locations %skeleton "lalr1.cc"])
AT_DATA_GRAMMAR([[input.y]],
[[%code {#include <sstream>}
%locations
%debug
%skeleton "lalr1.cc"
%code
{
]AT_YYERROR_DECLARE[
]AT_YYLEX_DECLARE[
}
%%
exp: %empty;
%%
]AT_YYERROR_DEFINE[
]AT_YYLEX_DEFINE[
template <typename T>
bool
check (const T& in, const std::string& s)
{
std::stringstream os;
os << in;
if (os.str () != s)
{
std::cerr << "fail: " << os.str () << ", expected: " << s << std::endl;
return false;
}
return true;
}
int
main (void)
{
int fail = 0;
]AT_YYLTYPE[ loc; fail += check (loc, "1.1");
loc += 10; fail += check (loc, "1.1-10");
loc += -5; fail += check (loc, "1.1-5");
loc -= 5; fail += check (loc, "1.1");
// Check that we don't go below.
// http://lists.gnu.org/archive/html/bug-bison/2013-02/msg00000.html
loc -= 10; fail += check (loc, "1.1");
loc.columns (10); loc.lines (10); fail += check (loc, "1.1-11.0");
loc.lines (-2); fail += check (loc, "1.1-9.0");
loc.lines (-10); fail += check (loc, "1.1");
return !fail;
}
]])
AT_FULL_COMPILE([input])
AT_PARSER_CHECK([./input], 0)
AT_BISON_OPTION_POPDEFS
AT_CLEANUP
## --------------------------- ## ## --------------------------- ##
## C++ Variant-based Symbols. ## ## C++ Variant-based Symbols. ##
## --------------------------- ## ## --------------------------- ##
@@ -28,7 +90,7 @@ AT_KEYWORDS([variant])
AT_BISON_OPTION_PUSHDEFS([%skeleton "lalr1.cc" %debug $1]) AT_BISON_OPTION_PUSHDEFS([%skeleton "lalr1.cc" %debug $1])
# Store strings and integers in a list of strings. # Store strings and integers in a list of strings.
AT_DATA_GRAMMAR([list.yy], AT_DATA_GRAMMAR([list.y],
[[%skeleton "lalr1.cc" [[%skeleton "lalr1.cc"
%define api.value.type variant %define api.value.type variant
%define parse.assert %define parse.assert
@@ -92,8 +154,7 @@ int main()
} }
]]) ]])
AT_BISON_CHECK([-o list.cc list.yy]) AT_FULL_COMPILE([list])
AT_COMPILE_CXX([list], [$NO_STRICT_ALIAS_CXXFLAGS list.cc])
AT_PARSER_CHECK([./list], 0, [], AT_PARSER_CHECK([./list], 0, [],
[12 [12
123 123
@@ -115,7 +176,7 @@ m4_pushdef([AT_TEST],
AT_BISON_OPTION_PUSHDEFS([%skeleton "lalr1.cc" %debug $1]) AT_BISON_OPTION_PUSHDEFS([%skeleton "lalr1.cc" %debug $1])
# Store strings and integers in a list of strings. # Store strings and integers in a list of strings.
AT_DATA_GRAMMAR([list.yy], AT_DATA_GRAMMAR([list.y],
[[%debug [[%debug
%skeleton "lalr1.cc" %skeleton "lalr1.cc"
%define api.value.type variant %define api.value.type variant
@@ -250,8 +311,7 @@ namespace yy
]AT_MAIN_DEFINE[ ]AT_MAIN_DEFINE[
]]) ]])
AT_BISON_CHECK([-o list.cc list.yy]) AT_FULL_COMPILE([list])
AT_COMPILE_CXX([list], [$NO_STRICT_ALIAS_CXXFLAGS list.cc])
AT_PARSER_CHECK([./list], 0, AT_PARSER_CHECK([./list], 0,
[(0, 1, 2, 4) [(0, 1, 2, 4)
]) ])
@@ -265,8 +325,8 @@ AT_TEST([%define parse.assert])
AT_TEST([%locations %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 %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]])
AT_TEST([[%define parse.assert %define api.token.constructor %define api.token.prefix "TOK_"]]) 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_"]]) AT_TEST([[%locations %define parse.assert %define api.token.constructor %define api.token.prefix {TOK_}]])
m4_popdef([AT_TEST]) m4_popdef([AT_TEST])
@@ -363,10 +423,10 @@ AT_CHECK_DOXYGEN([Private])
# is specified, then Bison should accept the input, but compilation will fail, # is specified, then Bison should accept the input, but compilation will fail,
# so don't check compilation. # so don't check compilation.
m4_pushdef([AT_TEST], m4_pushdef([AT_TEST],
[AT_BISON_OPTION_PUSHDEFS([%language "C++" %define api.namespace "$1"]) [AT_BISON_OPTION_PUSHDEFS([%language "C++" %define api.namespace {$1}])
AT_DATA_GRAMMAR([[input.y]], AT_DATA_GRAMMAR([[input.y]],
[[%language "C++" [[%language "C++"
%define api.namespace "]$1[" %define api.namespace {]$1[}
%union { int i; } %union { int i; }
%define global_tokens_and_yystype %define global_tokens_and_yystype
%locations %locations
@@ -422,8 +482,8 @@ AT_CLEANUP
AT_SETUP([[Syntactically invalid namespace references]]) AT_SETUP([[Syntactically invalid namespace references]])
AT_TEST([[:foo:bar]], [[-]]) AT_TEST([[:foo:bar]], [[-]])
AT_TEST([[foo: :bar]], [[-]]) AT_TEST([[foo: :bar]], [[-]])
# This one is interesting because `[3]' is encoded as `@<:@3@:>@', which # This one is interesting because '[3]' is encoded as '@<:@3@:>@', which
# contains single occurrences of `:'. # contains single occurrences of ':'.
AT_TEST([[foo[3]::bar::baz]], [[-]]) AT_TEST([[foo[3]::bar::baz]], [[-]])
AT_TEST([[foo::bar,baz]], [[-]]) AT_TEST([[foo::bar,baz]], [[-]])
AT_TEST([[foo::bar::(baz /* Pacify Emacs ) */]], [[-]]) AT_TEST([[foo::bar::(baz /* Pacify Emacs ) */]], [[-]])
@@ -615,14 +675,42 @@ $1
/// A class that counts its number of instances. /// A class that counts its number of instances.
struct Object 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; typedef std::list<const Object*> objects;
static objects instances; static objects instances;
char val;
static bool static bool
empty () empty ()
{ {
return instances.empty(); return instances.empty ();
} }
static void static void
@@ -645,26 +733,6 @@ $1
std::cerr << " }" << std::endl; std::cerr << " }" << std::endl;
} }
} }
Object (char v)
: val (v)
{
instances.push_back(this);
log (this, "Object::Object");
}
Object ()
: val ('?')
{
instances.push_back(this);
log (this, "Object::Object");
}
~Object ()
{
instances.remove(this);
log (this, "Object::~Object");
}
}; };
} }
@@ -722,16 +790,16 @@ list:
; ;
item: item:
'a' { $$][ = $][1; } 'a' { $$][ = $][1; }
| 'e' { YYUSE ($][$); YYUSE($][1); error ("syntax error"); } | 'e' { YYUSE ($][$); YYUSE($][1); error ("syntax error"); }
// Not just 'E', otherwise we reduce when 'E' is the lookahead, and // Not just 'E', otherwise we reduce when 'E' is the lookahead, and
// then the stack is emptied, defeating the point of the test. // then the stack is emptied, defeating the point of the test.
| 'E' 'a' { YYUSE($][1); $][$ = $][2; } | 'E' 'a' { YYUSE($][1); $][$ = $][2; }
| 'R' { $][$ = YY_NULL; ]AT_VARIANT_IF([], [delete $][1]; )[YYERROR; } | 'R' { ]AT_VARIANT_IF([], [$][$ = YY_NULL; delete $][1]; )[YYERROR; }
| 'p' { $][$ = $][1; } | 'p' { $][$ = $][1; }
| 's' { $][$ = $][1; throw std::runtime_error ("reduction"); } | 's' { $][$ = $][1; throw std::runtime_error ("reduction"); }
| 'T' { $][$ = YY_NULL; ]AT_VARIANT_IF([], [delete $][1]; )[YYABORT; } | 'T' { ]AT_VARIANT_IF([], [$][$ = YY_NULL; delete $][1]; )[YYABORT; }
| error { $][$ = YY_NULL; yyerrok; } | error { ]AT_VARIANT_IF([], [$][$ = YY_NULL; ])[yyerrok; }
; ;
%% %%
@@ -804,7 +872,7 @@ main (int argc, const char *argv[])
} }
]]) ]])
AT_BISON_CHECK([[-o input.cc --report=all input.yy]]) AT_BISON_CHECK([[-o input.cc --report=all input.yy]])
AT_COMPILE_CXX([input], [[$NO_STRICT_ALIAS_CXXFLAGS input.cc]]) AT_COMPILE_CXX([[input]])
AT_PARSER_CHECK([[./input aaaas]], [[2]], [[]], AT_PARSER_CHECK([[./input aaaas]], [[2]], [[]],
[[exception caught: reduction [[exception caught: reduction
+48 -48
View File
@@ -27,11 +27,11 @@
# _AT_DATA_CALC_Y($1, $2, $3, [BISON-DIRECTIVES]) # _AT_DATA_CALC_Y($1, $2, $3, [BISON-DIRECTIVES])
# ----------------------------------------------- # -----------------------------------------------
# Produce `calc.y' and, if %defines was specified, `calc-lex.c' or # Produce 'calc.y' and, if %defines was specified, 'calc-lex.c' or
# `calc-lex.cc'. # 'calc-lex.cc'.
# #
# Don't call this macro directly, because it contains some occurrences # 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. # 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. # When %defines is not passed, generate a single self-contained file.
@@ -72,10 +72,12 @@ main (int argc, const char **argv)
int count = 0; int count = 0;
int status; int status;
/* This used to be alarm (10), but that isn't enough time for /* This used to be alarm (10), but that isn't enough time for a July
a July 1995 vintage DEC Alphastation 200 4/100 system, 1995 vintage DEC Alphastation 200 4/100 system, according to
according to Nelson H. F. Beebe. 100 seconds is enough. */ Nelson H. F. Beebe. 100 seconds was enough for regular users,
alarm (100); but the Hydra build farm, which is heavily loaded needs more. */
alarm (200);
if (argc == 2) if (argc == 2)
input = fopen (argv[1], "r"); input = fopen (argv[1], "r");
@@ -88,8 +90,7 @@ main (int argc, const char **argv)
return 3; return 3;
} }
]AT_SKEL_CC_IF([], [m4_bmatch([$4], [%debug], ]AT_SKEL_CC_IF([], [AT_DEBUG_IF([ ]AT_NAME_PREFIX[debug = 1;])])[
[ ]AT_NAME_PREFIX[debug = 1;])])[
status = ]AT_NAME_PREFIX[parse (]AT_PARAM_IF([[&result, &count]])[); status = ]AT_NAME_PREFIX[parse (]AT_PARAM_IF([[&result, &count]])[);
if (fclose (input)) if (fclose (input))
perror ("fclose"); perror ("fclose");
@@ -133,7 +134,7 @@ unget_char (]AT_YYLEX_PRE_FORMALS[ int c)
{ {
]AT_USE_LEX_ARGS[; ]AT_USE_LEX_ARGS[;
]AT_LOCATION_IF([ ]AT_LOCATION_IF([
/* Wrong when C == `\n'. */ /* Wrong when C == '\n'. */
AT_LOC = last_yylloc; AT_LOC = last_yylloc;
])[ ])[
ungetc (c, input); ungetc (c, input);
@@ -365,8 +366,8 @@ m4_popdef([AT_CALC_LEX])
# AT_DATA_CALC_Y([BISON-OPTIONS]) # AT_DATA_CALC_Y([BISON-OPTIONS])
# ------------------------------- # -------------------------------
# Produce `calc.y' and, if %defines was specified, `calc-lex.c' or # Produce 'calc.y' and, if %defines was specified, 'calc-lex.c' or
# `calc-lex.cc'. # 'calc-lex.cc'.
m4_define([AT_DATA_CALC_Y], m4_define([AT_DATA_CALC_Y],
[_AT_DATA_CALC_Y($[1], $[2], $[3], [$1]) [_AT_DATA_CALC_Y($[1], $[2], $[3], [$1])
]) ])
@@ -375,9 +376,9 @@ m4_define([AT_DATA_CALC_Y],
# _AT_CHECK_CALC(BISON-OPTIONS, INPUT, [NUM-STDERR-LINES]) # _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. # NUM-STDERR-LINES is the number of expected lines on stderr.
# Currently this is ignored, though, since the output format is fluctuating. # Currently this is ignored, though, since the output format is fluctuating.
@@ -396,7 +397,7 @@ AT_PARSER_CHECK([./calc input], 0, [], [stderr])
# [NUM-STDERR-LINES], # [NUM-STDERR-LINES],
# [VERBOSE-AND-LOCATED-ERROR-MESSAGE]) # [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, # If INPUT starts with a slash, it is used as absolute input file name,
# otherwise as contents. # otherwise as contents.
@@ -404,14 +405,14 @@ AT_PARSER_CHECK([./calc input], 0, [], [stderr])
# NUM-STDERR-LINES is the number of expected lines on stderr. # NUM-STDERR-LINES is the number of expected lines on stderr.
# Currently this is ignored, though, since the output format is fluctuating. # 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. # is correctly output on stderr.
# #
# If BISON-OPTIONS contains `%define parse.error verbose', then make sure the # If BISON-OPTIONS contains '%define parse.error verbose', then make sure the
# IF-YYERROR-VERBOSE message is properly output after `syntax error, ' # IF-YYERROR-VERBOSE message is properly output after 'syntax error, '
# on STDERR. # 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. # is the number of expected lines on stderr.
m4_define([_AT_CHECK_CALC_ERROR], m4_define([_AT_CHECK_CALC_ERROR],
[m4_bmatch([$3], [^/], [m4_bmatch([$3], [^/],
@@ -448,7 +449,7 @@ AT_DATA([[expout]],
AT_YYERROR_SEES_LOC_IF([], AT_YYERROR_SEES_LOC_IF([],
[[sed 's/^[-0-9.]*: //' expout >at-expout [[sed 's/^[-0-9.]*: //' expout >at-expout
mv at-expout expout]]) mv at-expout expout]])
# 4. If error-verbose is not used, strip the`, unexpected....' part. # 4. If error-verbose is not used, strip the', unexpected....' part.
m4_bmatch([$1], [%define parse.error verbose], [], m4_bmatch([$1], [%define parse.error verbose], [],
[[sed 's/syntax error, .*$/syntax error/' expout >at-expout [[sed 's/syntax error, .*$/syntax error/' expout >at-expout
mv at-expout expout]]) mv at-expout expout]])
@@ -478,7 +479,7 @@ m4_define([AT_CHECK_SPACES],
# AT_CHECK_CALC([BISON-OPTIONS]) # 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. # BISON-OPTIONS, and performs several tests over the parser.
m4_define([AT_CHECK_CALC], m4_define([AT_CHECK_CALC],
[m4_ifval([$2], [m4_fatal([$0: expected a single argument])]) [m4_ifval([$2], [m4_fatal([$0: expected a single argument])])
@@ -538,7 +539,7 @@ _AT_CHECK_CALC_ERROR([$1], [1], [/dev/null], [4],
# - (* * *): nothing to pop, a lot to discard # - (* * *): nothing to pop, a lot to discard
# - (1 + 2 * *): some to pop and 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 # - check the lookahead that triggers an error is not discarded
# when we enter error recovery. Below, the lookahead causing the # when we enter error recovery. Below, the lookahead causing the
@@ -587,7 +588,7 @@ AT_BANNER([[Simple LALR(1) Calculator.]])
# AT_CHECK_CALC_LALR([BISON-OPTIONS]) # 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. # BISON-OPTIONS, and performs several tests over the parser.
m4_define([AT_CHECK_CALC_LALR], m4_define([AT_CHECK_CALC_LALR],
[AT_CHECK_CALC($@)]) [AT_CHECK_CALC($@)])
@@ -606,17 +607,17 @@ 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([%define api.push-pull both %define api.pure full %locations])
AT_CHECK_CALC_LALR([%define parse.error verbose %locations]) AT_CHECK_CALC_LALR([%define parse.error verbose %locations])
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 %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([%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([%debug])
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 %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 parse.error 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.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.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 %define parse.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}])
# ----------------------- # # ----------------------- #
@@ -627,7 +628,7 @@ AT_BANNER([[Simple GLR Calculator.]])
# AT_CHECK_CALC_GLR([BISON-OPTIONS]) # 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. # BISON-OPTIONS and %glr-parser, and performs several tests over the parser.
m4_define([AT_CHECK_CALC_GLR], m4_define([AT_CHECK_CALC_GLR],
[AT_CHECK_CALC([%glr-parser] $@)]) [AT_CHECK_CALC([%glr-parser] $@)])
@@ -638,7 +639,7 @@ AT_CHECK_CALC_GLR()
AT_CHECK_CALC_GLR([%defines]) AT_CHECK_CALC_GLR([%defines])
AT_CHECK_CALC_GLR([%locations]) AT_CHECK_CALC_GLR([%locations])
AT_CHECK_CALC_GLR([%name-prefix "calc"]) AT_CHECK_CALC_GLR([%name-prefix "calc"])
AT_CHECK_CALC_GLR([%define api.prefix "calc"]) AT_CHECK_CALC_GLR([%define api.prefix {calc}])
AT_CHECK_CALC_GLR([%verbose]) AT_CHECK_CALC_GLR([%verbose])
AT_CHECK_CALC_GLR([%yacc]) AT_CHECK_CALC_GLR([%yacc])
AT_CHECK_CALC_GLR([%define parse.error verbose]) AT_CHECK_CALC_GLR([%define parse.error verbose])
@@ -650,12 +651,12 @@ AT_CHECK_CALC_GLR([%define parse.error verbose %locations %defines %name-prefix
AT_CHECK_CALC_GLR([%debug]) AT_CHECK_CALC_GLR([%debug])
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 %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 parse.error verbose %debug %locations %defines %define api.prefix {calc} %define api.token.prefix {TOK_} %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 %define parse.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 %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}]) 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}])
# ----------------------------- # # ----------------------------- #
@@ -669,26 +670,26 @@ AT_CHECK_CALC([%skeleton "lalr1.cc" %defines])
# AT_CHECK_CALC_LALR1_CC([BISON-OPTIONS]) # 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. # the C++ skeleton, and performs several tests over the parser.
m4_define([AT_CHECK_CALC_LALR1_CC], m4_define([AT_CHECK_CALC_LALR1_CC],
[AT_CHECK_CALC([%language "C++"] $@)]) [AT_CHECK_CALC([%language "C++"] $@)])
AT_CHECK_CALC_LALR1_CC([]) AT_CHECK_CALC_LALR1_CC([])
AT_CHECK_CALC_LALR1_CC([%locations]) AT_CHECK_CALC_LALR1_CC([%locations])
AT_CHECK_CALC_LALR1_CC([%locations %define api.location.type Span]) 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([%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 %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 %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 %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([%locations %define parse.error verbose %debug %define api.prefix {calc} %define api.token.prefix {TOK_} %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([%defines %locations %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 %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([%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}]) AT_CHECK_CALC_LALR1_CC([%defines %locations %define parse.error verbose %debug %define api.prefix {calc} %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
@@ -703,22 +704,21 @@ AT_CHECK_CALC([%skeleton "glr.cc"])
# AT_CHECK_CALC_GLR_CC([BISON-OPTIONS]) # 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. # the GLR C++ skeleton, and performs several tests over the parser.
m4_define([AT_CHECK_CALC_GLR_CC], m4_define([AT_CHECK_CALC_GLR_CC],
[AT_CHECK_CALC([%language "C++" %glr-parser] $@)]) [AT_CHECK_CALC([%language "C++" %glr-parser] $@)])
AT_CHECK_CALC_GLR_CC([]) AT_CHECK_CALC_GLR_CC([])
AT_CHECK_CALC_GLR_CC([%locations]) AT_CHECK_CALC_GLR_CC([%locations])
AT_CHECK_CALC_GLR_CC([%locations %define api.location.type Span]) 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([%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([%define parse.error verbose %define api.prefix {calc} %verbose %yacc])
AT_CHECK_CALC_GLR_CC([%debug]) AT_CHECK_CALC_GLR_CC([%debug])
AT_CHECK_CALC_GLR_CC([%define parse.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([%define parse.error verbose %debug %name-prefix "calc" %define api.token.prefix {TOK_} %verbose %yacc])
AT_CHECK_CALC_GLR_CC([%pure-parser %define parse.error verbose %debug %name-prefix "calc" %verbose %yacc]) AT_CHECK_CALC_GLR_CC([%locations %defines %define parse.error verbose %debug %name-prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
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([%locations %defines %define parse.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}])
+170 -102
View File
@@ -17,42 +17,9 @@
AT_BANNER([[Conflicts.]]) AT_BANNER([[Conflicts.]])
## ------------------------------ ## ## ------------------------- ##
## Useless associativity warning. ## ## Token declaration order. ##
## ------------------------------ ## ## ------------------------- ##
AT_SETUP([Useless associativity warning])
AT_DATA([[input.y]],
[[%token T
%left A B
%right C
%nonassoc D
%precedence E
%%
e: T A T
| T B T
| T C T
| T D T
| T E T
;
]])
AT_BISON_CHECK([input.y], 0, [],
[[input.y:5.13: warning: useless precedence for E [-Wother]
input.y:2.7: warning: useless associativity for A [-Wother]
input.y:2.9: warning: useless associativity for B [-Wother]
input.y:3.8: warning: useless associativity for C [-Wother]
input.y:4.11: warning: useless associativity for D [-Wother]
]])
AT_CLEANUP
## ------------------------ ##
## Token declaration order. ##
## ------------------------ ##
# This test checks that token are declared left to right when in a precedence # This test checks that token are declared left to right when in a precedence
# statement. # statement.
@@ -110,27 +77,7 @@ int main (void)
} }
]]) ]])
AT_BISON_CHECK([-o input.c input.y], [], [], AT_BISON_CHECK([-o input.c input.y])
[[input.y:24.13: warning: useless precedence for R [-Wother]
input.y:24.15: warning: useless precedence for S [-Wother]
input.y:24.17: warning: useless precedence for T [-Wother]
input.y:24.19: warning: useless precedence for U [-Wother]
input.y:25.13: warning: useless precedence for V [-Wother]
input.y:25.15: warning: useless precedence for W [-Wother]
input.y:18.8: warning: useless associativity for E [-Wother]
input.y:18.10: warning: useless associativity for F [-Wother]
input.y:18.12: warning: useless associativity for G [-Wother]
input.y:19.8: warning: useless associativity for H [-Wother]
input.y:19.10: warning: useless associativity for I [-Wother]
input.y:20.8: warning: useless associativity for J [-Wother]
input.y:21.8: warning: useless associativity for K [-Wother]
input.y:22.8: warning: useless associativity for L [-Wother]
input.y:22.10: warning: useless associativity for M [-Wother]
input.y:22.12: warning: useless associativity for N [-Wother]
input.y:23.11: warning: useless associativity for O [-Wother]
input.y:23.13: warning: useless associativity for P [-Wother]
input.y:23.15: warning: useless associativity for Q [-Wother]
]])
AT_COMPILE([input]) AT_COMPILE([input])
AT_PARSER_CHECK([./input]) AT_PARSER_CHECK([./input])
@@ -140,6 +87,127 @@ AT_BISON_OPTION_POPDEFS
AT_CLEANUP 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]],
[[%token EQ "=" PL "+" ST "*" LP "("
%nonassoc "="
%left "+"
%left "*"
%precedence "("
%%
stmt:
exp
| "var" "=" exp
;
exp:
exp "+" exp
| exp "*" "num"
| "(" exp ")"
| "num"
;
]])
AT_BISON_CHECK([-Wprecedence input.y], 0, [],
[[input.y:2.1-9: warning: useless precedence and associativity for "=" [-Wprecedence]
input.y:4.1-5: warning: useless associativity for "*", use %precedence [-Wprecedence]
input.y:5.1-11: warning: useless precedence for "(" [-Wprecedence]
]])
AT_CLEANUP
## ---------------------------- ## ## ---------------------------- ##
## Useless precedence warning. ## ## Useless precedence warning. ##
## ---------------------------- ## ## ---------------------------- ##
@@ -147,7 +215,7 @@ AT_CLEANUP
AT_SETUP([Useless precedence warning]) AT_SETUP([Useless precedence warning])
AT_DATA([[input.y]], AT_DATA([[input.y]],
[[%token A B [[%token A B U V W X Y Z
%precedence Z %precedence Z
%left X %left X
%precedence Y %precedence Y
@@ -174,19 +242,19 @@ f: B
; ;
]]) ]])
AT_BISON_CHECK([-fcaret -o input.c input.y], 0, [], AT_BISON_CHECK([-Wprecedence -fcaret -o input.c input.y], 0, [],
[[input.y:2.13: warning: useless precedence for Z [-Wother] [[input.y:2.1-11: warning: useless precedence for Z [-Wprecedence]
%precedence Z %precedence Z
^ ^^^^^^^^^^^
input.y:5.7: warning: useless associativity for W [-Wother] input.y:5.1-5: warning: useless precedence and associativity for W [-Wprecedence]
%left W %left W
^ ^^^^^
input.y:6.8: warning: useless associativity for V [-Wother] input.y:6.1-6: warning: useless precedence and associativity for V [-Wprecedence]
%right V %right V
^ ^^^^^^
input.y:7.11: warning: useless associativity for U [-Wother] input.y:7.1-9: warning: useless precedence and associativity for U [-Wprecedence]
%nonassoc U %nonassoc U
^ ^^^^^^^^^
]]) ]])
AT_CLEANUP AT_CLEANUP
@@ -211,7 +279,7 @@ e: 'e' | /* Nothing. */;
]]) ]])
AT_BISON_CHECK([-o input.c input.y], 0, [], AT_BISON_CHECK([-o input.c input.y], 0, [],
[[input.y:4.9: warning: rule useless in parser due to conflicts: e: /* empty */ [-Wother] [[input.y:4.9: warning: rule useless in parser due to conflicts [-Wother]
]]) ]])
AT_BISON_CHECK([-fcaret -o input.c input.y], 0, [], AT_BISON_CHECK([-fcaret -o input.c input.y], 0, [],
@@ -938,8 +1006,8 @@ cond:
]]) ]])
AT_BISON_CHECK([-o input.c input.y], 0, [], 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]
input.y:12.3-18: warning: rule useless in parser due to conflicts: cond: cond "then" cond [-Wother] input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
]]) ]])
AT_CLEANUP AT_CLEANUP
@@ -955,13 +1023,13 @@ AT_CLEANUP
# $end reduce using rule 3 (num) # $end reduce using rule 3 (num)
# $end [reduce using rule 4 (id)] # $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)] # $end [reduce using rule 4 (id)]
# $default reduce using rule 3 (num) # $default reduce using rule 3 (num)
# #
# In this precise case (a reduction is masked by the default # 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 3 (num)
# $end [reduce using rule 4 (id)] # $end [reduce using rule 4 (id)]
@@ -982,8 +1050,8 @@ id : '0';
]]) ]])
AT_BISON_CHECK([-o input.c --report=all input.y], 0, [], AT_BISON_CHECK([-o input.c --report=all input.y], 0, [],
[[input.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr] [[input.y:4.6-8: warning: rule useless in parser due to conflicts [-Wother]
input.y:4.6-8: warning: rule useless in parser due to conflicts: id: '0' [-Wother] input.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
]]) ]])
# Check the contents of the report. # Check the contents of the report.
@@ -1196,10 +1264,10 @@ e: e '+' e
; ;
]]) ]])
AT_BISON_CHECK([-o input.c input.y], 0, [], AT_BISON_CHECK([-Wall -o input.c input.y], 0, [],
[[input.y: warning: 4 shift/reduce conflicts [-Wconflicts-sr] [[input.y:1.1-5: warning: useless precedence and associativity for '+' [-Wprecedence]
input.y:1.7-9: warning: useless associativity for '+' [-Wother] input.y:2.1-5: warning: useless precedence and associativity for '*' [-Wprecedence]
input.y:2.7-9: warning: useless associativity for '*' [-Wother] input.y: warning: 4 shift/reduce conflicts [-Wconflicts-sr]
]]) ]])
AT_CLEANUP AT_CLEANUP
@@ -1301,15 +1369,15 @@ reported_conflicts:
]]) ]])
AT_BISON_CHECK([[--report=all input.y]], 0, [], AT_BISON_CHECK([[--report=all input.y]], 0, [],
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr] [[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]
input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
input.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr] input.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
input.y:12.5-20: warning: rule useless in parser due to conflicts: resolved_conflict: 'a' unreachable1 [-Wother]
input.y:20.5-20: warning: rule useless in parser due to conflicts: unreachable1: 'a' unreachable2 [-Wother]
input.y:21.4: warning: rule useless in parser due to conflicts: unreachable1: /* empty */ [-Wother]
input.y:25.13: warning: rule useless in parser due to conflicts: unreachable2: /* empty */ [-Wother]
input.y:25.16: warning: rule useless in parser due to conflicts: unreachable2: /* empty */ [-Wother]
input.y:31.5-7: warning: rule useless in parser due to conflicts: reported_conflicts: 'a' [-Wother]
input.y:32.4: warning: rule useless in parser due to conflicts: reported_conflicts: /* empty */ [-Wother]
]]) ]])
AT_CHECK([[cat input.output]], 0, AT_CHECK([[cat input.output]], 0,
@@ -1318,13 +1386,13 @@ AT_CHECK([[cat input.output]], 0,
2 resolved_conflict: 'a' unreachable1 2 resolved_conflict: 'a' unreachable1
4 unreachable1: 'a' unreachable2 4 unreachable1: 'a' unreachable2
5 | /* empty */ 5 | %empty
6 unreachable2: /* empty */ 6 unreachable2: %empty
7 | /* empty */ 7 | %empty
9 reported_conflicts: 'a' 9 reported_conflicts: 'a'
10 | /* empty */ 10 | %empty
State 4 conflicts: 1 shift/reduce State 4 conflicts: 1 shift/reduce
@@ -1338,17 +1406,17 @@ Grammar
1 start: resolved_conflict 'a' reported_conflicts 'a' 1 start: resolved_conflict 'a' reported_conflicts 'a'
2 resolved_conflict: 'a' unreachable1 2 resolved_conflict: 'a' unreachable1
3 | /* empty */ 3 | %empty
4 unreachable1: 'a' unreachable2 4 unreachable1: 'a' unreachable2
5 | /* empty */ 5 | %empty
6 unreachable2: /* empty */ 6 unreachable2: %empty
7 | /* empty */ 7 | %empty
8 reported_conflicts: 'a' 8 reported_conflicts: 'a'
9 | 'a' 9 | 'a'
10 | /* empty */ 10 | %empty
Terminals, with rules where they appear Terminals, with rules where they appear
@@ -1454,12 +1522,12 @@ AT_DATA([[input-keep.y]],
AT_CHECK([[cat input.y >> input-keep.y]]) AT_CHECK([[cat input.y >> input-keep.y]])
AT_BISON_CHECK([[input-keep.y]], 0, [], AT_BISON_CHECK([[input-keep.y]], 0, [],
[[input-keep.y: warning: 2 shift/reduce conflicts [-Wconflicts-sr] [[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]
input-keep.y: warning: 2 shift/reduce conflicts [-Wconflicts-sr]
input-keep.y: warning: 2 reduce/reduce conflicts [-Wconflicts-rr] input-keep.y: warning: 2 reduce/reduce conflicts [-Wconflicts-rr]
input-keep.y:22.4: warning: rule useless in parser due to conflicts: unreachable1: /* empty */ [-Wother]
input-keep.y:26.16: warning: rule useless in parser due to conflicts: unreachable2: /* empty */ [-Wother]
input-keep.y:32.5-7: warning: rule useless in parser due to conflicts: reported_conflicts: 'a' [-Wother]
input-keep.y:33.4: warning: rule useless in parser due to conflicts: reported_conflicts: /* empty */ [-Wother]
]]) ]])
AT_CLEANUP AT_CLEANUP
@@ -1637,9 +1705,9 @@ exp: 'a' | 'a';
]]) ]])
AT_BISON_CHECK([[2.y]], [[0]], [], AT_BISON_CHECK([[2.y]], [[0]], [],
[[2.y: warning: %expect-rr applies only to GLR parsers [-Wother] [[2.y:3.12-14: warning: rule useless in parser due to conflicts [-Wother]
2.y: warning: %expect-rr applies only to GLR parsers [-Wother]
2.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr] 2.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
2.y:3.12-14: warning: rule useless in parser due to conflicts: exp: 'a' [-Wother]
]]) ]])
AT_CLEANUP AT_CLEANUP
+156 -143
View File
@@ -403,68 +403,60 @@ dnl parses it as:
dnl dnl
dnl getline $!(4*0); dnl getline $!(4*0);
dnl 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 argument.
dnl dnl
dnl The grammar below using LALR(1) parses it as a syntax error. So does 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 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
dnl GNU AWK 3.1.2, 3.1.3, 3.1.4, and 3.1.5 parse it as: dnl GNU AWK 3.1.2, 3.1.3, 3.1.4, and 3.1.5 parse it as:
dnl dnl
dnl (getline $!4)*0; dnl (getline $!4)*0;
dnl dnl
dnl That is, like the other versions of GNU AWK, they reduce the full getline 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 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 getline rule, '*' actually is a valid lookahead. Solaris /usr/xpg4/bin/awk
dnl and the Open Group awk specification seem to agree: dnl and the Open Group awk specification seem to agree:
dnl dnl
dnl http://www.opengroup.org/pubs/online/7908799/xcu/awk.html dnl http://www.opengroup.org/pubs/online/7908799/xcu/awk.html
dnl dnl
dnl /bin/nawk and /bin/awk on Solaris 10 report it as a syntax error, but they 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, ';']], [[LEX_GETLINE, '$', '!', YNUMBER, '*', YNUMBER, ';']],
dnl BISON-STDERR dnl BISON-STDERR
[AT_COND_CASE([[canonical LR]], [[input.y:33.1-6: warning: useless associativity for ASSIGNOP, use %precedence [-Wprecedence]
[[input.y: warning: 265 shift/reduce conflicts [-Wconflicts-sr] input.y:37.1-5: warning: useless precedence and associativity for LEX_GETLINE [-Wprecedence]
input.y:19.8-16: warning: useless associativity for FUNC_CALL [-Wother] input.y:38.1-9: warning: useless associativity for LEX_IN, use %precedence [-Wprecedence]
input.y:21.8-14: warning: useless associativity for YNUMBER [-Wother] input.y:39.1-5: warning: useless associativity for FUNC_CALL, use %precedence [-Wprecedence]
input.y:21.16-22: warning: useless associativity for YSTRING [-Wother] input.y:39.1-5: warning: useless associativity for LEX_BUILTIN, use %precedence [-Wprecedence]
input.y:22.14-22: warning: useless associativity for APPEND_OP [-Wother] input.y:39.1-5: warning: useless associativity for LEX_LENGTH, use %precedence [-Wprecedence]
input.y:23.8-15: warning: useless associativity for ASSIGNOP [-Wother] input.y:40.1-9: warning: useless precedence and associativity for ',' [-Wprecedence]
input.y:23.33-41: warning: useless associativity for CONCAT_OP [-Wother] input.y:42.1-9: warning: useless precedence and associativity for APPEND_OP [-Wprecedence]
input.y:27.8-18: warning: useless associativity for LEX_GETLINE [-Wother] input.y:43.1-5: warning: useless associativity for CONCAT_OP, use %precedence [-Wprecedence]
input.y:28.8-13: warning: useless associativity for LEX_IN [-Wother] input.y:44.1-5: warning: useless associativity for YNUMBER, use %precedence [-Wprecedence]
input.y:29.23-31: warning: useless associativity for INCREMENT [-Wother] input.y:44.1-5: warning: useless associativity for YSTRING, use %precedence [-Wprecedence]
input.y:29.33-41: warning: useless associativity for DECREMENT [-Wother] input.y:47.1-6: warning: useless associativity for '!', use %precedence [-Wprecedence]
input.y:30.8-18: warning: useless associativity for LEX_BUILTIN [-Wother] input.y:47.1-6: warning: useless associativity for UNARY, use %precedence [-Wprecedence]
input.y:30.20-29: warning: useless associativity for LEX_LENGTH [-Wother] input.y:49.1-5: warning: useless associativity for INCREMENT, use %precedence [-Wprecedence]
input.y:40.11-13: warning: useless associativity for ',' [-Wother] input.y:49.1-5: warning: useless associativity for DECREMENT, use %precedence [-Wprecedence]
input.y:47.8-10: warning: useless associativity for '!' [-Wother] input.y:50.1-5: warning: useless associativity for '$', use %precedence [-Wprecedence]
input.y:47.12-16: warning: useless associativity for UNARY [-Wother] input.y:51.1-5: warning: useless associativity for '(', use %precedence [-Wprecedence]
input.y:50.7-9: warning: useless associativity for '$' [-Wother] input.y:51.1-5: warning: useless precedence and associativity for ')' [-Wprecedence]
input.y:51.7-9: warning: useless associativity for '(' [-Wother] input.y:66.10: warning: empty rule without %empty [-Wempty-rule]
input.y:51.11-13: warning: useless associativity for ')' [-Wother]]], input.y:169.8: warning: empty rule without %empty [-Wempty-rule]
[[input.y: warning: 65 shift/reduce conflicts [-Wconflicts-sr] input.y:174.12: warning: empty rule without %empty [-Wempty-rule]
input.y:19.8-16: warning: useless associativity for FUNC_CALL [-Wother] input.y:179.13: warning: empty rule without %empty [-Wempty-rule]
input.y:21.8-14: warning: useless associativity for YNUMBER [-Wother] input.y:187.15: warning: empty rule without %empty [-Wempty-rule]
input.y:21.16-22: warning: useless associativity for YSTRING [-Wother] input.y:201.8: warning: empty rule without %empty [-Wempty-rule]
input.y:22.14-22: warning: useless associativity for APPEND_OP [-Wother] input.y:206.21: warning: empty rule without %empty [-Wempty-rule]
input.y:23.8-15: warning: useless associativity for ASSIGNOP [-Wother] input.y:220.20: warning: empty rule without %empty [-Wempty-rule]
input.y:23.33-41: warning: useless associativity for CONCAT_OP [-Wother] input.y:299.13: warning: empty rule without %empty [-Wempty-rule]
input.y:27.8-18: warning: useless associativity for LEX_GETLINE [-Wother] input.y:322.9: warning: empty rule without %empty [-Wempty-rule]
input.y:28.8-13: warning: useless associativity for LEX_IN [-Wother] ]AT_COND_CASE([[canonical LR]],
input.y:29.23-31: warning: useless associativity for INCREMENT [-Wother] [[input.y: warning: 265 shift/reduce conflicts [-Wconflicts-sr]]],
input.y:29.33-41: warning: useless associativity for DECREMENT [-Wother] [[input.y: warning: 65 shift/reduce conflicts [-Wconflicts-sr]]])[
input.y:30.8-18: warning: useless associativity for LEX_BUILTIN [-Wother]
input.y:30.20-29: warning: useless associativity for LEX_LENGTH [-Wother]
input.y:40.11-13: warning: useless associativity for ',' [-Wother]
input.y:47.8-10: warning: useless associativity for '!' [-Wother]
input.y:47.12-16: warning: useless associativity for UNARY [-Wother]
input.y:50.7-9: warning: useless associativity for '$' [-Wother]
input.y:51.7-9: warning: useless associativity for '(' [-Wother]
input.y:51.11-13: warning: useless associativity for ')' [-Wother]]])[
]], ]],
dnl LAST-STATE dnl LAST-STATE
@@ -1403,23 +1395,39 @@ dnl INPUT
[[]], [[]],
dnl BISON-STDERR dnl BISON-STDERR
[AT_COND_CASE([[canonical LR]], [[input.y:53.1-6: warning: useless associativity for HASSIGN, use %precedence [-Wprecedence]
input.y:54.1-5: warning: useless associativity for HORELSE, use %precedence [-Wprecedence]
input.y:55.1-5: warning: useless associativity for HANDTHEN, use %precedence [-Wprecedence]
input.y:61.1-5: warning: useless associativity for HNOT, use %precedence [-Wprecedence]
input.y:68.1-5: warning: useless associativity for UNEAR, use %precedence [-Wprecedence]
input.y:72.1-5: warning: useless associativity for HQUA, 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]
]AT_COND_CASE([[canonical LR]],
[[input.y: warning: 1876 shift/reduce conflicts [-Wconflicts-sr] [[input.y: warning: 1876 shift/reduce conflicts [-Wconflicts-sr]
input.y: warning: 144 reduce/reduce conflicts [-Wconflicts-rr] input.y: warning: 144 reduce/reduce conflicts [-Wconflicts-rr]]],
input.y:32.9-12: warning: useless associativity for HQUA [-Wother]
input.y:53.8-14: warning: useless associativity for HASSIGN [-Wother]
input.y:54.9-15: warning: useless associativity for HORELSE [-Wother]
input.y:55.9-16: warning: useless associativity for HANDTHEN [-Wother]
input.y:61.9-12: warning: useless associativity for HNOT [-Wother]
input.y:68.7-11: warning: useless associativity for UNEAR [-Wother]]],
[[input.y: warning: 78 shift/reduce conflicts [-Wconflicts-sr] [[input.y: warning: 78 shift/reduce conflicts [-Wconflicts-sr]
input.y: warning: 10 reduce/reduce conflicts [-Wconflicts-rr] input.y: warning: 10 reduce/reduce conflicts [-Wconflicts-rr]]])[
input.y:32.9-12: warning: useless associativity for HQUA [-Wother]
input.y:53.8-14: warning: useless associativity for HASSIGN [-Wother]
input.y:54.9-15: warning: useless associativity for HORELSE [-Wother]
input.y:55.9-16: warning: useless associativity for HANDTHEN [-Wother]
input.y:61.9-12: warning: useless associativity for HNOT [-Wother]
input.y:68.7-11: warning: useless associativity for UNEAR [-Wother]]])[
]], ]],
dnl LAST-STATE dnl LAST-STATE
@@ -1585,7 +1593,7 @@ box "foo" above ljust == box ("foo" above ljust)
%left LEFT RIGHT %left LEFT RIGHT
/* Give attributes that take an optional expression a higher /* 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. */ parses properly. */
%left CHOP SOLID DASHED DOTTED UP DOWN FILL COLORED OUTLINED %left CHOP SOLID DASHED DOTTED UP DOWN FILL COLORED OUTLINED
%left LABEL %left LABEL
@@ -1598,7 +1606,7 @@ parses properly. */
/* these need to be lower than '-' */ /* these need to be lower than '-' */
%left HEIGHT RADIUS WIDTH DIAMETER FROM TO AT THICKNESS %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 */ works */
%left DOT_N DOT_E DOT_W DOT_S DOT_NE DOT_SE DOT_NW DOT_SW DOT_C %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 %left DOT_START DOT_END TOP BOTTOM LEFT_CORNER RIGHT_CORNER
@@ -2001,88 +2009,93 @@ dnl without being followed by "of".)
[[VARIABLE, '=', LABEL, LEFT, DOT_X]], [[VARIABLE, '=', LABEL, LEFT, DOT_X]],
dnl BISON-STDERR dnl BISON-STDERR
[[input.y:471.11-48: warning: rule useless in parser due to conflicts: path: ORDINAL LAST object_type relative_path [-Wother] [[input.y:137.1-5: warning: useless associativity for '.', use %precedence [-Wprecedence]
input.y:19.8-12: warning: useless associativity for LABEL [-Wother] input.y:140.1-5: warning: useless associativity for PLOT, use %precedence [-Wprecedence]
input.y:20.8-15: warning: useless associativity for VARIABLE [-Wother] input.y:141.1-5: warning: useless associativity for TEXT, use %precedence [-Wprecedence]
input.y:21.8-13: warning: useless associativity for NUMBER [-Wother] input.y:141.1-5: warning: useless associativity for SPRINTF, use %precedence [-Wprecedence]
input.y:22.8-11: warning: useless associativity for TEXT [-Wother] input.y:147.1-5: warning: useless precedence and associativity for LJUST [-Wprecedence]
input.y:25.8-14: warning: useless associativity for ORDINAL [-Wother] input.y:147.1-5: warning: useless precedence and associativity for RJUST [-Wprecedence]
input.y:30.8-11: warning: useless associativity for LAST [-Wother] input.y:147.1-5: warning: useless precedence and associativity for ABOVE [-Wprecedence]
input.y:31.8-9: warning: useless associativity for UP [-Wother] input.y:147.1-5: warning: useless precedence and associativity for BELOW [-Wprecedence]
input.y:32.8-11: warning: useless associativity for DOWN [-Wother] input.y:153.1-5: warning: useless associativity for UP, use %precedence [-Wprecedence]
input.y:35.8-10: warning: useless associativity for BOX [-Wother] input.y:153.1-5: warning: useless associativity for DOWN, use %precedence [-Wprecedence]
input.y:36.8-13: warning: useless associativity for CIRCLE [-Wother] input.y:153.1-5: warning: useless precedence and associativity for SOLID [-Wprecedence]
input.y:37.8-14: warning: useless associativity for ELLIPSE [-Wother] input.y:153.1-5: warning: useless associativity for DOTTED, use %precedence [-Wprecedence]
input.y:38.8-10: warning: useless associativity for ARC [-Wother] input.y:153.1-5: warning: useless associativity for DASHED, use %precedence [-Wprecedence]
input.y:39.8-11: warning: useless associativity for LINE [-Wother] input.y:153.1-5: warning: useless associativity for CHOP, use %precedence [-Wprecedence]
input.y:40.8-12: warning: useless associativity for ARROW [-Wother] input.y:153.1-5: warning: useless associativity for FILL, use %precedence [-Wprecedence]
input.y:42.8-13: warning: useless associativity for SPLINE [-Wother] input.y:153.1-5: warning: useless precedence and associativity for COLORED [-Wprecedence]
input.y:43.8-13: warning: useless associativity for HEIGHT [-Wother] input.y:153.1-5: warning: useless precedence and associativity for OUTLINED [-Wprecedence]
input.y:44.8-13: warning: useless associativity for RADIUS [-Wother] input.y:154.1-5: warning: useless associativity for LABEL, use %precedence [-Wprecedence]
input.y:45.8-12: warning: useless associativity for WIDTH [-Wother] input.y:156.1-5: warning: useless associativity for VARIABLE, use %precedence [-Wprecedence]
input.y:46.8-15: warning: useless associativity for DIAMETER [-Wother] input.y:156.1-5: warning: useless associativity for NUMBER, use %precedence [-Wprecedence]
input.y:47.8-11: warning: useless associativity for FROM [-Wother] input.y:156.1-5: warning: useless associativity for LAST, use %precedence [-Wprecedence]
input.y:48.8-9: warning: useless associativity for TO [-Wother] input.y:156.1-5: warning: useless associativity for SIN, use %precedence [-Wprecedence]
input.y:49.8-9: warning: useless associativity for AT [-Wother] input.y:156.1-5: warning: useless associativity for COS, use %precedence [-Wprecedence]
input.y:53.8-12: warning: useless associativity for SOLID [-Wother] input.y:156.1-5: warning: useless associativity for ATAN2, use %precedence [-Wprecedence]
input.y:54.8-13: warning: useless associativity for DOTTED [-Wother] input.y:156.1-5: warning: useless associativity for LOG, use %precedence [-Wprecedence]
input.y:55.8-13: warning: useless associativity for DASHED [-Wother] input.y:156.1-5: warning: useless associativity for EXP, use %precedence [-Wprecedence]
input.y:56.8-11: warning: useless associativity for CHOP [-Wother] input.y:156.1-5: warning: useless associativity for SQRT, use %precedence [-Wprecedence]
input.y:59.8-12: warning: useless associativity for LJUST [-Wother] input.y:156.1-5: warning: useless associativity for K_MAX, use %precedence [-Wprecedence]
input.y:60.8-12: warning: useless associativity for RJUST [-Wother] input.y:156.1-5: warning: useless associativity for K_MIN, use %precedence [-Wprecedence]
input.y:61.8-12: warning: useless associativity for ABOVE [-Wother] input.y:156.1-5: warning: useless associativity for INT, use %precedence [-Wprecedence]
input.y:62.8-12: warning: useless associativity for BELOW [-Wother] input.y:156.1-5: warning: useless associativity for RAND, use %precedence [-Wprecedence]
input.y:63.8-9: warning: useless associativity for OF [-Wother] input.y:156.1-5: warning: useless associativity for SRAND, use %precedence [-Wprecedence]
input.y:66.8-14: warning: useless associativity for BETWEEN [-Wother] input.y:156.1-5: warning: useless associativity for '(', use %precedence [-Wprecedence]
input.y:67.8-10: warning: useless associativity for AND [-Wother] input.y:157.1-5: warning: useless associativity for ORDINAL, use %precedence [-Wprecedence]
input.y:68.8-11: warning: useless associativity for HERE [-Wother] input.y:157.1-5: warning: useless associativity for HERE, use %precedence [-Wprecedence]
input.y:69.8-12: warning: useless associativity for DOT_N [-Wother] input.y:157.1-5: warning: useless associativity for '`', use %precedence [-Wprecedence]
input.y:70.8-12: warning: useless associativity for DOT_E [-Wother] input.y:159.1-5: warning: useless associativity for BOX, use %precedence [-Wprecedence]
input.y:71.8-12: warning: useless associativity for DOT_W [-Wother] input.y:159.1-5: warning: useless associativity for CIRCLE, use %precedence [-Wprecedence]
input.y:72.8-12: warning: useless associativity for DOT_S [-Wother] input.y:159.1-5: warning: useless associativity for ELLIPSE, use %precedence [-Wprecedence]
input.y:73.8-13: warning: useless associativity for DOT_NE [-Wother] input.y:159.1-5: warning: useless associativity for ARC, use %precedence [-Wprecedence]
input.y:74.8-13: warning: useless associativity for DOT_SE [-Wother] input.y:159.1-5: warning: useless associativity for LINE, use %precedence [-Wprecedence]
input.y:75.8-13: warning: useless associativity for DOT_NW [-Wother] input.y:159.1-5: warning: useless associativity for ARROW, use %precedence [-Wprecedence]
input.y:76.8-13: warning: useless associativity for DOT_SW [-Wother] input.y:159.1-5: warning: useless associativity for SPLINE, use %precedence [-Wprecedence]
input.y:77.8-12: warning: useless associativity for DOT_C [-Wother] input.y:159.1-5: warning: useless associativity for '@<:@', use %precedence [-Wprecedence]
input.y:78.8-16: warning: useless associativity for DOT_START [-Wother] input.y:162.1-5: warning: useless associativity for HEIGHT, use %precedence [-Wprecedence]
input.y:79.8-14: warning: useless associativity for DOT_END [-Wother] input.y:162.1-5: warning: useless associativity for RADIUS, use %precedence [-Wprecedence]
input.y:85.8-10: warning: useless associativity for SIN [-Wother] input.y:162.1-5: warning: useless associativity for WIDTH, use %precedence [-Wprecedence]
input.y:86.8-10: warning: useless associativity for COS [-Wother] input.y:162.1-5: warning: useless associativity for DIAMETER, use %precedence [-Wprecedence]
input.y:87.8-12: warning: useless associativity for ATAN2 [-Wother] input.y:162.1-5: warning: useless associativity for FROM, use %precedence [-Wprecedence]
input.y:88.8-10: warning: useless associativity for LOG [-Wother] input.y:162.1-5: warning: useless associativity for TO, use %precedence [-Wprecedence]
input.y:89.8-10: warning: useless associativity for EXP [-Wother] input.y:162.1-5: warning: useless associativity for AT, use %precedence [-Wprecedence]
input.y:90.8-11: warning: useless associativity for SQRT [-Wother] input.y:162.1-5: warning: useless associativity for THICKNESS, use %precedence [-Wprecedence]
input.y:91.8-12: warning: useless associativity for K_MAX [-Wother] input.y:166.1-5: warning: useless associativity for DOT_N, use %precedence [-Wprecedence]
input.y:92.8-12: warning: useless associativity for K_MIN [-Wother] input.y:166.1-5: warning: useless associativity for DOT_E, use %precedence [-Wprecedence]
input.y:93.8-10: warning: useless associativity for INT [-Wother] input.y:166.1-5: warning: useless associativity for DOT_W, use %precedence [-Wprecedence]
input.y:94.8-11: warning: useless associativity for RAND [-Wother] input.y:166.1-5: warning: useless associativity for DOT_S, use %precedence [-Wprecedence]
input.y:95.8-12: warning: useless associativity for SRAND [-Wother] input.y:166.1-5: warning: useless associativity for DOT_NE, use %precedence [-Wprecedence]
input.y:98.8-10: warning: useless associativity for TOP [-Wother] input.y:166.1-5: warning: useless associativity for DOT_SE, use %precedence [-Wprecedence]
input.y:99.8-13: warning: useless associativity for BOTTOM [-Wother] input.y:166.1-5: warning: useless associativity for DOT_NW, use %precedence [-Wprecedence]
input.y:100.8-12: warning: useless associativity for UPPER [-Wother] input.y:166.1-5: warning: useless associativity for DOT_SW, use %precedence [-Wprecedence]
input.y:101.8-12: warning: useless associativity for LOWER [-Wother] input.y:166.1-5: warning: useless associativity for DOT_C, use %precedence [-Wprecedence]
input.y:116.8-18: warning: useless associativity for LEFT_CORNER [-Wother] input.y:167.1-5: warning: useless associativity for DOT_START, use %precedence [-Wprecedence]
input.y:117.8-19: warning: useless associativity for RIGHT_CORNER [-Wother] input.y:167.1-5: warning: useless associativity for DOT_END, use %precedence [-Wprecedence]
input.y:118.8-12: warning: useless associativity for NORTH [-Wother] input.y:167.1-5: warning: useless associativity for TOP, use %precedence [-Wprecedence]
input.y:119.8-12: warning: useless associativity for SOUTH [-Wother] input.y:167.1-5: warning: useless associativity for BOTTOM, use %precedence [-Wprecedence]
input.y:120.8-11: warning: useless associativity for EAST [-Wother] input.y:167.1-5: warning: useless associativity for LEFT_CORNER, use %precedence [-Wprecedence]
input.y:121.8-11: warning: useless associativity for WEST [-Wother] input.y:167.1-5: warning: useless associativity for RIGHT_CORNER, use %precedence [-Wprecedence]
input.y:122.8-13: warning: useless associativity for CENTER [-Wother] input.y:168.1-5: warning: useless associativity for UPPER, use %precedence [-Wprecedence]
input.y:123.8-10: warning: useless associativity for END [-Wother] input.y:168.1-5: warning: useless associativity for LOWER, use %precedence [-Wprecedence]
input.y:124.8-12: warning: useless associativity for START [-Wother] input.y:168.1-5: warning: useless associativity for NORTH, use %precedence [-Wprecedence]
input.y:127.8-11: warning: useless associativity for PLOT [-Wother] input.y:168.1-5: warning: useless associativity for SOUTH, use %precedence [-Wprecedence]
input.y:128.8-16: warning: useless associativity for THICKNESS [-Wother] input.y:168.1-5: warning: useless associativity for EAST, use %precedence [-Wprecedence]
input.y:129.8-11: warning: useless associativity for FILL [-Wother] input.y:168.1-5: warning: useless associativity for WEST, use %precedence [-Wprecedence]
input.y:130.8-14: warning: useless associativity for COLORED [-Wother] input.y:168.1-5: warning: useless associativity for CENTER, use %precedence [-Wprecedence]
input.y:131.8-15: warning: useless associativity for OUTLINED [-Wother] input.y:168.1-5: warning: useless associativity for END, use %precedence [-Wprecedence]
input.y:134.8-14: warning: useless associativity for SPRINTF [-Wother] input.y:168.1-5: warning: useless associativity for START, use %precedence [-Wprecedence]
input.y:137.7-9: warning: useless associativity for '.' [-Wother] input.y:170.1-5: warning: useless associativity for ',', use %precedence [-Wprecedence]
input.y:156.23-25: warning: useless associativity for '(' [-Wother] input.y:176.1-5: warning: useless associativity for OF, use %precedence [-Wprecedence]
input.y:157.20-22: warning: useless associativity for '`' [-Wother] input.y:176.1-5: warning: useless associativity for BETWEEN, use %precedence [-Wprecedence]
input.y:159.48-50: warning: useless associativity for '@<:@' [-Wother] input.y:177.1-5: warning: useless associativity for AND, use %precedence [-Wprecedence]
input.y:170.7-9: warning: useless associativity for ',' [-Wother] input.y:181.1-6: warning: useless associativity for '!', use %precedence [-Wprecedence]
input.y:181.8-10: warning: useless associativity for '!' [-Wother] 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]
]], ]],
dnl LAST-STATE dnl LAST-STATE
+6 -6
View File
@@ -486,8 +486,8 @@ start:
; ;
%% %%
]AT_YYLEX_DEFINE(["a"])[
]AT_YYERROR_DEFINE[ ]AT_YYERROR_DEFINE[
]AT_YYLEX_DEFINE(["a"])[
]AT_MAIN_DEFINE[ ]AT_MAIN_DEFINE[
]]) ]])
AT_BISON_OPTION_POPDEFS AT_BISON_OPTION_POPDEFS
@@ -1015,17 +1015,17 @@ main (void)
int exit_status = yyparse (); int exit_status = yyparse ();
if (parent_rhs_before_value) 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; exit_status = 1;
} }
if (merged_value) if (merged_value)
{ {
fprintf (stderr, "`merged' destructor not called.\n"); fprintf (stderr, "'merged' destructor not called.\n");
exit_status = 1; exit_status = 1;
} }
if (parent_rhs_after_value) 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; exit_status = 1;
} }
return exit_status; return exit_status;
@@ -1449,7 +1449,7 @@ main (void)
int exit_status = yyparse () != 1; int exit_status = yyparse () != 1;
if (parent_rhs_before_value) 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; exit_status = 1;
} }
return exit_status; return exit_status;
@@ -1679,8 +1679,8 @@ start:
b: 'b'; b: 'b';
d: /* nada. */; d: /* nada. */;
%% %%
]AT_YYLEX_DEFINE(["abc"])[
]AT_YYERROR_DEFINE[ ]AT_YYERROR_DEFINE[
]AT_YYLEX_DEFINE(["abc"])[
]AT_MAIN_DEFINE[ ]AT_MAIN_DEFINE[
]]) ]])
AT_BISON_OPTION_POPDEFS AT_BISON_OPTION_POPDEFS
+2 -2
View File
@@ -117,9 +117,9 @@ AT_SETUP([Several parsers])
# nor yy* identifiers in the header. Check that headers are # nor yy* identifiers in the header. Check that headers are
# self-contained, and can be compiled by a C++ compiler. # self-contained, and can be compiled by a C++ compiler.
m4_pushdef([AT_TEST], m4_pushdef([AT_TEST],
[AT_BISON_OPTION_PUSHDEFS([%define api.prefix "$1_" $2]) [AT_BISON_OPTION_PUSHDEFS([%define api.prefix {$1_} $2])
AT_DATA_GRAMMAR([$1.y], AT_DATA_GRAMMAR([$1.y],
[[%define api.prefix "$1_" [[%define api.prefix {$1_}
$2 $2
%error-verbose %error-verbose
%union %union
+281 -190
View File
@@ -20,6 +20,29 @@ AT_BANNER([[Input Processing.]])
# Mostly test that we are robust to mistakes. # 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. ## ## Invalid inputs. ##
## ---------------- ## ## ---------------- ##
@@ -85,17 +108,17 @@ AT_SETUP([Invalid $n and @n])
AT_DATA([input.y], AT_DATA([input.y],
[[%% [[%%
exp: { $$ = $1 ; }; exp: %empty { $$ = $1 ; };
exp: { @$ = @1 ; }; exp: %empty { @$ = @1 ; };
]]) ]])
AT_BISON_CHECK([-fcaret input.y], [1], [], AT_BISON_CHECK([-fcaret input.y], [1], [],
[[input.y:2.13-14: error: integer out of range: '$1' [[input.y:2.20-21: error: integer out of range: '$1'
exp: { $$ = $1 ; }; exp: %empty { $$ = $1 ; };
^^ ^^
input.y:3.13-14: error: integer out of range: '@1' input.y:3.20-21: error: integer out of range: '@1'
exp: { @$ = @1 ; }; exp: %empty { @$ = @1 ; };
^^ ^^
]]) ]])
AT_CLEANUP AT_CLEANUP
@@ -114,26 +137,26 @@ AT_DATA([input.y],
%% %%
exp: foo { $$; } foo { $2; } foo exp: foo { $$; } foo { $2; } foo
| foo | foo
| /* empty. */ | %empty
; ;
]]) ]])
AT_BISON_CHECK([-fcaret 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 [[input.y:5.6-32: warning: type clash on default action: <bar> != <> [-Wother]
exp: foo { $$; } foo { $2; } foo
^^^^^^^^^^^^^^^^^^^^^^^^^^^
input.y:5.12-13: error: $$ for the midrule at $2 of 'exp' has no declared type
exp: foo { $$; } foo { $2; } foo exp: foo { $$; } foo { $2; } foo
^^ ^^
input.y:5.24-25: error: $2 of 'exp' has no declared type input.y:5.24-25: error: $2 of 'exp' has no declared type
exp: foo { $$; } foo { $2; } foo 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] input.y:6.6-8: warning: type clash on default action: <bar> != <> [-Wother]
| foo | foo
^^^ ^^^
input.y:7.5: warning: empty rule for typed nonterminal, and no action [-Wother] input.y:7.6-11: warning: empty rule for typed nonterminal, and no action [-Wother]
| /* empty. */ | %empty
^ ^^^^^^
]]) ]])
AT_CLEANUP AT_CLEANUP
@@ -169,7 +192,7 @@ start:
; ;
a: INT | INT { } INT { } INT { }; a: INT | INT { } INT { } INT { };
b: INT | /* empty */; b: INT | %empty;
c: INT | INT { $]1[; } INT { $<integer>2; } INT { $<integer>4; }; c: INT | INT { $]1[; } INT { $<integer>2; } INT { $<integer>4; };
d: INT | INT { } INT { $]1[; } INT { $<integer>2; }; d: INT | INT { } INT { $]1[; } INT { $<integer>2; };
e: INT | INT { } INT { } INT { $]1[; }; e: INT | INT { } INT { } INT { $]1[; };
@@ -185,43 +208,43 @@ _AT_UNUSED_VALUES_DECLARATIONS])
AT_BISON_CHECK(m4_ifval($2, [--warnings=midrule-values ])[-fcaret input.y], AT_BISON_CHECK(m4_ifval($2, [--warnings=midrule-values ])[-fcaret input.y],
[0], [], [0], [],
[[input.y:11.10-32: warning: unset value: $][$ [-Wother] [[input.y:11.10-12: warning: unused value: $][1 [-Wother]
a: INT | INT { } INT { } INT { };
^^^^^^^^^^^^^^^^^^^^^^^
input.y:11.10-12: warning: unused value: $][1 [-Wother]
a: INT | INT { } INT { } INT { }; a: INT | INT { } INT { } INT { };
^^^ ^^^
input.y:11.10-32: warning: unset value: $][$ [-Wother]
a: INT | INT { } INT { } INT { };
^^^^^^^^^^^^^^^^^^^^^^^
input.y:11.18-20: warning: unused value: $][3 [-Wother] input.y:11.18-20: warning: unused value: $][3 [-Wother]
a: INT | INT { } INT { } INT { }; a: INT | INT { } INT { } INT { };
^^^ ^^^
input.y:11.26-28: warning: unused value: $][5 [-Wother] input.y:11.26-28: warning: unused value: $][5 [-Wother]
a: INT | INT { } INT { } INT { }; a: INT | INT { } INT { } INT { };
^^^ ^^^
input.y:12.9: warning: empty rule for typed nonterminal, and no action [-Wother] input.y:12.10-15: warning: empty rule for typed nonterminal, and no action [-Wother]
b: INT | /* empty */; b: INT | %empty;
^ ^^^^^^
input.y:13.10-62: warning: unset value: $][$ [-Wother]
c: INT | INT { $][1; } INT { $<integer>2; } INT { $<integer>4; };
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
]]m4_ifval($2, [[[input.y:13.14-20: warning: unset value: $][$ [-Wmidrule-values] ]]m4_ifval($2, [[[input.y:13.14-20: warning: unset value: $][$ [-Wmidrule-values]
c: INT | INT { $][1; } INT { $<integer>2; } INT { $<integer>4; }; c: INT | INT { $][1; } INT { $<integer>2; } INT { $<integer>4; };
^^^^^^^ ^^^^^^^
input.y:13.26-41: warning: unset value: $][$ [-Wmidrule-values] ]]])[[input.y:13.22-24: warning: unused value: $][3 [-Wother]
c: INT | INT { $][1; } INT { $<integer>2; } INT { $<integer>4; };
^^^^^^^^^^^^^^^^
]]])[[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 [-Wother]
c: INT | INT { $][1; } INT { $<integer>2; } INT { $<integer>4; }; c: INT | INT { $][1; } INT { $<integer>2; } INT { $<integer>4; };
^^^ ^^^
input.y:13.43-45: warning: unused value: $][5 [-Wother] ]]m4_ifval($2, [[[input.y:13.26-41: warning: unset value: $][$ [-Wmidrule-values]
c: INT | INT { $][1; } INT { $<integer>2; } INT { $<integer>4; };
^^^^^^^^^^^^^^^^
]]])[[input.y:13.43-45: warning: unused value: $][5 [-Wother]
c: INT | INT { $][1; } INT { $<integer>2; } INT { $<integer>4; }; c: INT | INT { $][1; } INT { $<integer>2; } INT { $<integer>4; };
^^^ ^^^
input.y:14.10-49: warning: unset value: $][$ [-Wother]
d: INT | INT { } INT { $][1; } INT { $<integer>2; };
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
]]m4_ifval($2, [[[input.y:14.14-16: warning: unset value: $][$ [-Wmidrule-values] ]]m4_ifval($2, [[[input.y:14.14-16: warning: unset value: $][$ [-Wmidrule-values]
d: INT | INT { } INT { $][1; } INT { $<integer>2; }; d: INT | INT { } INT { $][1; } INT { $<integer>2; };
^^^ ^^^
]]])[[input.y:14.10-49: warning: unset value: $][$ [-Wother] ]]])[[input.y:14.18-20: warning: unused value: $][3 [-Wother]
d: INT | INT { } INT { $][1; } INT { $<integer>2; };
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
input.y:14.18-20: warning: unused value: $][3 [-Wother]
d: INT | INT { } INT { $][1; } INT { $<integer>2; }; d: INT | INT { } INT { $][1; } INT { $<integer>2; };
^^^ ^^^
input.y:14.30-32: warning: unused value: $][5 [-Wother] input.y:14.30-32: warning: unused value: $][5 [-Wother]
@@ -236,12 +259,12 @@ input.y:15.18-20: warning: unused value: $][3 [-Wother]
input.y:15.27-29: warning: unused value: $][5 [-Wother] input.y:15.27-29: warning: unused value: $][5 [-Wother]
e: INT | INT { } INT { } INT { $][1; }; e: INT | INT { } INT { } INT { $][1; };
^^^ ^^^
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 [-Wother] input.y:17.10-12: warning: unused value: $][1 [-Wother]
g: INT | INT { $<integer>$; } INT { $<integer>$; } INT { }; g: INT | INT { $<integer>$; } INT { $<integer>$; } INT { };
^^^ ^^^
input.y:17.10-58: warning: unset value: $][$ [-Wother]
g: INT | INT { $<integer>$; } INT { $<integer>$; } INT { };
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
]]m4_ifval($2, [[[input.y:17.14-29: warning: unused value: $][2 [-Wmidrule-values] ]]m4_ifval($2, [[[input.y:17.14-29: warning: unused value: $][2 [-Wmidrule-values]
g: INT | INT { $<integer>$; } INT { $<integer>$; } INT { }; g: INT | INT { $<integer>$; } INT { $<integer>$; } INT { };
^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^
@@ -254,12 +277,12 @@ input.y:17.10-12: warning: unused value: $][1 [-Wother]
]]])[[input.y:17.52-54: warning: unused value: $][5 [-Wother] ]]])[[input.y:17.52-54: warning: unused value: $][5 [-Wother]
g: INT | INT { $<integer>$; } INT { $<integer>$; } INT { }; g: INT | INT { $<integer>$; } INT { $<integer>$; } INT { };
^^^ ^^^
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 [-Wother] input.y:18.10-12: warning: unused value: $][1 [-Wother]
h: INT | INT { $<integer>$; } INT { $<integer>$ = $<integer>2; } INT { }; h: INT | INT { $<integer>$; } INT { $<integer>$ = $<integer>2; } INT { };
^^^ ^^^
input.y:18.10-72: warning: unset value: $][$ [-Wother]
h: INT | INT { $<integer>$; } INT { $<integer>$ = $<integer>2; } INT { };
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
input.y:18.31-33: warning: unused value: $][3 [-Wother] input.y:18.31-33: warning: unused value: $][3 [-Wother]
h: INT | INT { $<integer>$; } INT { $<integer>$ = $<integer>2; } INT { }; h: INT | INT { $<integer>$; } INT { $<integer>$ = $<integer>2; } INT { };
^^^ ^^^
@@ -272,12 +295,12 @@ input.y:18.31-33: warning: unused value: $][3 [-Wother]
]]m4_ifval($2, [[[input.y:20.18-37: warning: unused value: $][3 [-Wmidrule-values] ]]m4_ifval($2, [[[input.y:20.18-37: warning: unused value: $][3 [-Wmidrule-values]
j: INT | INT INT { $<integer>$ = 1; } { $][$ = $][1 + $][2; }; j: INT | INT INT { $<integer>$ = 1; } { $][$ = $][1 + $][2; };
^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^
]]])[[input.y:21.10-68: warning: unset value: $][$ [-Wother] ]]])[[input.y:21.10-12: warning: unused value: $][1 [-Wother]
k: INT | INT INT { $<integer>$; } { $<integer>$ = $<integer>3; } { };
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
input.y:21.10-12: warning: unused value: $][1 [-Wother]
k: INT | INT INT { $<integer>$; } { $<integer>$ = $<integer>3; } { }; k: INT | INT INT { $<integer>$; } { $<integer>$ = $<integer>3; } { };
^^^ ^^^
input.y:21.10-68: warning: unset value: $][$ [-Wother]
k: INT | INT INT { $<integer>$; } { $<integer>$ = $<integer>3; } { };
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
input.y:21.14-16: warning: unused value: $][2 [-Wother] input.y:21.14-16: warning: unused value: $][2 [-Wother]
k: INT | INT INT { $<integer>$; } { $<integer>$ = $<integer>3; } { }; k: INT | INT INT { $<integer>$; } { $<integer>$ = $<integer>3; } { };
^^^ ^^^
@@ -313,104 +336,67 @@ AT_CLEANUP
AT_SETUP([Default %printer and %destructor redeclared]) AT_SETUP([Default %printer and %destructor redeclared])
AT_DATA([[input.y]], # AT_TEST([*])
[[%destructor { destroy ($$); } <*> <*> # ------------
%printer { print ($$); } <*> <*> m4_pushdef([AT_TEST],
[AT_DATA([[input.y]],
[[%destructor { destroy ($$); } <$1> <$1>
%printer { print ($$); } <$1> <$1>
%destructor { destroy ($$); } <*> %destructor { destroy ($$); } <$1>
%printer { print ($$); } <*> %printer { print ($$); } <$1>
%destructor { destroy ($$); } <> <>
%printer { print ($$); } <> <>
%destructor { destroy ($$); } <>
%printer { print ($$); } <>
%% %%
start: ; start: %empty;
%destructor { destroy ($$); } <*>; %destructor { destroy ($$); } <$1>;
%printer { print ($$); } <*>; %printer { print ($$); } <$1>;
%destructor { destroy ($$); } <>;
%printer { print ($$); } <>;
]]) ]])
AT_BISON_CHECK([-fcaret input.y], [1], [], AT_BISON_CHECK([-fcaret input.y], [1], [],
[[input.y:1.13-29: error: %destructor redeclaration for <*> [[input.y:1.13-29: error: %destructor redeclaration for <>
%destructor { destroy ($$); } <*> <*>
^^^^^^^^^^^^^^^^^
input.y:1.13-29: previous declaration
%destructor { destroy ($$); } <*> <*>
^^^^^^^^^^^^^^^^^
input.y:2.10-24: error: %printer redeclaration for <*>
%printer { print ($$); } <*> <*>
^^^^^^^^^^^^^^^
input.y:2.10-24: previous declaration
%printer { print ($$); } <*> <*>
^^^^^^^^^^^^^^^
input.y:4.13-29: error: %destructor redeclaration for <*>
%destructor { destroy ($$); } <*>
^^^^^^^^^^^^^^^^^
input.y:1.13-29: previous declaration
%destructor { destroy ($$); } <*> <*>
^^^^^^^^^^^^^^^^^
input.y:5.10-24: error: %printer redeclaration for <*>
%printer { print ($$); } <*>
^^^^^^^^^^^^^^^
input.y:2.10-24: previous declaration
%printer { print ($$); } <*> <*>
^^^^^^^^^^^^^^^
input.y:7.13-29: error: %destructor redeclaration for <>
%destructor { destroy ($$); } <> <> %destructor { destroy ($$); } <> <>
^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^
input.y:7.13-29: previous declaration input.y:1.13-29: previous declaration
%destructor { destroy ($$); } <> <> %destructor { destroy ($$); } <> <>
^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^
input.y:8.10-24: error: %printer redeclaration for <> input.y:2.10-24: error: %printer redeclaration for <>
%printer { print ($$); } <> <> %printer { print ($$); } <> <>
^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
input.y:8.10-24: previous declaration input.y:2.10-24: previous declaration
%printer { print ($$); } <> <> %printer { print ($$); } <> <>
^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
input.y:10.13-29: error: %destructor redeclaration for <> input.y:4.13-29: error: %destructor redeclaration for <>
%destructor { destroy ($$); } <> %destructor { destroy ($$); } <>
^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^
input.y:7.13-29: previous declaration input.y:1.13-29: previous declaration
%destructor { destroy ($$); } <> <> %destructor { destroy ($$); } <> <>
^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^
input.y:11.10-24: error: %printer redeclaration for <> input.y:5.10-24: error: %printer redeclaration for <>
%printer { print ($$); } <> %printer { print ($$); } <>
^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
input.y:8.10-24: previous declaration input.y:2.10-24: previous declaration
%printer { print ($$); } <> <> %printer { print ($$); } <> <>
^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
input.y:17.13-29: error: %destructor redeclaration for <*> input.y:11.13-29: error: %destructor redeclaration for <>
%destructor { destroy ($$); } <*>;
^^^^^^^^^^^^^^^^^
input.y:4.13-29: previous declaration
%destructor { destroy ($$); } <*>
^^^^^^^^^^^^^^^^^
input.y:18.10-24: error: %printer redeclaration for <*>
%printer { print ($$); } <*>;
^^^^^^^^^^^^^^^
input.y:5.10-24: previous declaration
%printer { print ($$); } <*>
^^^^^^^^^^^^^^^
input.y:20.13-29: error: %destructor redeclaration for <>
%destructor { destroy ($$); } <>; %destructor { destroy ($$); } <>;
^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^
input.y:10.13-29: previous declaration input.y:1.13-29: previous declaration
%destructor { destroy ($$); } <> %destructor { destroy ($$); } <> <>
^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^
input.y:21.10-24: error: %printer redeclaration for <> input.y:12.10-24: error: %printer redeclaration for <>
%printer { print ($$); } <>; %printer { print ($$); } <>;
^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
input.y:11.10-24: previous declaration input.y:2.10-24: previous declaration
%printer { print ($$); } <> %printer { print ($$); } <> <>
^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
]]) ]])
])
AT_TEST([], [], [])
AT_TEST([], [*], [*])
m4_popdef([AT_TEST])
AT_CLEANUP AT_CLEANUP
@@ -430,7 +416,7 @@ AT_DATA([[input.y]],
%% %%
start: ; start: %empty;
%destructor { destroy ($$); } <field2> <field1>; %destructor { destroy ($$); } <field2> <field1>;
%printer { print ($$); } <field2> <field1>; %printer { print ($$); } <field2> <field1>;
@@ -440,17 +426,17 @@ AT_BISON_CHECK([input.y], [1], [],
[[input.y:4.13-29: error: %destructor redeclaration for <field1> [[input.y:4.13-29: error: %destructor redeclaration for <field1>
input.y:1.13-29: previous declaration input.y:1.13-29: previous declaration
input.y:4.13-29: error: %destructor redeclaration for <field1> input.y:4.13-29: error: %destructor redeclaration for <field1>
input.y:4.13-29: previous declaration input.y:1.13-29: previous declaration
input.y:5.10-24: error: %printer redeclaration for <field2> input.y:5.10-24: error: %printer redeclaration for <field2>
input.y:2.10-24: previous declaration input.y:2.10-24: previous declaration
input.y:5.10-24: error: %printer redeclaration for <field2> input.y:5.10-24: error: %printer redeclaration for <field2>
input.y:5.10-24: previous declaration input.y:2.10-24: previous declaration
input.y:11.13-29: error: %destructor redeclaration for <field2> input.y:11.13-29: error: %destructor redeclaration for <field2>
input.y:1.13-29: previous declaration input.y:1.13-29: previous declaration
input.y:11.13-29: error: %destructor redeclaration for <field1> input.y:11.13-29: error: %destructor redeclaration for <field1>
input.y:4.13-29: previous declaration input.y:1.13-29: previous declaration
input.y:12.10-24: error: %printer redeclaration for <field2> input.y:12.10-24: error: %printer redeclaration for <field2>
input.y:5.10-24: previous declaration input.y:2.10-24: previous declaration
input.y:12.10-24: error: %printer redeclaration for <field1> input.y:12.10-24: error: %printer redeclaration for <field1>
input.y:2.10-24: previous declaration input.y:2.10-24: previous declaration
]]) ]])
@@ -472,15 +458,15 @@ exp: bar;
]]) ]])
AT_BISON_CHECK([-fcaret input.y], [1], [], 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 [[input.y:1.13-15: warning: symbol foo is used, but is not defined as a token and has no rules [-Wother]
%destructor {} bar %printer {} foo baz
^^^ ^^^
input.y:1.17-19: warning: symbol baz is used, but is not defined as a token and has no rules [-Wother] input.y:1.17-19: warning: symbol baz is used, but is not defined as a token and has no rules [-Wother]
%printer {} foo baz %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] input.y:2.16-18: error: symbol bar is used, but is not defined as a token and has no rules
%printer {} foo baz %destructor {} bar
^^^ ^^^
input.y:3.13-15: warning: symbol qux is used, but is not defined as a token and has no rules [-Wother] 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 %type <foo> qux
^^^ ^^^
@@ -686,25 +672,25 @@ exp: foo;
]]) ]])
AT_BISON_CHECK([-fcaret input.y], [1], [], AT_BISON_CHECK([-fcaret input.y], [1], [],
[[input.y:8.7-11: error: %type redeclaration for foo [[input.y:8.7-11: error: %type redeclaration for "foo"
%type <baz> "foo" %type <baz> "foo"
^^^^^ ^^^^^
input.y:3.7-11: previous declaration input.y:3.7-11: previous declaration
%type <bar> foo %type <bar> foo
^^^^^ ^^^^^
input.y:10.13-17: error: %destructor redeclaration for foo input.y:9.10-14: error: %printer 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" %printer {baz} "foo"
^^^^^ ^^^^^
input.y:4.10-14: previous declaration input.y:4.10-14: previous declaration
%printer {bar} foo %printer {bar} foo
^^^^^ ^^^^^
input.y:11.1-5: error: %left redeclaration for 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:11.1-5: error: %left redeclaration for "foo"
%left "foo" %left "foo"
^^^^^ ^^^^^
input.y:6.1-5: previous declaration input.y:6.1-5: previous declaration
@@ -826,7 +812,7 @@ exp: '@<:@' '\1' two '$' '@' '{' oline output.or.oline.opt
two: '\x000000000000000000000000000000000000000000000000000000000000000000002'; two: '\x000000000000000000000000000000000000000000000000000000000000000000002';
oline: '@' 'o' 'l' 'i' 'n' 'e' '@' '_' '_' 'o' 'l' 'i' 'n' 'e' '_' '_'; 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' ' '; output: '#' 'o' 'u' 't' 'p' 'u' 't' ' ';
%% %%
/* Exercise M4 quoting: '@:>@@:>@', @<:@, 2. */ /* Exercise M4 quoting: '@:>@@:>@', @<:@, 2. */
@@ -908,7 +894,7 @@ m4_define([AT_CHECK_REQUIRE],
AT_DATA_GRAMMAR([input.y], AT_DATA_GRAMMAR([input.y],
[[%require "$1"; [[%require "$1";
%% %%
empty_file: /* empty */; empty_file: %empty;
]]) ]])
AT_BISON_CHECK([-o input.c input.y], $2, [], ignore) AT_BISON_CHECK([-o input.c input.y], $2, [], ignore)
AT_CLEANUP AT_CLEANUP
@@ -1066,7 +1052,7 @@ AT_DATA([input.y],
%% %%
start: ; start: %empty;
// Used to report a syntax error because it didn't see any kind of symbol // Used to report a syntax error because it didn't see any kind of symbol
// identifier. // identifier.
@@ -1111,7 +1097,7 @@ AT_SETUP([%start after first rule])
AT_DATA([input.y], AT_DATA([input.y],
[[%% [[%%
false_start: ; false_start: %empty;
start: false_start ; start: false_start ;
%start start; %start start;
]]) ]])
@@ -1132,7 +1118,7 @@ AT_SETUP([%prec takes a token])
AT_DATA([input.y], AT_DATA([input.y],
[[%% [[%%
start: PREC %prec PREC ; start: PREC %prec PREC ;
PREC: ; PREC: %empty;
]]) ]])
AT_BISON_CHECK([input.y], [1], [], AT_BISON_CHECK([input.y], [1], [],
@@ -1174,7 +1160,7 @@ AT_DATA([input-c.y],
%code bad {} %code bad {}
%code format {} %code format {}
%% %%
start: ; start: %empty;
]]) ]])
AT_BISON_CHECK([[input-c.y]], [[1]], [], AT_BISON_CHECK([[input-c.y]], [[1]], [],
[[input-c.y:1.7: error: %code qualifier 'q' is not used [[input-c.y:1.7: error: %code qualifier 'q' is not used
@@ -1188,7 +1174,7 @@ AT_DATA([input-c-glr.y],
%code bad {} %code bad {}
%code bad {} %code bad {}
%% %%
start: ; start: %empty;
]]) ]])
AT_BISON_CHECK([[input-c-glr.y]], [[1]], [], AT_BISON_CHECK([[input-c-glr.y]], [[1]], [],
[[input-c-glr.y:1.7: error: %code qualifier 'q' is not used [[input-c-glr.y:1.7: error: %code qualifier 'q' is not used
@@ -1201,7 +1187,7 @@ AT_DATA([input-c++.y],
%code bad {} %code bad {}
%code q {} %code q {}
%% %%
start: ; start: %empty;
]]) ]])
AT_BISON_CHECK([[input-c++.y]], [[1]], [], AT_BISON_CHECK([[input-c++.y]], [[1]], [],
[[input-c++.y:1.7: error: %code qualifier 'q' is not used [[input-c++.y:1.7: error: %code qualifier 'q' is not used
@@ -1214,7 +1200,7 @@ AT_DATA([input-c++-glr.y],
%code q {} %code q {}
%code q {} %code q {}
%% %%
start: ; start: %empty;
]]) ]])
AT_BISON_CHECK([[input-c++-glr.y]], [[1]], [], AT_BISON_CHECK([[input-c++-glr.y]], [[1]], [],
[[input-c++-glr.y:1.7-9: error: %code qualifier 'bad' is not used [[input-c++-glr.y:1.7-9: error: %code qualifier 'bad' is not used
@@ -1227,7 +1213,7 @@ AT_DATA([special-char-@@.y],
%code q {} %code q {}
%code q {} %code q {}
%% %%
start: ; start: %empty;
]]) ]])
AT_BISON_CHECK([[special-char-@@.y]], [[1]], [], AT_BISON_CHECK([[special-char-@@.y]], [[1]], [],
[[special-char-@@.y:1.7-9: error: %code qualifier 'bad' is not used [[special-char-@@.y:1.7-9: error: %code qualifier 'bad' is not used
@@ -1240,7 +1226,7 @@ AT_DATA([special-char-@:>@.y],
%code q {} %code q {}
%code q {} %code q {}
%% %%
start: ; start: %empty;
]]) ]])
AT_BISON_CHECK([[special-char-@:>@.y]], [[1]], [], AT_BISON_CHECK([[special-char-@:>@.y]], [[1]], [],
[[special-char-@:>@.y:1.7-9: error: %code qualifier 'bad' is not used [[special-char-@:>@.y:1.7-9: error: %code qualifier 'bad' is not used
@@ -1251,6 +1237,45 @@ special-char-@:>@.y:3.7: error: %code qualifier 'q' is not used
AT_CLEANUP AT_CLEANUP
## ---------------- ##
## Multiple %code. ##
## ---------------- ##
AT_SETUP([Multiple %code])
# Make sure that repeated arguments to %code are separated by
# end-of-lines. At some point, a missing eol would leave synclines
# appended to the previous value. Here, we use CPP directive to
# introduce dependency on the absence/presence of the eol.
AT_BISON_OPTION_PUSHDEFS
AT_DATA([input.y],
[[%code {#include <assert.h>}
%code {#define A B}
%code {#define B C}
%code {#define C D}
%code {#define D 42}
%code {
]AT_YYERROR_DECLARE[
]AT_YYLEX_DECLARE[
}
%%
start: %empty;
%%
]AT_YYERROR_DEFINE[
]AT_YYLEX_DEFINE[
int main (void)
{
assert (A == 42);
return 0;
}
]])
AT_FULL_COMPILE([input])
AT_PARSER_CHECK([./input])
AT_BISON_OPTION_POPDEFS
AT_CLEANUP()
## ---------------- ## ## ---------------- ##
## %define errors. ## ## %define errors. ##
## ---------------- ## ## ---------------- ##
@@ -1264,7 +1289,7 @@ AT_DATA([input-redefined.y],
%define special1 "@:>@" %define special1 "@:>@"
%define special2 "@<:@" %define special2 "@<:@"
%% %%
start: ; start: %empty;
]]) ]])
AT_BISON_CHECK([[input-redefined.y]], [[1]], [], AT_BISON_CHECK([[input-redefined.y]], [[1]], [],
@@ -1277,7 +1302,7 @@ input-redefined.y:2.9-11: previous definition
AT_DATA([input-unused.y], AT_DATA([input-unused.y],
[[%define var "value" [[%define var "value"
%% %%
start: ; start: %empty;
]]) ]])
AT_BISON_CHECK([[input-unused.y]], [[1]], [], AT_BISON_CHECK([[input-unused.y]], [[1]], [],
@@ -1305,7 +1330,7 @@ m4@&t@_divert_pop(0)
AT_DATA([[input.y]], AT_DATA([[input.y]],
[[%define var-dfg "gram" [[%define var-dfg "gram"
%% %%
start: ; start: %empty;
]]) ]])
AT_BISON_CHECK([[-Dvar-dd=cmd-d1 -Dvar-dd=cmd-d2 \ AT_BISON_CHECK([[-Dvar-dd=cmd-d1 -Dvar-dd=cmd-d2 \
-Fvar-ff=cmd-f1 -Fvar-ff=cmd-f2 \ -Fvar-ff=cmd-f1 -Fvar-ff=cmd-f2 \
@@ -1322,7 +1347,7 @@ var-fd: cmd-d
AT_DATA([[input-dg.y]], AT_DATA([[input-dg.y]],
[[%define var "gram" [[%define var "gram"
%% %%
start: ; start: %empty;
]]) ]])
AT_BISON_CHECK([[-Dvar=cmd-d input-dg.y]], [[1]], [], AT_BISON_CHECK([[-Dvar=cmd-d input-dg.y]], [[1]], [],
[[input-dg.y:1.9-11: error: %define variable 'var' redefined [[input-dg.y:1.9-11: error: %define variable 'var' redefined
@@ -1332,7 +1357,7 @@ AT_BISON_CHECK([[-Dvar=cmd-d input-dg.y]], [[1]], [],
AT_DATA([[input-dg.y]], AT_DATA([[input-dg.y]],
[[%define var "gram" [[%define var "gram"
%% %%
start: ; start: %empty;
]]) ]])
AT_BISON_CHECK([[-fcaret -Dvar=cmd-d input-dg.y]], [[1]], [], AT_BISON_CHECK([[-fcaret -Dvar=cmd-d input-dg.y]], [[1]], [],
[[input-dg.y:1.9-11: error: %define variable 'var' redefined [[input-dg.y:1.9-11: error: %define variable 'var' redefined
@@ -1343,7 +1368,7 @@ AT_BISON_CHECK([[-fcaret -Dvar=cmd-d input-dg.y]], [[1]], [],
AT_DATA([[input-unused.y]], AT_DATA([[input-unused.y]],
[[%% [[%%
start: ; start: %empty;
]]) ]])
AT_BISON_CHECK([[-Dunused-d -Funused-f input-unused.y]], [[1]], [], AT_BISON_CHECK([[-Dunused-d -Funused-f input-unused.y]], [[1]], [],
[[<command line>:2: error: %define variable 'unused-d' is not used [[<command line>:2: error: %define variable 'unused-d' is not used
@@ -1360,10 +1385,10 @@ AT_SETUP([["%define" Boolean variables]])
AT_DATA([Input.y], AT_DATA([Input.y],
[[%language "Java" [[%language "Java"
%define public "maybe" %define public maybe
%define parser_class_name "Input" %define parser_class_name {Input}
%% %%
start: ; start: %empty;
]]) ]])
AT_BISON_CHECK([[Input.y]], [1], [], AT_BISON_CHECK([[Input.y]], [1], [],
@@ -1372,6 +1397,72 @@ AT_BISON_CHECK([[Input.y]], [1], [],
AT_CLEANUP AT_CLEANUP
## ------------------------ ##
## %define code variables. ##
## ------------------------ ##
AT_SETUP([["%define" code variables]])
m4_pushdef([AT_TEST],
[AT_DATA([input.yy],
[[%skeleton "lalr1.cc" %locations
%define api.location.type ]$1[quux]$2[
%define api.namespace ]$1[quux]$2[
%define api.prefix ]$1[quux]$2[
%define api.token.prefix ]$1[quux]$2[
%token TOK // Otherwise api.token.prefix is unused.
%%
start: TOK;
]])
AT_BISON_CHECK([[input.yy]], [0], [],
[[input.yy:2.9-25: warning: %define variable 'api.location.type' requires '{...}' values [-Wdeprecated]
input.yy:3.9-21: warning: %define variable 'api.namespace' requires '{...}' values [-Wdeprecated]
input.yy:4.9-18: warning: %define variable 'api.prefix' requires '{...}' values [-Wdeprecated]
input.yy:5.9-24: warning: %define variable 'api.token.prefix' requires '{...}' values [-Wdeprecated]
]])
])
AT_TEST([], [])
AT_TEST(["], ["])
m4_popdef([AT_TEST])
AT_CLEANUP
## --------------------------- ##
## %define keyword variables. ##
## --------------------------- ##
AT_SETUP([["%define" keyword variables]])
m4_pushdef([AT_TEST],
[AT_DATA([input.y],
[[%define api.pure ]$1[true]$2[
%define api.push-pull ]$1[both]$2[
%define lr.default-reduction ]$1[most]$2[
%define lr.keep-unreachable-state ]$1[true]$2[
%define lr.type ]$1[lalr]$2[
%%
exp: %empty
]])
AT_BISON_CHECK([[input.y]], [0], [],
[[input.y:1.9-16: warning: %define variable 'api.pure' requires keyword values [-Wdeprecated]
input.y:2.9-21: warning: %define variable 'api.push-pull' requires keyword values [-Wdeprecated]
input.y:3.9-28: warning: %define variable 'lr.default-reduction' requires keyword values [-Wdeprecated]
input.y:4.9-33: warning: %define variable 'lr.keep-unreachable-state' requires keyword values [-Wdeprecated]
input.y:5.9-15: warning: %define variable 'lr.type' requires keyword values [-Wdeprecated]
]])
])
AT_TEST(["], ["])
AT_TEST([{], [}])
m4_popdef([AT_TEST])
AT_CLEANUP
## ------------------------ ## ## ------------------------ ##
## %define enum variables. ## ## %define enum variables. ##
## ------------------------ ## ## ------------------------ ##
@@ -1386,7 +1477,7 @@ AT_SETUP([["%define" enum variables]])
AT_DATA([[input.y]], AT_DATA([[input.y]],
[[%define lr.default-reduction bogus [[%define lr.default-reduction bogus
%% %%
start: ; start: %empty;
]]) ]])
AT_BISON_CHECK([[-fcaret input.y]], [[1]], [[]], AT_BISON_CHECK([[-fcaret input.y]], [[1]], [[]],
[[input.y:1.9-28: error: invalid value for %define variable 'lr.default-reduction': 'bogus' [[input.y:1.9-28: error: invalid value for %define variable 'lr.default-reduction': 'bogus'
@@ -1401,7 +1492,7 @@ input.y:1.9-28: accepted value: 'accepting'
AT_DATA([[input.y]], AT_DATA([[input.y]],
[[%define api.push-pull neither [[%define api.push-pull neither
%% %%
start: ; start: %empty;
]]) ]])
AT_BISON_CHECK([[-fcaret 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: invalid value for %define variable 'api.push-pull': 'neither'
@@ -1425,10 +1516,10 @@ AT_DATA([[input.y]],
[[%define api.push_pull both [[%define api.push_pull both
%define lr.keep_unreachable_states maybe %define lr.keep_unreachable_states maybe
%define namespace "foo" %define namespace "foo"
%define api.namespace "foo" %define api.namespace {foo}
%define variant %define variant
%% %%
start: ; start: %empty;
]]) ]])
AT_BISON_CHECK([[-fcaret input.y]], [1], [], AT_BISON_CHECK([[-fcaret input.y]], [1], [],
[[input.y:1.9-21: warning: deprecated directive, use '%define api.push-pull both' [-Wdeprecated] [[input.y:1.9-21: warning: deprecated directive, use '%define api.push-pull both' [-Wdeprecated]
@@ -1441,7 +1532,7 @@ input.y:3.9-17: warning: deprecated directive, use '%define api.namespace foo' [
%define namespace "foo" %define namespace "foo"
^^^^^^^^^ ^^^^^^^^^
input.y:4.9-21: error: %define variable 'api.namespace' redefined input.y:4.9-21: error: %define variable 'api.namespace' redefined
%define api.namespace "foo" %define api.namespace {foo}
^^^^^^^^^^^^^ ^^^^^^^^^^^^^
input.y:3.9-17: previous definition input.y:3.9-17: previous definition
%define namespace "foo" %define namespace "foo"
@@ -1461,7 +1552,7 @@ AT_SETUP([[Unused %define api.pure]])
# AT_CHECK_API_PURE(DECLS, VALUE) # 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. # are specified.
m4_define([AT_CHECK_API_PURE], m4_define([AT_CHECK_API_PURE],
[ [
@@ -1469,7 +1560,7 @@ AT_DATA([[input.y]],
[[%define api.pure ]$2[ [[%define api.pure ]$2[
]$1[ ]$1[
%% %%
start: ; start: %empty;
]]) ]])
AT_BISON_CHECK([[input.y]], [[1]], [], AT_BISON_CHECK([[input.y]], [[1]], [],
@@ -1500,9 +1591,9 @@ m4_define([AT_CHECK_NAMESPACE_ERROR],
AT_DATA([[input.y]], AT_DATA([[input.y]],
[[%language "C++" [[%language "C++"
%defines %defines
%define api.namespace "]$1[" %define api.namespace {]$1[}
%% %%
start: ; start: %empty;
]]) ]])
AT_BISON_CHECK([[input.y]], [1], [], AT_BISON_CHECK([[input.y]], [1], [],
@@ -1626,26 +1717,26 @@ AT_CHECK([[$PERL -e 'print "start: \"\\\t\\\f\\\0\\\1\" ;";' >> input.y \
|| exit 77]]) || exit 77]])
AT_BISON_CHECK([input.y], [1], [], 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 [-Wother]
input.y:2.8-13: warning: empty character literal [-Wother] input.y:2.9-12: error: invalid number after \-escape: 777
input.y:2.16-17: error: invalid number after \-escape: 0
input.y:2.15-18: warning: empty character literal [-Wother] input.y:2.15-18: warning: empty character literal [-Wother]
input.y:2.21-25: error: invalid number after \-escape: xfff input.y:2.16-17: error: invalid number after \-escape: 0
input.y:2.20-26: warning: empty character literal [-Wother] input.y:2.20-26: warning: empty character literal [-Wother]
input.y:2.29-31: error: invalid number after \-escape: x0 input.y:2.21-25: error: invalid number after \-escape: xfff
input.y:2.28-32: warning: empty character literal [-Wother] input.y:2.28-32: warning: empty character literal [-Wother]
input.y:3.9-14: error: invalid number after \-escape: uffff input.y:2.29-31: error: invalid number after \-escape: x0
input.y:3.8-15: warning: empty character literal [-Wother] input.y:3.8-15: warning: empty character literal [-Wother]
input.y:3.18-23: error: invalid number after \-escape: u0000 input.y:3.9-14: error: invalid number after \-escape: uffff
input.y:3.17-24: warning: empty character literal [-Wother] input.y:3.17-24: warning: empty character literal [-Wother]
input.y:3.27-36: error: invalid number after \-escape: Uffffffff input.y:3.18-23: error: invalid number after \-escape: u0000
input.y:3.26-37: warning: empty character literal [-Wother] input.y:3.26-37: warning: empty character literal [-Wother]
input.y:3.40-49: error: invalid number after \-escape: U00000000 input.y:3.27-36: error: invalid number after \-escape: Uffffffff
input.y:3.39-50: warning: empty character literal [-Wother] input.y:3.39-50: warning: empty character literal [-Wother]
input.y:4.9-10: error: invalid character after \-escape: ' ' input.y:3.40-49: error: invalid number after \-escape: U00000000
input.y:4.8-11: warning: empty character literal [-Wother] input.y:4.8-11: warning: empty character literal [-Wother]
input.y:4.14-15: error: invalid character after \-escape: A input.y:4.9-10: error: invalid character after \-escape: ' '
input.y:4.13-16: warning: empty character literal [-Wother] input.y:4.13-16: warning: empty character literal [-Wother]
input.y:4.14-15: error: invalid character after \-escape: A
input.y:5.9-16: error: invalid character after \-escape: \t input.y:5.9-16: error: invalid character after \-escape: \t
input.y:5.17: error: invalid character after \-escape: \f input.y:5.17: error: invalid character after \-escape: \f
input.y:5.18: error: invalid character after \-escape: \0 input.y:5.18: error: invalid character after \-escape: \0
@@ -1662,7 +1753,7 @@ AT_SETUP([[LAC: Errors for %define]])
AT_DATA([[input.y]], AT_DATA([[input.y]],
[[%% [[%%
start: ; start: %empty;
]]) ]])
# parse.lac.* options are useless if LAC isn't actually activated. # parse.lac.* options are useless if LAC isn't actually activated.
@@ -1685,27 +1776,27 @@ AT_SETUP([[-Werror is not affected by -Wnone and -Wall]])
AT_DATA([[input.y]], AT_DATA([[input.y]],
[[%% [[%%
foo-bar: ; a: '0' { $$ = $; };
]]) ]])
# -Werror is not enabled by -Wall or equivalent. # -Werror is not enabled by -Wall or equivalent.
AT_BISON_CHECK([[-Wall input.y]], [[0]], [[]], AT_BISON_CHECK([[-Wall input.y]], [[0]], [[]],
[[input.y:2.1-7: warning: POSIX Yacc forbids dashes in symbol names: foo-bar [-Wyacc] [[input.y:2.15: warning: stray '$' [-Wother]
]]) ]])
AT_BISON_CHECK([[-W input.y]], [[0]], [[]], AT_BISON_CHECK([[-W input.y]], [[0]], [[]],
[[input.y:2.1-7: warning: POSIX Yacc forbids dashes in symbol names: foo-bar [-Wyacc] [[input.y:2.15: warning: stray '$' [-Wother]
]]) ]])
AT_BISON_CHECK([[-Wno-none input.y]], [[0]], [[]], AT_BISON_CHECK([[-Wno-none input.y]], [[0]], [[]],
[[input.y:2.1-7: warning: POSIX Yacc forbids dashes in symbol names: foo-bar [-Wyacc] [[input.y:2.15: warning: stray '$' [-Wother]
]]) ]])
# -Werror is not disabled by -Wnone or equivalent. # -Werror is not disabled by -Wnone or equivalent.
AT_BISON_CHECK([[-Werror,none,yacc input.y]], [[1]], [[]], [[stderr]]) AT_BISON_CHECK([[-Werror,none,other input.y]], [[1]], [[]],
AT_CHECK([[sed 's/^.*bison:/bison:/' stderr]], [[0]], [[input.y:2.15: error: stray '$' [-Werror=other]
[[input.y:2.1-7: error: POSIX Yacc forbids dashes in symbol names: foo-bar [-Werror=yacc] ]])
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 AT_CLEANUP
@@ -1722,17 +1813,17 @@ m4_pushdef([AT_TEST],
[AT_DATA([[input.y]], [AT_DATA([[input.y]],
[[$1 [[$1
%% %%
exp: /* empty */; exp: %empty;
]]) ]])
AT_BISON_CHECK([[$2 input.y]], [[1]], [[]], AT_BISON_CHECK([[$2 input.y]], [[1]], [[]],
[[$3: error: '%name-prefix' and '%define api.prefix' cannot be used together [[$3: error: '%name-prefix' and '%define api.prefix' cannot be used together
]]) ]])
]) ])
AT_TEST([%define api.prefix foo %name-prefix "bar"], [], [input.y:1.9-18]) AT_TEST([%define api.prefix {foo} %name-prefix "bar"], [], [input.y:1.9-18])
AT_TEST([], [-Dapi.prefix=foo -p bar], [<command line>:2]) AT_TEST([], [-Dapi.prefix={foo} -p bar], [<command line>:2])
AT_TEST([%name-prefix "bar"], [-Dapi.prefix=foo], [<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]) AT_TEST([%define api.prefix {foo}], [-p bar], [input.y:1.9-18])
m4_popdef([AT_TEST]) m4_popdef([AT_TEST])
@@ -1916,12 +2007,12 @@ AT_BISON_CHECK([[input.y]], [[1]], [[]],
input.y:11.15-24: 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: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.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.11-21: error: %define variable 'parse.error' redefined
input.y:13-6: previous definition input.y:13-6: previous definition
input.y:14.16-29: 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:14.11-21: error: %define variable 'parse.error' redefined input.y:14.11-21: error: %define variable 'parse.error' redefined
input.y:13.11-21: previous definition input.y:13.11-21: previous definition
input.y:14.16-29: warning: deprecated directive: '%error_verbose', use '%define parse.error verbose' [-Wdeprecated]
]]) ]])
AT_CLEANUP AT_CLEANUP
+35 -36
View File
@@ -25,8 +25,8 @@ AT_BANNER([[Java Calculator.]])
# _AT_DATA_JAVA_CALC_Y($1, $2, $3, [BISON-DIRECTIVES]) # _AT_DATA_JAVA_CALC_Y($1, $2, $3, [BISON-DIRECTIVES])
# ---------------------------------------------------- # ----------------------------------------------------
# Produce `calc.y'. Don't call this macro directly, because it contains # Produce 'calc.y'. Don't call this macro directly, because it contains
# some occurrences of `$1' etc. which will be interpreted by m4. So # 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 # you should call it with $1, $2, and $3 as arguments, which is what
# AT_DATA_JAVA_CALC_Y does. # AT_DATA_JAVA_CALC_Y does.
m4_define([_AT_DATA_JAVA_CALC_Y], m4_define([_AT_DATA_JAVA_CALC_Y],
@@ -37,7 +37,7 @@ AT_DATA([Calc.y],
[[/* Infix notation calculator--calc */ [[/* Infix notation calculator--calc */
%language "Java" %language "Java"
%name-prefix "Calc" %name-prefix "Calc"
%define parser_class_name "Calc" %define parser_class_name {Calc}
%define public %define public
]$4[ ]$4[
@@ -206,7 +206,7 @@ AT_BISON_OPTION_POPDEFS
# AT_DATA_CALC_Y([BISON-OPTIONS]) # AT_DATA_CALC_Y([BISON-OPTIONS])
# ------------------------------- # -------------------------------
# Produce `calc.y'. # Produce 'calc.y'.
m4_define([AT_DATA_JAVA_CALC_Y], m4_define([AT_DATA_JAVA_CALC_Y],
[_AT_DATA_JAVA_CALC_Y($[1], $[2], $[3], [$1]) [_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, # _AT_CHECK_JAVA_CALC_ERROR(BISON-OPTIONS, INPUT,
# [VERBOSE-AND-LOCATED-ERROR-MESSAGE]) # [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, # If INPUT starts with a slash, it is used as absolute input file name,
# otherwise as contents. # otherwise as contents.
@@ -240,7 +240,7 @@ AT_DATA([[expout]],
AT_YYERROR_SEES_LOC_IF([], AT_YYERROR_SEES_LOC_IF([],
[[sed 's/^[-0-9.]*: //' expout >at-expout [[sed 's/^[-0-9.]*: //' expout >at-expout
mv at-expout 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], [], m4_bmatch([$1], [%error-verbose], [],
[[sed 's/syntax error, .*$/syntax error/' expout >at-expout [[sed 's/syntax error, .*$/syntax error/' expout >at-expout
mv at-expout expout]]) mv at-expout expout]])
@@ -250,7 +250,7 @@ AT_CHECK([cat stderr], 0, [expout])
# _AT_CHECK_JAVA_CALC([BISON-DIRECTIVES], [BISON-CODE]) # _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. # BISON-DIRECTIVES, and performs several tests over the parser.
m4_define([_AT_CHECK_JAVA_CALC], m4_define([_AT_CHECK_JAVA_CALC],
[# We use integers to avoid dependencies upon the precision of doubles. [# 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 # - (* * *): nothing to pop, a lot to discard
# - (1 + 2 * *): some to pop and 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 # - check the lookahead that triggers an error is not discarded
# when we enter error recovery. Below, the lookahead causing the # when we enter error recovery. Below, the lookahead causing the
@@ -342,7 +342,7 @@ AT_CLEANUP
# AT_CHECK_JAVA_CALC([BISON-DIRECTIVES]) # 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. # BISON-DIRECTIVES, and performs several tests over the parser.
# Run the test with and without %error-verbose. # Run the test with and without %error-verbose.
m4_define([AT_CHECK_JAVA_CALC], m4_define([AT_CHECK_JAVA_CALC],
@@ -444,9 +444,8 @@ m4_define([AT_CHECK_JAVA_MINIMAL_W_LEXER],
# Check that YYParser.java contains exactly COUNT lines matching ^LINE$ # Check that YYParser.java contains exactly COUNT lines matching ^LINE$
# with grep. # with grep.
m4_define([AT_CHECK_JAVA_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], [ignore], [m4_default([$2], [1])
]) ])])
])
# ------------------------------------- # # ------------------------------------- #
@@ -461,13 +460,13 @@ AT_CHECK_JAVA_GREP([[class YYParser]])
AT_CHECK_JAVA_MINIMAL([[%name-prefix "Prefix"]]) AT_CHECK_JAVA_MINIMAL([[%name-prefix "Prefix"]])
AT_CHECK_JAVA_GREP([[class PrefixParser]]) AT_CHECK_JAVA_GREP([[class PrefixParser]])
AT_CHECK_JAVA_MINIMAL([[%define api.token.prefix "TOK_"]]) AT_CHECK_JAVA_MINIMAL([[%define api.token.prefix {TOK_}]])
AT_CHECK_JAVA_GREP([[.*TOK_END.*]]) AT_CHECK_JAVA_GREP([[.*TOK_END.*]])
AT_CHECK_JAVA_MINIMAL([[%define parser_class_name "ParserClassName"]]) AT_CHECK_JAVA_MINIMAL([[%define parser_class_name {ParserClassName}]])
AT_CHECK_JAVA_GREP([[class ParserClassName]]) AT_CHECK_JAVA_GREP([[class ParserClassName]])
AT_CHECK_JAVA_MINIMAL([[%define package "user_java_package"]]) AT_CHECK_JAVA_MINIMAL([[%define package {user_java_package}]])
AT_CHECK_JAVA_GREP([[package user_java_package;]]) AT_CHECK_JAVA_GREP([[package user_java_package;]])
AT_CLEANUP AT_CLEANUP
@@ -530,7 +529,7 @@ AT_CHECK_JAVA_GREP([[public final strictfp class YYParser]])
# FIXME: Can't do a Java compile because javacomp.sh is configured for 1.3 # FIXME: Can't do a Java compile because javacomp.sh is configured for 1.3
AT_CHECK_JAVA_MINIMAL([[ AT_CHECK_JAVA_MINIMAL([[
%define annotations "/*@Deprecated @SupressWarnings(\"unchecked\") @SupressWarnings({\"unchecked\", \"deprecation\"}) @SupressWarnings(value={\"unchecked\", \"deprecation\"})*/" %define annotations {/*@Deprecated @SupressWarnings("unchecked") @SupressWarnings({"unchecked", "deprecation"}) @SupressWarnings(value={"unchecked", "deprecation"})*/}
%define public]]) %define public]])
AT_CHECK_JAVA_GREP([[/\*@Deprecated @SupressWarnings("unchecked") @SupressWarnings({"unchecked", "deprecation"}) @SupressWarnings(value={"unchecked", "deprecation"})\*/ public class YYParser]]) AT_CHECK_JAVA_GREP([[/\*@Deprecated @SupressWarnings("unchecked") @SupressWarnings({"unchecked", "deprecation"}) @SupressWarnings(value={"unchecked", "deprecation"})\*/ public class YYParser]])
@@ -543,15 +542,15 @@ AT_CLEANUP
AT_SETUP([Java parser class extends and implements]) AT_SETUP([Java parser class extends and implements])
AT_CHECK_JAVA_MINIMAL([[%define extends "Thread"]]) AT_CHECK_JAVA_MINIMAL([[%define extends {Thread}]])
AT_CHECK_JAVA_GREP([[class YYParser extends Thread]]) AT_CHECK_JAVA_GREP([[class YYParser extends Thread]])
AT_CHECK_JAVA_MINIMAL([[%define implements "Cloneable"]]) AT_CHECK_JAVA_MINIMAL([[%define implements {Cloneable}]])
AT_CHECK_JAVA_GREP([[class YYParser implements Cloneable]]) AT_CHECK_JAVA_GREP([[class YYParser implements Cloneable]])
AT_CHECK_JAVA_MINIMAL([[ AT_CHECK_JAVA_MINIMAL([[
%define extends "Thread" %define extends {Thread}
%define implements "Cloneable"]]) %define implements {Cloneable}]])
AT_CHECK_JAVA_GREP([[class YYParser extends Thread implements Cloneable]]) AT_CHECK_JAVA_GREP([[class YYParser extends Thread implements Cloneable]])
AT_CLEANUP AT_CLEANUP
@@ -643,9 +642,9 @@ AT_SETUP([Java throws specifications])
m4_define([AT_JT_lex_throws_define], [m4_case(AT_JT_lex_throws, m4_define([AT_JT_lex_throws_define], [m4_case(AT_JT_lex_throws,
-1, [], -1, [],
0, [[%define lex_throws ""]], 0, [[%define lex_throws {}]],
1, [[%define lex_throws "InterruptedException"]], 1, [[%define lex_throws {InterruptedException}]],
2, [[%define lex_throws "InterruptedException, IllegalAccessException"]])]) 2, [[%define lex_throws {InterruptedException, IllegalAccessException}]])])
m4_define([AT_JT_yylex_throws], [m4_case(AT_JT_lex_throws, m4_define([AT_JT_yylex_throws], [m4_case(AT_JT_lex_throws,
-1, [[ throws java.io.IOException]], -1, [[ throws java.io.IOException]],
@@ -662,9 +661,9 @@ m4_define([AT_JT_yylex_action], [m4_case(AT_JT_lex_throws,
m4_define([AT_JT_throws_define], [m4_case(AT_JT_throws, m4_define([AT_JT_throws_define], [m4_case(AT_JT_throws,
-1, [], -1, [],
0, [[%define throws ""]], 0, [[%define throws {}]],
1, [[%define throws "ClassNotFoundException"]], 1, [[%define throws {ClassNotFoundException}]],
2, [[%define throws "ClassNotFoundException, InstantiationException"]])]) 2, [[%define throws {ClassNotFoundException, InstantiationException}]])])
m4_define([AT_JT_yyaction_throws], [m4_case(AT_JT_throws, m4_define([AT_JT_yyaction_throws], [m4_case(AT_JT_throws,
-1, [], -1, [],
@@ -727,16 +726,16 @@ AT_CLEANUP
AT_SETUP([Java constructor init and init_throws]) AT_SETUP([Java constructor init and init_throws])
AT_CHECK_JAVA_MINIMAL([[ AT_CHECK_JAVA_MINIMAL([[
%define extends "Thread" %define extends {Thread}
%code init { super("Test Thread"); if (true) throw new InterruptedException(); } %code init { super("Test Thread"); if (true) throw new InterruptedException(); }
%define init_throws "InterruptedException" %define init_throws {InterruptedException}
%lex-param {int lex_param}]]) %lex-param {int lex_param}]])
AT_CHECK([[grep -q 'super("Test Thread"); if (true) throw new InterruptedException();' YYParser.java]]) AT_CHECK([[grep -q 'super("Test Thread"); if (true) throw new InterruptedException();' YYParser.java]])
AT_CHECK_JAVA_MINIMAL_W_LEXER([[ AT_CHECK_JAVA_MINIMAL_W_LEXER([[
%define extends "Thread" %define extends {Thread}
%code init { super("Test Thread"); if (true) throw new InterruptedException(); } %code init { super("Test Thread"); if (true) throw new InterruptedException(); }
%define init_throws "InterruptedException"]], [], [[return EOF;]]) %define init_throws {InterruptedException}]], [], [[return EOF;]])
AT_CHECK([[grep -q 'super("Test Thread"); if (true) throw new InterruptedException();' YYParser.java]]) AT_CHECK([[grep -q 'super("Test Thread"); if (true) throw new InterruptedException();' YYParser.java]])
AT_CLEANUP AT_CLEANUP
@@ -749,20 +748,20 @@ AT_CLEANUP
AT_SETUP([Java value, position, and location types]) AT_SETUP([Java value, position, and location types])
AT_CHECK_JAVA_MINIMAL([[ AT_CHECK_JAVA_MINIMAL([[
%define api.value.type "java.awt.Color" %define api.value.type {java.awt.Color}
%type<java.awt.Color> start; %type<java.awt.Color> start;
%define api.location.type "MyLoc" %define api.location.type {MyLoc}
%define api.position.type "MyPos" %define api.position.type {MyPos}
%code { class MyPos {} }]], [[$$ = $<java.awt.Color>1;]], [[MyPos]]) %code { class MyPos {} }]], [[$$ = $<java.awt.Color>1;]], [[MyPos]])
AT_CHECK([[grep 'java.awt.Color' YYParser.java]], [0], [ignore]) AT_CHECK([[grep 'java.awt.Color' YYParser.java]], [0], [ignore])
AT_CHECK([[$EGREP -v ' */?\*' YYParser.java | grep 'Position']], [1], [ignore]) AT_CHECK([[$EGREP -v ' */?\*' YYParser.java | grep 'Position']], [1], [ignore])
AT_CHECK([[$EGREP -v ' */?\*' YYParser.java | grep 'Location']], [1], [ignore]) AT_CHECK([[$EGREP -v ' */?\*' YYParser.java | grep 'Location']], [1], [ignore])
AT_CHECK_JAVA_MINIMAL_W_LEXER([[ AT_CHECK_JAVA_MINIMAL_W_LEXER([[
%define api.value.type "java.awt.Color" %define api.value.type {java.awt.Color}
%type<java.awt.Color> start; %type<java.awt.Color> start;
%define api.location.type "MyLoc" %define api.location.type {MyLoc}
%define api.position.type "MyPos" %define api.position.type {MyPos}
%code { class MyPos {} }]], [], [[return EOF;]], [], %code { class MyPos {} }]], [], [[return EOF;]], [],
[[$$ = $<java.awt.Color>1;]], [[$$ = $<java.awt.Color>1;]],
[[java.awt.Color]], [[MyPos]], [[MyLoc]]) [[java.awt.Color]], [[MyPos]], [[MyLoc]])
+864
View File
@@ -0,0 +1,864 @@
# Checking Java Push Parsing. -*- 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/>.
# The Java push parser tests are intended primarily
# to verify that the sequence of states that the parser
# traverses is the same as a pull parser would traverse.
##################################################
# Provide a way to generate data with and without push parsing
# so it is possible to capture the output for comparison
# (except the "trivial" tests).
# Use "both" rather than "push" so we can also set it to "pull" to
# get the "experr" data.
m4_define([PUSHPULLFLAG],[-Dapi.push-pull=both])
# AT_CHECK_JAVA_GREP(FILE, [LINE], [COUNT=1])
# -------------------------------------------
# Check that FILE contains exactly COUNT lines matching ^LINE$
# with grep. Unquoted so that COUNT can be a shell expression.
m4_define([AT_CHECK_JAVA_GREP],
[AT_CHECK_UNQUOTED([grep -c '^$2$' $1], [ignore], [m4_default([$3], [1])
])])
##################################################
AT_BANNER([[Java Push Parsing Tests]])
# Define a single copy of the trivial parser grammar.
# This is missing main(), so two versions
# are instantiated with different main() procedures.
m4_define([AT_TRIVIAL_GRAMMAR],[
%define parser_class_name {YYParser}
%error-verbose
%code imports {
import java.io.*;
import java.util.*;
}
%%
start: 'a' 'b' 'c' ;
%%
])
# Define comon code across to be includede in
# class Main for the trivial parser tests.
m4_define([AT_TRIVIAL_COMMON],[
static class YYerror implements YYParser.Lexer
{
public Object getLVal() {return null;}
public int yylex () throws java.io.IOException { return 0; }
public void yyerror (String msg) { System.err.println(msg); }
}
static YYParser parser = null;
static YYerror yyerror = null;
static int teststate = -1;
static void setup()
throws IOException
{
yyerror = new YYerror();
parser = new YYParser(yyerror);
parser.setDebugLevel(1);
teststate = -1;
}
static String[[]] teststatename
= new String[[]]{"YYACCEPT","YYABORT","YYERROR","UNKNOWN","YYPUSH_MORE"};
static void check(int teststate, int expected, String msg)
{
System.err.println("teststate="+teststatename[[teststate]]
+"; expected="+teststatename[[expected]]);
if (teststate == expected)
return;
System.err.println("unexpected state: "+msg);
System.exit(1);
}
])
m4_define([AT_TRIVIAL_PARSER],[
AT_TRIVIAL_GRAMMAR
public class Main
{
AT_TRIVIAL_COMMON
static public void main (String[[]] argv)
throws IOException
{
setup();
teststate = parser.push_parse('a', null);
check(teststate,YYParser.YYPUSH_MORE,"push_parse('a', null)");
setup();
teststate = parser.push_parse('a', null);
check(teststate,YYParser.YYPUSH_MORE,"push_parse('a', null)");
teststate = parser.push_parse('b', null);
check(teststate,YYParser.YYPUSH_MORE,"push_parse('b', null)");
teststate = parser.push_parse('c', null);
check(teststate,YYParser.YYPUSH_MORE,"push_parse('c', null)");
teststate = parser.push_parse('\0', null);
check(teststate,YYParser.YYACCEPT,"push_parse('\\0', null)");
/* Reuse the parser instance and cause a failure */
teststate = parser.push_parse('b', null);
check(teststate,YYParser.YYABORT,"push_parse('b', null)");
System.exit(0);
}
}
])
m4_define([AT_TRIVIAL_PARSER_INITIAL_ACTION],[
AT_TRIVIAL_GRAMMAR
public class Main
{
AT_TRIVIAL_COMMON
static public void main (String[[]] argv)
throws IOException
{
setup();
teststate = parser.push_parse('a', null);
check(teststate,YYParser.YYPUSH_MORE,"push_parse('a', null)");
teststate = parser.push_parse('b', null);
check(teststate,YYParser.YYPUSH_MORE,"push_parse('b', null)");
teststate = parser.push_parse('c', null);
check(teststate,YYParser.YYPUSH_MORE,"push_parse('c', null)");
teststate = parser.push_parse('\0', null);
check(teststate,YYParser.YYACCEPT,"push_parse('\\0', null)");
System.exit(0);
}
}
])
## ----------------------------------------------------- ##
## Trivial Push Parser with api.push-pull verification. ##
## ----------------------------------------------------- ##
AT_SETUP([Trivial Push Parser with api.push-pull verification])
AT_BISON_OPTION_PUSHDEFS
AT_DATA([[input.y]],
[[%language "Java"
]AT_TRIVIAL_PARSER[
]])
# Verify that the proper procedure(s) are generated for each case.
AT_BISON_CHECK([[-Dapi.push-pull=pull -o Main.java input.y]])
AT_CHECK_JAVA_GREP([[Main.java]],
[[.*public boolean parse ().*]],
[1])
# If BISON_USE_PUSH_FOR_PULL is set, then we have one occurrence of
# this function, otherwise it should not be there.
AT_CHECK_JAVA_GREP([[Main.java]],
[[.*public int push_parse (int yylextoken, Object yylexval).*]],
[${BISON_USE_PUSH_FOR_PULL-0}])
AT_BISON_CHECK([[-Dapi.push-pull=both -o Main.java input.y]])
AT_CHECK_JAVA_GREP([[Main.java]],
[[.*public boolean parse ().*]],
[1])
AT_CHECK_JAVA_GREP([[Main.java]],
[[.*public int push_parse (int yylextoken, Object yylexval).*]],
[1])
AT_BISON_CHECK([[-Dapi.push-pull=push -o Main.java input.y]])
AT_CHECK_JAVA_GREP([[Main.java]],
[[.*public boolean parse ().*]],
[0])
AT_CHECK_JAVA_GREP([[Main.java]],
[[.*public int push_parse (int yylextoken, Object yylexval).*]],
[1])
AT_JAVA_COMPILE([[Main.java]])
AT_JAVA_PARSER_CHECK([Main], 0, [], [stderr-nolog])
AT_BISON_OPTION_POPDEFS
AT_CLEANUP
## ------------------------------------------ ##
## Trivial Push Parser with %initial-action. ##
## ------------------------------------------ ##
AT_SETUP([Trivial Push Parser with %initial-action])
AT_BISON_OPTION_PUSHDEFS
AT_DATA([[input.y]],[[%language "Java"
%initial-action {
System.err.println("Initial action invoked");
}
]AT_TRIVIAL_PARSER_INITIAL_ACTION[
]])
AT_BISON_OPTION_POPDEFS
AT_BISON_CHECK([[-Dapi.push-pull=push -o Main.java input.y]])
AT_CHECK_JAVA_GREP([[Main.java]],
[[System.err.println("Initial action invoked");]])
AT_JAVA_COMPILE([[Main.java]])
AT_JAVA_PARSER_CHECK([Main], 0, [], [stderr-nolog])
# Verify that initial action is called exactly once.
AT_CHECK_JAVA_GREP(
[[stderr]],
[[Initial action invoked]],
[1])
AT_CLEANUP
# Define a single copy of the Calculator grammar.
m4_define([AT_CALC_BODY],[
%code imports {
import java.io.*;
}
%code {
static StringReader
getinput(String filename) throws IOException
{
StringBuilder buf = new StringBuilder();
FileReader file = new FileReader(filename);
int c;
while ((c=file.read()) > 0)
buf.append((char)c);
file.close();
return new StringReader(buf.toString());
}
}
/* Bison Declarations */
%token <Integer> NUM "number"
%type <Integer> exp
%nonassoc '=' /* comparison */
%left '-' '+'
%left '*' '/'
%left NEG /* negation--unary minus */
%right '^' /* exponentiation */
/* Grammar follows */
%%
input:
line
| input line
;
line:
'\n'
| exp '\n'
{System.out.println("total = "+$[]1);}
| error '\n'
;
exp:
NUM { $[]$ = $[]1;}
| exp '=' exp
{
if ($[]1.intValue() != $[]3.intValue())
yyerror (]AT_LOCATION_IF([[@$,]])[ "calc: error: " + $[]1 + " != " + $[]3);
}
| exp '+' exp
{ $[]$ = new Integer ($[]1.intValue () + $[]3.intValue ()); }
| exp '-' exp
{ $[]$ = new Integer ($[]1.intValue () - $[]3.intValue ()); }
| exp '*' exp
{ $[]$ = new Integer ($[]1.intValue () * $[]3.intValue ()); }
| exp '/' exp
{ $[]$ = new Integer ($[]1.intValue () / $[]3.intValue ()); }
| '-' exp %prec NEG
{ $[]$ = new Integer (-$[]2.intValue ()); }
| exp '^' exp
{ $[]$ = new Integer ((int)Math.pow ($[]1.intValue (),
$[]3.intValue ())); }
| '(' exp ')' { $[]$ = $[]2;}
| '(' error ')' { $[]$ = new Integer (1111);}
| '!' { $[]$ = new Integer (0); return YYERROR;}
| '-' error { $[]$ = new Integer (0); return YYERROR;}
;
])
# Test that the states transitioned by the push parser are the
# same as for the pull parser. This test is assumed to work
# if it produces the same partial trace of stack states as is
# produced when using pull parsing. The output is verbose,
# but seems essential for verifying push parsing.
AT_SETUP([Calc parser with api.push-pull both])
AT_BISON_OPTION_PUSHDEFS
# Define the calculator input.
# Warning: if you changes the input file
# then the locations test file position numbers
# may be incorrect and you will have
# to modify that file as well.
AT_DATA([input],[[1 + 2 * 3 = 7
1 + 2 * -3 = -5
-1^2 = -1
(-1)^2 = 1
---1 = -1
1 - 2 - 3 = -4
1 - (2 - 3) = 2
2^2^3 = 256
(2^2)^3 = 64
]])
# Compose pieces to build the actual .y file.
AT_DATA([Calc.y],[[/* Infix notation calculator--calc */
%language "Java"
%name-prefix "Calc"
%define parser_class_name {Calc}
%code {
static class UserLexer implements Calc.Lexer
{
StreamTokenizer st;
StringReader rdr;
public UserLexer(StringReader reader)
{
rdr = reader;
st = new StreamTokenizer(rdr);
st.resetSyntax();
st.eolIsSignificant(true);
st.whitespaceChars(9, 9);
st.whitespaceChars(32, 32);
st.wordChars(48, 57);
}
Integer yylval;
public Object getLVal() { return yylval; }
public void yyerror(String msg) { System.err.println(msg); }
public int yylex () throws IOException
{
switch (st.nextToken()) {
case StreamTokenizer.TT_EOF: return EOF;
case StreamTokenizer.TT_EOL: return (int) '\n';
case StreamTokenizer.TT_WORD:
yylval = new Integer (st.sval);
return NUM;
default: return st.ttype;
}
}
}
}
%code {
public static void main (String[] argv)
throws IOException
{
StringReader reader = getinput(argv[0]);
UserLexer lexer = new UserLexer(reader);
Calc calc = new Calc(lexer);
calc.setDebugLevel(1);
calc.parse();
}//main
}
]AT_CALC_BODY[
]])
# This data was captured from running a pull parser.
AT_DATA([[expout]],[[Stack now 0
Stack now 0 2
Stack now 0 9
Stack now 0 9 19
Stack now 0 9 19 2
Stack now 0 9 19 28
Stack now 0 9 19 28 20
Stack now 0 9 19 28 20 2
Stack now 0 9 19 28 20 29
Stack now 0 9 19 28
Stack now 0 9
Stack now 0 9 17
Stack now 0 9 17 2
Stack now 0 9 17 26
Stack now 0 9
Stack now 0 9 23
Stack now 0 8
Stack now 0 7
Stack now 0 7 2
Stack now 0 7 9
Stack now 0 7 9 19
Stack now 0 7 9 19 2
Stack now 0 7 9 19 28
Stack now 0 7 9 19 28 20
Stack now 0 7 9 19 28 20 3
Stack now 0 7 9 19 28 20 3 2
Stack now 0 7 9 19 28 20 3 12
Stack now 0 7 9 19 28 20 29
Stack now 0 7 9 19 28
Stack now 0 7 9
Stack now 0 7 9 17
Stack now 0 7 9 17 3
Stack now 0 7 9 17 3 2
Stack now 0 7 9 17 3 12
Stack now 0 7 9 17 26
Stack now 0 7 9
Stack now 0 7 9 23
Stack now 0 7 16
Stack now 0 7
Stack now 0 7 4
Stack now 0 7 16
Stack now 0 7
Stack now 0 7 3
Stack now 0 7 3 2
Stack now 0 7 3 12
Stack now 0 7 3 12 22
Stack now 0 7 3 12 22 2
Stack now 0 7 3 12 22 31
Stack now 0 7 3 12
Stack now 0 7 9
Stack now 0 7 9 17
Stack now 0 7 9 17 3
Stack now 0 7 9 17 3 2
Stack now 0 7 9 17 3 12
Stack now 0 7 9 17 26
Stack now 0 7 9
Stack now 0 7 9 23
Stack now 0 7 16
Stack now 0 7
Stack now 0 7 5
Stack now 0 7 5 3
Stack now 0 7 5 3 2
Stack now 0 7 5 3 12
Stack now 0 7 5 14
Stack now 0 7 5 14 25
Stack now 0 7 9
Stack now 0 7 9 22
Stack now 0 7 9 22 2
Stack now 0 7 9 22 31
Stack now 0 7 9
Stack now 0 7 9 17
Stack now 0 7 9 17 2
Stack now 0 7 9 17 26
Stack now 0 7 9
Stack now 0 7 9 23
Stack now 0 7 16
Stack now 0 7
Stack now 0 7 4
Stack now 0 7 16
Stack now 0 7
Stack now 0 7 3
Stack now 0 7 3 3
Stack now 0 7 3 3 3
Stack now 0 7 3 3 3 2
Stack now 0 7 3 3 3 12
Stack now 0 7 3 3 12
Stack now 0 7 3 12
Stack now 0 7 9
Stack now 0 7 9 17
Stack now 0 7 9 17 3
Stack now 0 7 9 17 3 2
Stack now 0 7 9 17 3 12
Stack now 0 7 9 17 26
Stack now 0 7 9
Stack now 0 7 9 23
Stack now 0 7 16
Stack now 0 7
Stack now 0 7 4
Stack now 0 7 16
Stack now 0 7
Stack now 0 7 2
Stack now 0 7 9
Stack now 0 7 9 18
Stack now 0 7 9 18 2
Stack now 0 7 9 18 27
Stack now 0 7 9
Stack now 0 7 9 18
Stack now 0 7 9 18 2
Stack now 0 7 9 18 27
Stack now 0 7 9
Stack now 0 7 9 17
Stack now 0 7 9 17 3
Stack now 0 7 9 17 3 2
Stack now 0 7 9 17 3 12
Stack now 0 7 9 17 26
Stack now 0 7 9
Stack now 0 7 9 23
Stack now 0 7 16
Stack now 0 7
Stack now 0 7 2
Stack now 0 7 9
Stack now 0 7 9 18
Stack now 0 7 9 18 5
Stack now 0 7 9 18 5 2
Stack now 0 7 9 18 5 14
Stack now 0 7 9 18 5 14 18
Stack now 0 7 9 18 5 14 18 2
Stack now 0 7 9 18 5 14 18 27
Stack now 0 7 9 18 5 14
Stack now 0 7 9 18 5 14 25
Stack now 0 7 9 18 27
Stack now 0 7 9
Stack now 0 7 9 17
Stack now 0 7 9 17 2
Stack now 0 7 9 17 26
Stack now 0 7 9
Stack now 0 7 9 23
Stack now 0 7 16
Stack now 0 7
Stack now 0 7 4
Stack now 0 7 16
Stack now 0 7
Stack now 0 7 2
Stack now 0 7 9
Stack now 0 7 9 22
Stack now 0 7 9 22 2
Stack now 0 7 9 22 31
Stack now 0 7 9 22 31 22
Stack now 0 7 9 22 31 22 2
Stack now 0 7 9 22 31 22 31
Stack now 0 7 9 22 31
Stack now 0 7 9
Stack now 0 7 9 17
Stack now 0 7 9 17 2
Stack now 0 7 9 17 26
Stack now 0 7 9
Stack now 0 7 9 23
Stack now 0 7 16
Stack now 0 7
Stack now 0 7 5
Stack now 0 7 5 2
Stack now 0 7 5 14
Stack now 0 7 5 14 22
Stack now 0 7 5 14 22 2
Stack now 0 7 5 14 22 31
Stack now 0 7 5 14
Stack now 0 7 5 14 25
Stack now 0 7 9
Stack now 0 7 9 22
Stack now 0 7 9 22 2
Stack now 0 7 9 22 31
Stack now 0 7 9
Stack now 0 7 9 17
Stack now 0 7 9 17 2
Stack now 0 7 9 17 26
Stack now 0 7 9
Stack now 0 7 9 23
Stack now 0 7 16
Stack now 0 7
Stack now 0 7 15
]])
AT_BISON_CHECK([PUSHPULLFLAG [-o Calc.java Calc.y]])
AT_JAVA_COMPILE([[Calc.java]])
#Verify that this is a push parser.
AT_CHECK_JAVA_GREP([[Calc.java]],
[[.*public void push_parse_initialize().*]])
# Capture stderr output for comparison purposes.
AT_JAVA_PARSER_CHECK([Calc input], 0, [ignore-nolog], [stderr-nolog])
# Extract the "Stack Now" lines from the error output,
# send them to stdout (via the sed command) and compare to expout.
# NOTE: because the target is "expout", this macro automatically
# compares the output of the sed command with the contents of
# the file "expout" (defined above).
AT_CHECK([[sed -e '/^Stack now.*$/p' -e d ./stderr]],
[ignore], [expout], [ignore-nolog])
AT_BISON_OPTION_POPDEFS
AT_CLEANUP
# This test looks for location reporting by looking
# at the lexer output with locations enabled.
# It defines a lexer that reports location info.
AT_SETUP([Calc parser with %locations %code lexer and api.push-pull both])
AT_BISON_OPTION_PUSHDEFS
AT_DATA([Calc.y],[[/* Infix notation calculator--calc. */
%language "Java"
%name-prefix "Calc"
%define parser_class_name {Calc}
%lex-param { Reader rdr }
%locations
%code imports {
import java.io.*;
}
%code lexer {
StreamTokenizer st;
Integer yylval;
public YYLexer(Reader rdr)
{
st = new StreamTokenizer(rdr);
st.resetSyntax();
st.eolIsSignificant(true);
st.whitespaceChars(9, 9);
st.whitespaceChars(32, 32);
st.wordChars(48, 57);
}
Position yypos = new Position (1, 0);
public Position getStartPos() { return yypos; }
public Position getEndPos() { return yypos; }
public Object getLVal() { return yylval; }
public void yyerror(Location loc, String msg)
{
System.err.println(loc+":"+msg);
}
public int yylex () throws IOException
{
yypos = new Position (yypos.lineno (),yypos.token () + 1);
switch (st.nextToken()) {
case StreamTokenizer.TT_EOF:
return EOF;
case StreamTokenizer.TT_EOL:
yypos = new Position (yypos.lineno () + 1, 0);
return (int) '\n';
case StreamTokenizer.TT_WORD:
yylval = new Integer (st.sval);
return NUM;
default:
return st.ttype;
}
}
}
%code {
class Position {
public int line;
public int token;
public Position () { line = 0; token = 0; }
public Position (int l, int t) { line = l; token = t; }
public boolean equals (Position l)
{
return l.line == line && l.token == token;
}
public String toString ()
{
return Integer.toString(line) + "." + Integer.toString(token);
}
public int lineno () { return line; }
public int token () { return token; }
}//Class Position
}
%code {
public static void main (String[] argv)
throws IOException
{
StringReader reader = getinput(argv[0]);
Calc calc = new Calc(reader);
calc.setDebugLevel(1);
calc.parse();
}
}
]AT_CALC_BODY[
]])
# Define the expected calculator output.
# This should match the output from a pull parser.
AT_DATA([output],[[total = 7
total = -5
total = -1
total = 1
total = -1
total = -4
total = 2
total = 256
total = 64
]])
AT_DATA([locations],[[Next token is token "number" (1.1: 1)
Next token is token '+' (1.2: 1)
Next token is token "number" (1.3: 2)
Next token is token '*' (1.4: 2)
Next token is token "number" (1.5: 3)
Next token is token '=' (1.6: 3)
Next token is token '=' (1.6: 3)
Next token is token '=' (1.6: 3)
Next token is token "number" (1.7: 7)
Next token is token '\n' (2.0: 7)
Next token is token '\n' (2.0: 7)
Next token is token "number" (2.1: 1)
Next token is token '+' (2.2: 1)
Next token is token "number" (2.3: 2)
Next token is token '*' (2.4: 2)
Next token is token '-' (2.5: 2)
Next token is token "number" (2.6: 3)
Next token is token '=' (2.7: 3)
Next token is token '=' (2.7: 3)
Next token is token '=' (2.7: 3)
Next token is token '=' (2.7: 3)
Next token is token '-' (2.8: 3)
Next token is token "number" (2.9: 5)
Next token is token '\n' (3.0: 5)
Next token is token '\n' (3.0: 5)
Next token is token '\n' (3.0: 5)
Next token is token '\n' (4.0: 5)
Next token is token '-' (4.1: 5)
Next token is token "number" (4.2: 1)
Next token is token '^' (4.3: 1)
Next token is token "number" (4.4: 2)
Next token is token '=' (4.5: 2)
Next token is token '=' (4.5: 2)
Next token is token '=' (4.5: 2)
Next token is token '-' (4.6: 2)
Next token is token "number" (4.7: 1)
Next token is token '\n' (5.0: 1)
Next token is token '\n' (5.0: 1)
Next token is token '\n' (5.0: 1)
Next token is token '(' (5.1: 1)
Next token is token '-' (5.2: 1)
Next token is token "number" (5.3: 1)
Next token is token ')' (5.4: 1)
Next token is token ')' (5.4: 1)
Next token is token '^' (5.5: 1)
Next token is token "number" (5.6: 2)
Next token is token '=' (5.7: 2)
Next token is token '=' (5.7: 2)
Next token is token "number" (5.8: 1)
Next token is token '\n' (6.0: 1)
Next token is token '\n' (6.0: 1)
Next token is token '\n' (7.0: 1)
Next token is token '-' (7.1: 1)
Next token is token '-' (7.2: 1)
Next token is token '-' (7.3: 1)
Next token is token "number" (7.4: 1)
Next token is token '=' (7.5: 1)
Next token is token '=' (7.5: 1)
Next token is token '=' (7.5: 1)
Next token is token '=' (7.5: 1)
Next token is token '-' (7.6: 1)
Next token is token "number" (7.7: 1)
Next token is token '\n' (8.0: 1)
Next token is token '\n' (8.0: 1)
Next token is token '\n' (8.0: 1)
Next token is token '\n' (9.0: 1)
Next token is token "number" (9.1: 1)
Next token is token '-' (9.2: 1)
Next token is token "number" (9.3: 2)
Next token is token '-' (9.4: 2)
Next token is token '-' (9.4: 2)
Next token is token "number" (9.5: 3)
Next token is token '=' (9.6: 3)
Next token is token '=' (9.6: 3)
Next token is token '-' (9.7: 3)
Next token is token "number" (9.8: 4)
Next token is token '\n' (10.0: 4)
Next token is token '\n' (10.0: 4)
Next token is token '\n' (10.0: 4)
Next token is token "number" (10.1: 1)
Next token is token '-' (10.2: 1)
Next token is token '(' (10.3: 1)
Next token is token "number" (10.4: 2)
Next token is token '-' (10.5: 2)
Next token is token "number" (10.6: 3)
Next token is token ')' (10.7: 3)
Next token is token ')' (10.7: 3)
Next token is token '=' (10.8: 3)
Next token is token '=' (10.8: 3)
Next token is token "number" (10.9: 2)
Next token is token '\n' (11.0: 2)
Next token is token '\n' (11.0: 2)
Next token is token '\n' (12.0: 2)
Next token is token "number" (12.1: 2)
Next token is token '^' (12.2: 2)
Next token is token "number" (12.3: 2)
Next token is token '^' (12.4: 2)
Next token is token "number" (12.5: 3)
Next token is token '=' (12.6: 3)
Next token is token '=' (12.6: 3)
Next token is token '=' (12.6: 3)
Next token is token "number" (12.7: 256)
Next token is token '\n' (13.0: 256)
Next token is token '\n' (13.0: 256)
Next token is token '(' (13.1: 256)
Next token is token "number" (13.2: 2)
Next token is token '^' (13.3: 2)
Next token is token "number" (13.4: 2)
Next token is token ')' (13.5: 2)
Next token is token ')' (13.5: 2)
Next token is token '^' (13.6: 2)
Next token is token "number" (13.7: 3)
Next token is token '=' (13.8: 3)
Next token is token '=' (13.8: 3)
Next token is token "number" (13.9: 64)
Next token is token '\n' (14.0: 64)
Next token is token '\n' (14.0: 64)
]])
# Define the calculator input.
# Warning: if you changes the input file
# then the locations test file position numbers
# may be incorrect and you will have
# to modify that file as well.
AT_DATA([input],[[1 + 2 * 3 = 7
1 + 2 * -3 = -5
-1^2 = -1
(-1)^2 = 1
---1 = -1
1 - 2 - 3 = -4
1 - (2 - 3) = 2
2^2^3 = 256
(2^2)^3 = 64
]])
AT_BISON_CHECK([PUSHPULLFLAG [-o Calc.java Calc.y]])
AT_JAVA_COMPILE([[Calc.java]])
# Verify that this is a push parser
AT_CHECK_JAVA_GREP([[Calc.java]],
[[.*public void push_parse_initialize().*]])
# Capture the stdout and stderr output for comparison purposes.
AT_JAVA_PARSER_CHECK([Calc input], 0, [stdout-nolog], [stderr-nolog])
# 1. Check that the token locations are correct
AT_CHECK([[cp -f ./locations ./expout]],[ignore],[ignore-nolog],[ignore-nolog])
AT_CHECK([[sed -e '/^Next token.*$/p' -e d ./stderr]],[ignore],[expout],[ignore-nolog])
# 2. Check that the calculator output matches that of a pull parser
AT_CHECK([[rm -f ./expout; cp -f ./output ./expout]],[ignore],[ignore-nolog],[ignore-nolog])
AT_CHECK([[cat ./stdout]],[ignore],[expout],[ignore-nolog])
AT_CLEANUP
+153 -104
View File
@@ -37,7 +37,7 @@ m4_define([AT_SETUP_STRIP],
[m4_bpatsubsts([$1], [m4_bpatsubsts([$1],
[%\(language\|skeleton\) "?\([^\" ]*\)"?], [%\(language\|skeleton\) "?\([^\" ]*\)"?],
[\2], [\2],
[%define "?\([-A-Za-z0-9_.]+\)"? \("[^\"]+"\|[-A-Za-z0-9_.]+\)], [%define "?\([-A-Za-z0-9_.]+\)"? \({[^\}]+}\|"[^\"]+"\|[-A-Za-z0-9_.]+\)],
[\1=\2], [\1=\2],
[%define "?\([-A-Za-z0-9_.]+\)"?], [%define "?\([-A-Za-z0-9_.]+\)"?],
[\1], [\1],
@@ -134,7 +134,7 @@ m4_define([AT_BISON_OPTION_PUSHDEFS],
# _AT_BISON_OPTION_PUSHDEFS($1, $2, [BISON-OPTIONS]) # _AT_BISON_OPTION_PUSHDEFS($1, $2, [BISON-OPTIONS])
# -------------------------------------------------- # --------------------------------------------------
# This macro works around the impossibility to define macros # This macro works around the impossibility to define macros
# inside macros, because issuing `[$1]' is not possible in M4 :(. # inside macros, because issuing '[$1]' is not possible in M4 :(.
# This sucks hard, GNU M4 should really provide M5-like $$1. # This sucks hard, GNU M4 should really provide M5-like $$1.
m4_define([_AT_BISON_OPTION_PUSHDEFS], m4_define([_AT_BISON_OPTION_PUSHDEFS],
[m4_if([$1$2], $[1]$[2], [], [m4_if([$1$2], $[1]$[2], [],
@@ -178,23 +178,25 @@ m4_bpatsubst([$3], [%parse-param { *\([^{}]*[^{} ]\) *}],
m4_pushdef([AT_PURE_IF], m4_pushdef([AT_PURE_IF],
[m4_bmatch([$3], [%define *api\.pure\|%pure-parser], [m4_bmatch([$3], [%define *api\.pure\|%pure-parser],
[m4_bmatch([$3], [%define *api\.pure *"?false"?], [$2], [$1])], [m4_bmatch([$3], [%define *api\.pure *false], [$2], [$1])],
[$2])]) [$2])])
# AT_NAME_PREFIX: also consider api.namespace. # AT_NAME_PREFIX: also consider api.namespace.
m4_pushdef([AT_NAME_PREFIX], m4_pushdef([AT_NAME_PREFIX],
[m4_bmatch([$3], [\(%define api\.\(namespace\|prefix\)\|%name-prefix\) ".*"], [m4_bmatch([$3], [\(%define api\.\(namespace\|prefix\)\|%name-prefix\) .*],
[m4_bregexp([$3], [\(%define api\.\(namespace\|prefix\)\|%name-prefix\) "\([^""]*\)"], [\3])], [m4_bregexp([$3],
[yy])]) [\(%define api\.\(namespace\|prefix\)\|%name-prefix\) [\{\"]\([^\"\}]*\)[\"\}]],
[\3])],
[yy])])
m4_pushdef([AT_TOKEN_CTOR_IF], m4_pushdef([AT_TOKEN_CTOR_IF],
[m4_bmatch([$3], [%define api\.token\.constructor], [$1], [$2])]) [m4_bmatch([$3], [%define api\.token\.constructor], [$1], [$2])])
m4_pushdef([AT_TOKEN_PREFIX], m4_pushdef([AT_TOKEN_PREFIX],
[m4_bmatch([$3], [%define api\.token\.prefix ".*"], [m4_bmatch([$3], [%define api\.token\.prefix {.*}],
[m4_bregexp([$3], [%define api\.token\.prefix "\(.*\)"], [\1])])]) [m4_bregexp([$3], [%define api\.token\.prefix {\(.*\)}], [\1])])])
m4_pushdef([AT_VARIANT_IF], m4_pushdef([AT_VARIANT_IF],
[m4_bmatch([$3], [%define api\.value\.type "?variant"?], [$1], [$2])]) [m4_bmatch([$3], [%define api\.value\.type variant], [$1], [$2])])
m4_pushdef([AT_API_prefix], m4_pushdef([AT_API_prefix],
[m4_bmatch([$3], [%define api\.prefix ".*"], [m4_bmatch([$3], [%define api\.prefix {.*}],
[m4_bregexp([$3], [%define api\.prefix "\([^""]*\)"], [\1])], [m4_bregexp([$3], [%define api\.prefix {\([^\}]*\)}], [\1])],
[yy])]) [yy])])
m4_pushdef([AT_API_PREFIX], m4_pushdef([AT_API_PREFIX],
[m4_toupper(AT_API_prefix)]) [m4_toupper(AT_API_prefix)])
@@ -205,7 +207,7 @@ m4_pushdef([AT_API_PREFIX],
m4_pushdef([AT_YYERROR_ARG_LOC_IF], m4_pushdef([AT_YYERROR_ARG_LOC_IF],
[AT_LOCATION_IF([AT_PURE_IF([m4_bmatch([$3], [AT_LOCATION_IF([AT_PURE_IF([m4_bmatch([$3],
m4_quote(m4_join([\|], m4_quote(m4_join([\|],
[%define api\.pure "?full"?], [%define api\.pure full],
[%glr-parser], [%glr-parser],
[%parse-param], [%parse-param],
[%skeleton "?glr.c"?])), [%skeleton "?glr.c"?])),
@@ -317,10 +319,29 @@ AT_LOC_POPDEF])dnl
## Generating Grammar Files. ## ## 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 # AT_DATA_SOURCE_PROLOGUE
# ------------------------ # -----------------------
# The prologue that should be included in any source code that is # The prologue that should be included in any source code that is
# meant to be compiled. # meant to be compiled. Keep atlocal.in sync (BISON_CXX_WORKS).
m4_define([AT_DATA_SOURCE_PROLOGUE], m4_define([AT_DATA_SOURCE_PROLOGUE],
[[#include <config.h> [[#include <config.h>
/* We don't need perfect functions for these tests. */ /* We don't need perfect functions for these tests. */
@@ -406,24 +427,33 @@ static
# AT_YYERROR_DEFINE # AT_YYERROR_DEFINE
# ------------------------- # -------------------------
# Must be called inside a AT_BISON_OPTION_PUSHDEFS/POPDEFS pair. # Must be called inside a AT_BISON_OPTION_PUSHDEFS/POPDEFS pair.
m4_define([AT_YYERROR_FORMALS], m4_define([AT_YYERROR_FORMALS], [AT_LANG_DISPATCH([$0], $@)])
[m4_case(AT_LANG, m4_define([AT_YYERROR_PROTOTYPE],[AT_LANG_DISPATCH([$0], $@)])
[c], [AT_YYERROR_ARG_LOC_IF([AT_YYLTYPE const * const llocp, ])AT_PARSE_PARAMS [const char *msg]])[]dnl 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], # AT_MAIN_DEFINE
[m4_case(AT_LANG, # --------------
[c], [[void ]AT_NAME_PREFIX[error (]AT_YYERROR_FORMALS[)]])[]dnl 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], [#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([[ ]AT_LOCATION_IF([[
#if defined ]AT_YYLTYPE[_IS_TRIVIAL && ]AT_YYLTYPE[_IS_TRIVIAL #if defined ]AT_YYLTYPE[_IS_TRIVIAL && ]AT_YYLTYPE[_IS_TRIVIAL
static unsigned location_print (FILE *yyo, ]AT_YYLTYPE[ const * const yylocp); static unsigned location_print (FILE *yyo, ]AT_YYLTYPE[ const * const yylocp);
@@ -432,12 +462,11 @@ static unsigned location_print (FILE *yyo, ]AT_YYLTYPE[ const * const yylocp);
# endif # endif
#endif #endif
]])[ ]])[
static AT_YYERROR_DECLARE_EXTERN])[]dnl static AT_YYERROR_DECLARE_EXTERN])
])
m4_define([AT_YYERROR_DEFINE],
[m4_case(AT_LANG, m4_define([AT_YYERROR_DEFINE(c)],
[c], [[ [[
]AT_LOCATION_IF([[ ]AT_LOCATION_IF([[
# if defined ]AT_YYLTYPE[_IS_TRIVIAL && ]AT_YYLTYPE[_IS_TRIVIAL # if defined ]AT_YYLTYPE[_IS_TRIVIAL && ]AT_YYLTYPE[_IS_TRIVIAL
/* Print *YYLOCP on YYO. */ /* Print *YYLOCP on YYO. */
@@ -478,34 +507,10 @@ AT_YYERROR_SEES_LOC_IF([[
LOCATION_PRINT (stderr, ]AT_LOC[); LOCATION_PRINT (stderr, ]AT_LOC[);
fprintf (stderr, ": ");]])[ fprintf (stderr, ": ");]])[
fprintf (stderr, "%s\n", msg); fprintf (stderr, "%s\n", msg);
}]], }]])
[c++], [[/* A C++ error reporting function. */
void
]AT_NAME_PREFIX[::parser::error (]AT_LOCATION_IF([[const location_type& l, ]])[const std::string& m)
{
std::cerr << ]AT_LOCATION_IF([l << ": " << ])[m << std::endl;
}]],
[java], [AT_LOCATION_IF([[public void yyerror (Calc.Location l, String s)
{
if (l == null)
System.err.println (s);
else
System.err.println (l + ": " + s);
}
]], [[
public void yyerror (String s)
{
System.err.println (s);
}]])],
[m4_fatal([$0: invalid language: ]AT_LANG)])dnl
])
# AT_MAIN_DEFINE m4_define([AT_MAIN_DEFINE(c)],
# --------------
m4_define([AT_MAIN_DEFINE],
[m4_case(AT_LANG,
[c],
[[#include <stdlib.h> /* getenv. */ [[#include <stdlib.h> /* getenv. */
#include <string.h> /* strcmp. */ #include <string.h> /* strcmp. */
int int
@@ -518,8 +523,27 @@ main (int argc, char const* argv[])
(void) argc; (void) argc;
(void) argv;]])[ (void) argv;]])[
return ]AT_NAME_PREFIX[parse (); return ]AT_NAME_PREFIX[parse ();
}]], }]])
[c++],
## ----- ##
## 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 (]AT_LOCATION_IF([[const location_type& l, ]])[const std::string& m)
{
std::cerr << ]AT_LOCATION_IF([l << ": " << ])[m << std::endl;
}]])
m4_define([AT_MAIN_DEFINE(c++)],
[[#include <cstdlib> // getenv. [[#include <cstdlib> // getenv.
#include <cstring> // strcmp. #include <cstring> // strcmp.
int int
@@ -533,8 +557,30 @@ main (int argc, char const* argv[])
(void) argc; (void) argc;
(void) argv;]])[ (void) argv;]])[
return p.parse (); return p.parse ();
}]], }]])
[java],
## ------ ##
## 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
System.err.println (l + ": " + s);
}
]], [[
public void yyerror (String s)
{
System.err.println (s);
}
]])])
m4_define([AT_MAIN_DEFINE(java)],
[[class input [[class input
{ {
public static void main (String args[]) throws IOException public static void main (String args[]) throws IOException
@@ -542,7 +588,8 @@ main (int argc, char const* argv[])
YYParser p = new YYParser (); YYParser p = new YYParser ();
p.parse (); p.parse ();
} }
}]])]) }]])
## --------------- ## ## --------------- ##
@@ -554,7 +601,7 @@ main (int argc, char const* argv[])
# High-level routine that may call bison several times, under different # High-level routine that may call bison several times, under different
# conditions. # 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 # shell constructs (such as redirection or pipes) that would prevent
# appending additional command-line arguments for bison. OTHER_AT_CHECK_ARGS # appending additional command-line arguments for bison. OTHER_AT_CHECK_ARGS
# are the usual remaining arguments to AT_CHECK: STATUS, STDOUT, etc. # are the usual remaining arguments to AT_CHECK: STATUS, STDOUT, etc.
@@ -707,6 +754,7 @@ AT_CHECK(m4_join([ ],
[m4_bmatch([$1], [[.]], [], [$LIBS])]), [m4_bmatch([$1], [[.]], [], [$LIBS])]),
0, [ignore], [ignore])]) 0, [ignore], [ignore])])
# AT_COMPILE_CXX(OUTPUT, [SOURCES = OUTPUT.cc]) # AT_COMPILE_CXX(OUTPUT, [SOURCES = OUTPUT.cc])
# --------------------------------------------- # ---------------------------------------------
# Compile SOURCES into OUTPUT. If the C++ compiler does not work, # Compile SOURCES into OUTPUT. If the C++ compiler does not work,
@@ -714,7 +762,7 @@ AT_CHECK(m4_join([ ],
# #
# If OUTPUT does not contain '.', assume that we are linking too, # If OUTPUT does not contain '.', assume that we are linking too,
# otherwise pass "-c"; this is a hack. The default SOURCES is OUTPUT # otherwise pass "-c"; this is a hack. The default SOURCES is OUTPUT
# with trailing .o removed, and ".cc" appended. # with trailing ".o" removed, and ".cc" appended.
m4_define([AT_COMPILE_CXX], m4_define([AT_COMPILE_CXX],
[AT_KEYWORDS(c++) [AT_KEYWORDS(c++)
AT_CHECK([$BISON_CXX_WORKS], 0, ignore, ignore) AT_CHECK([$BISON_CXX_WORKS], 0, ignore, ignore)
@@ -726,6 +774,7 @@ AT_CHECK(m4_join([ ],
[m4_bmatch([$1], [[.]], [], [$LIBS])]), [m4_bmatch([$1], [[.]], [], [$LIBS])]),
0, [ignore], [ignore])]) 0, [ignore], [ignore])])
# AT_JAVA_COMPILE(SOURCES) # AT_JAVA_COMPILE(SOURCES)
# ------------------------ # ------------------------
# Compile SOURCES into Java class files. Skip the test if java or javac # Compile SOURCES into Java class files. Skip the test if java or javac
@@ -737,6 +786,7 @@ AT_SKIP_IF([[test -z "$CONF_JAVA"]])
AT_CHECK([[$SHELL ../../../javacomp.sh ]$1], AT_CHECK([[$SHELL ../../../javacomp.sh ]$1],
[[0]], [ignore], [ignore])]) [[0]], [ignore], [ignore])])
# AT_LANG_COMPILE(OUTPUT, [SOURCES = OUTPUT.c] # AT_LANG_COMPILE(OUTPUT, [SOURCES = OUTPUT.c]
# -------------------------------------------- # --------------------------------------------
# Compile SOURCES into OUTPUT. Skip if compiler does not work. # Compile SOURCES into OUTPUT. Skip if compiler does not work.
@@ -744,13 +794,11 @@ AT_CHECK([[$SHELL ../../../javacomp.sh ]$1],
# If OUTPUT does not contain '.', assume that we are linking too, # If OUTPUT does not contain '.', assume that we are linking too,
# otherwise pass "-c"; this is a hack. The default SOURCES is OUTPUT # otherwise pass "-c"; this is a hack. The default SOURCES is OUTPUT
# with trailing .o removed, and ".c"/".cc" appended. # with trailing .o removed, and ".c"/".cc" appended.
m4_define([AT_LANG_COMPILE], m4_define([AT_LANG_COMPILE], [AT_LANG_DISPATCH([$0], $@)])
[m4_case(AT_LANG, m4_define([AT_LANG_COMPILE(c)], [AT_COMPILE([$1], [$2])])
[c], [AT_COMPILE([$1], [$2])], m4_define([AT_LANG_COMPILE(c++)], [AT_COMPILE_CXX([$1], [$2])])
[c++], [AT_COMPILE_CXX([$1], [$2])], m4_define([AT_LANG_COMPILE(java)], [AT_JAVA_COMPILE([$1.java], [$2])])
[java], [AT_JAVA_COMPILE([$1.java], [$2])],
[m4_fatal([unknown language: ]m4_defn([AT_LANG]))])[]dnl
])
# AT_FULL_COMPILE(OUTPUT, [OTHER1], [OTHER2]) # AT_FULL_COMPILE(OUTPUT, [OTHER1], [OTHER2])
# ------------------------------------------- # -------------------------------------------
@@ -759,30 +807,31 @@ m4_define([AT_LANG_COMPILE],
# OUTPUT-OTHER.c, OUTPUT-OTHER.cc, or OUTPUT-OTHER.java to OUTPUT or # 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 # OUTPUT.java along with it. Relies on AT_SKEL_CC_IF and
# AT_SKEL_JAVA_IF. # AT_SKEL_JAVA_IF.
m4_define([AT_FULL_COMPILE], m4_define([AT_FULL_COMPILE], [AT_LANG_DISPATCH([$0], $@)])
[m4_case(AT_LANG, m4_define([AT_FULL_COMPILE(c)],
[java], [AT_BISON_CHECK([-o $1.c $1.y])
[AT_BISON_CHECK([-o $1.java $1.y]) AT_LANG_COMPILE([$1],
AT_LANG_COMPILE([$1], m4_join([ ],
m4_join([ ], [$1.c],
[$1.java], m4_ifval($2, [[$1-$2.c]]),
m4_ifval($2, [[$1-$2.java]]), m4_ifval($3, [[$1-$3.c]])))])
m4_ifval($3, [[$1-$3.java]])))],
[c++], m4_define([AT_FULL_COMPILE(c++)],
[AT_BISON_CHECK([-o $1.cc $1.y]) [AT_BISON_CHECK([-o $1.cc $1.y])
AT_LANG_COMPILE([$1], AT_LANG_COMPILE([$1],
m4_join([ ], m4_join([ ],
[$1.cc], [$1.cc],
m4_ifval($2, [[$1-$2.cc]]), m4_ifval($2, [[$1-$2.cc]]),
m4_ifval($3, [[$1-$3.cc]])))], m4_ifval($3, [[$1-$3.cc]])))])
[c],
[AT_BISON_CHECK([-o $1.c $1.y]) m4_define([AT_FULL_COMPILE(java)],
AT_LANG_COMPILE([$1], [AT_BISON_CHECK([-o $1.java $1.y])
m4_join([ ], AT_LANG_COMPILE([$1],
[$1.c], m4_join([ ],
m4_ifval($2, [[$1-$2.c]]), [$1.java],
m4_ifval($3, [[$1-$3.c]])))]) m4_ifval($2, [[$1-$2.java]]),
]) m4_ifval($3, [[$1-$3.java]])))])
@@ -830,7 +879,7 @@ AT_PARSER_CHECK([./c-and-cxx])
# AT_PARSER_CHECK(COMMAND, EXIT-STATUS, EXPOUT, EXPERR, [PRE]) # 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: # Get rid of spurious messages when compiled with --coverage:
# +profiling:/[...]/lib/fprintf.gcda:Merge mismatch for summaries # +profiling:/[...]/lib/fprintf.gcda:Merge mismatch for summaries
@@ -872,16 +921,16 @@ m4_define([AT_JAVA_PARSER_CHECK],
# that Bison exits with value 0, has no stdout, and has stderr # that Bison exits with value 0, has no stdout, and has stderr
# BISON-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 # 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). # 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 # the definition of state 0 is the same as the entire value of
# TABLES-OR-LAST-STATE. # TABLES-OR-LAST-STATE.
# #
# Expand the M4 in OTHER-CHECKS to perform additional checks of the # Expand the M4 in OTHER-CHECKS to perform additional checks of the
# `.output' file, which is named `input.output', and/or grammar file, # '.output' file, which is named 'input.output', and/or grammar file,
# which is named `input.y'. # which is named 'input.y'.
# #
# Finally, compile the generated parser and then run it using # Finally, compile the generated parser and then run it using
# AT_PARSER_CHECK with PARSER-EXIT-VALUE, PARSER-STDOUT, and # AT_PARSER_CHECK with PARSER-EXIT-VALUE, PARSER-STDOUT, and
@@ -962,7 +1011,7 @@ yylex (void)
m4_if(m4_index(m4_quote($3), [no-xml]), -1, m4_if(m4_index(m4_quote($3), [no-xml]), -1,
[AT_BISON_CHECK], [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)) [0], [], m4_dquote($7))
m4_if(m4_index(m4_quote($3), [last-state]), -1, m4_if(m4_index(m4_quote($3), [last-state]), -1,
+3 -1
View File
@@ -53,6 +53,7 @@ TESTSUITE_AT = \
tests/headers.at \ tests/headers.at \
tests/input.at \ tests/input.at \
tests/java.at \ tests/java.at \
tests/javapush.at \
tests/local.at \ tests/local.at \
tests/named-refs.at \ tests/named-refs.at \
tests/output.at \ tests/output.at \
@@ -63,7 +64,8 @@ TESTSUITE_AT = \
tests/sets.at \ tests/sets.at \
tests/skeletons.at \ tests/skeletons.at \
tests/synclines.at \ tests/synclines.at \
tests/torture.at tests/torture.at \
tests/types.at
TESTSUITE = $(top_srcdir)/tests/testsuite TESTSUITE = $(top_srcdir)/tests/testsuite
+12 -6
View File
@@ -37,10 +37,11 @@ foo: {};
]AT_BISON_CHECK([$3 $1 $5], 0)[ ]AT_BISON_CHECK([$3 $1 $5], 0)[
# Ignore the files non-generated files # Ignore the files non-generated files
]AT_CHECK([find . -type f -and -not -path './$1' -and -not -path './testsuite.log' | ]AT_CHECK([[find . -type f |
sed 's,\./,,' | $PERL -ne '
sort | s,\./,,; chomp;
xargs echo], push @file, $_ unless m{^($1|testsuite.log)$};
END { print join (" ", sort @file), "\n" }']],
[], [$4 [], [$4
])[ ])[
]$6[ ]$6[
@@ -62,8 +63,13 @@ 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], AT_CHECK_OUTPUT([foo.y], [], [-dv -o foo.tab.c],
[foo.output foo.tab.c foo.tab.h]) [foo.output foo.tab.c foo.tab.h])
AT_CHECK_OUTPUT([foo.y], [], [-dv -y],
[y.output y.tab.c y.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], 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], AT_CHECK_OUTPUT([foo.y], [], [-dv -g -o foo.c],
+45 -77
View File
@@ -88,8 +88,7 @@ exp: useful;
]]) ]])
AT_BISON_CHECK([[input.y]], 0, [], AT_BISON_CHECK([[input.y]], 0, [],
[[input.y: warning: 9 nonterminals useless in grammar [-Wother] [[input.y:4.8-15: warning: nonterminal useless in grammar: useless1 [-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:5.8-15: warning: nonterminal useless in grammar: useless2 [-Wother]
input.y:6.8-15: warning: nonterminal useless in grammar: useless3 [-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:7.8-15: warning: nonterminal useless in grammar: useless4 [-Wother]
@@ -98,6 +97,7 @@ 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:10.8-15: warning: nonterminal useless in grammar: useless7 [-Wother]
input.y:11.8-15: warning: nonterminal useless in grammar: useless8 [-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] input.y:12.8-15: warning: nonterminal useless in grammar: useless9 [-Wother]
input.y: warning: 9 nonterminals useless in grammar [-Wother]
]]) ]])
AT_CHECK([[sed -n '/^Grammar/q;/^$/!p' input.output]], 0, AT_CHECK([[sed -n '/^Grammar/q;/^$/!p' input.output]], 0,
@@ -143,86 +143,64 @@ useless9: '9';
]]) ]])
AT_BISON_CHECK([[-fcaret input.y]], 0, [], AT_BISON_CHECK([[-fcaret input.y]], 0, [],
[[input.y: warning: 9 nonterminals useless in grammar [-Wother] [[input.y:6.1-8: warning: nonterminal useless in grammar: useless1 [-Wother]
input.y: warning: 9 rules useless in grammar [-Wother]
input.y:6.1-8: warning: nonterminal useless in grammar: useless1 [-Wother]
useless1: '1'; useless1: '1';
^^^^^^^^ ^^^^^^^^
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 [-Wother]
useless3: '3';
^^^^^^^^
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 [-Wother]
useless5: '5';
^^^^^^^^
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 [-Wother]
useless7: '7';
^^^^^^^^
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 [-Wother]
useless9: '9';
^^^^^^^^
input.y:6.11-13: warning: rule useless in grammar [-Wother] input.y:6.11-13: warning: rule useless in grammar [-Wother]
useless1: '1'; useless1: '1';
^^^ ^^^
input.y:7.1-8: warning: nonterminal useless in grammar: useless2 [-Wother]
useless2: '2';
^^^^^^^^
input.y:7.11-13: warning: rule useless in grammar [-Wother] input.y:7.11-13: warning: rule useless in grammar [-Wother]
useless2: '2'; useless2: '2';
^^^ ^^^
input.y:8.1-8: warning: nonterminal useless in grammar: useless3 [-Wother]
useless3: '3';
^^^^^^^^
input.y:8.11-13: warning: rule useless in grammar [-Wother] input.y:8.11-13: warning: rule useless in grammar [-Wother]
useless3: '3'; useless3: '3';
^^^ ^^^
input.y:9.1-8: warning: nonterminal useless in grammar: useless4 [-Wother]
useless4: '4';
^^^^^^^^
input.y:9.11-13: warning: rule useless in grammar [-Wother] input.y:9.11-13: warning: rule useless in grammar [-Wother]
useless4: '4'; useless4: '4';
^^^ ^^^
input.y:10.1-8: warning: nonterminal useless in grammar: useless5 [-Wother]
useless5: '5';
^^^^^^^^
input.y:10.11-13: warning: rule useless in grammar [-Wother] input.y:10.11-13: warning: rule useless in grammar [-Wother]
useless5: '5'; useless5: '5';
^^^ ^^^
input.y:11.1-8: warning: nonterminal useless in grammar: useless6 [-Wother]
useless6: '6';
^^^^^^^^
input.y:11.11-13: warning: rule useless in grammar [-Wother] input.y:11.11-13: warning: rule useless in grammar [-Wother]
useless6: '6'; useless6: '6';
^^^ ^^^
input.y:12.1-8: warning: nonterminal useless in grammar: useless7 [-Wother]
useless7: '7';
^^^^^^^^
input.y:12.11-13: warning: rule useless in grammar [-Wother] input.y:12.11-13: warning: rule useless in grammar [-Wother]
useless7: '7'; useless7: '7';
^^^ ^^^
input.y:13.1-8: warning: nonterminal useless in grammar: useless8 [-Wother]
useless8: '8';
^^^^^^^^
input.y:13.11-13: warning: rule useless in grammar [-Wother] input.y:13.11-13: warning: rule useless in grammar [-Wother]
useless8: '8'; useless8: '8';
^^^ ^^^
input.y:14.1-8: warning: nonterminal useless in grammar: useless9 [-Wother]
useless9: '9';
^^^^^^^^
input.y:14.11-13: warning: rule useless in grammar [-Wother] input.y:14.11-13: warning: rule useless in grammar [-Wother]
useless9: '9'; useless9: '9';
^^^ ^^^
input.y: warning: 9 nonterminals useless in grammar [-Wother]
input.y: warning: 9 rules useless in grammar [-Wother]
]]) ]])
AT_BISON_CHECK([[input.y]], 0, [],
[[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]
input.y:7.1-8: warning: nonterminal useless in grammar: useless2 [-Wother]
input.y:8.1-8: warning: nonterminal useless in grammar: useless3 [-Wother]
input.y:9.1-8: warning: nonterminal useless in grammar: useless4 [-Wother]
input.y:10.1-8: warning: nonterminal useless in grammar: useless5 [-Wother]
input.y:11.1-8: warning: nonterminal useless in grammar: useless6 [-Wother]
input.y:12.1-8: warning: nonterminal useless in grammar: useless7 [-Wother]
input.y:13.1-8: warning: nonterminal useless in grammar: useless8 [-Wother]
input.y:14.1-8: warning: nonterminal useless in grammar: useless9 [-Wother]
input.y:6.11-13: warning: rule useless in grammar: useless1: '1' [-Wother]
input.y:7.11-13: warning: rule useless in grammar: useless2: '2' [-Wother]
input.y:8.11-13: warning: rule useless in grammar: useless3: '3' [-Wother]
input.y:9.11-13: warning: rule useless in grammar: useless4: '4' [-Wother]
input.y:10.11-13: warning: rule useless in grammar: useless5: '5' [-Wother]
input.y:11.11-13: warning: rule useless in grammar: useless6: '6' [-Wother]
input.y:12.11-13: warning: rule useless in grammar: useless7: '7' [-Wother]
input.y:13.11-13: warning: rule useless in grammar: useless8: '8' [-Wother]
input.y:14.11-13: warning: rule useless in grammar: useless9: '9' [-Wother]
]])
AT_CHECK([[sed -n '/^Grammar/q;/^$/!p' input.output]], 0, AT_CHECK([[sed -n '/^Grammar/q;/^$/!p' input.output]], 0,
[[Nonterminals useless in grammar [[Nonterminals useless in grammar
@@ -298,33 +276,23 @@ non_productive: non_productive useless_token
]]) ]])
AT_BISON_CHECK([[-fcaret not-reduced.y]], 0, [], AT_BISON_CHECK([[-fcaret not-reduced.y]], 0, [],
[[not-reduced.y: warning: 2 nonterminals useless in grammar [-Wother] [[not-reduced.y:11.6-19: warning: nonterminal useless in grammar: non_productive [-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 [-Wother]
| non_productive { /* A non productive action. */ } | non_productive { /* A non productive action. */ }
^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^
not-reduced.y:11.6-57: warning: rule useless in grammar [-Wother] not-reduced.y:11.6-57: warning: rule useless in grammar [-Wother]
| non_productive { /* A non productive action. */ } | non_productive { /* A non productive action. */ }
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
not-reduced.y:14.1-13: warning: nonterminal useless in grammar: not_reachable [-Wother]
not_reachable: useful { /* A not reachable action. */ }
^^^^^^^^^^^^^
not-reduced.y:14.16-56: warning: rule useless in grammar [-Wother] not-reduced.y:14.16-56: warning: rule useless in grammar [-Wother]
not_reachable: useful { /* A not reachable action. */ } not_reachable: useful { /* A not reachable action. */ }
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
not-reduced.y:17.17-18.63: warning: rule useless in grammar [-Wother] not-reduced.y:17.17-18.63: warning: rule useless in grammar [-Wother]
non_productive: non_productive useless_token non_productive: non_productive useless_token
^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
]]) not-reduced.y: warning: 2 nonterminals useless in grammar [-Wother]
AT_BISON_CHECK([[not-reduced.y]], 0, [],
[[not-reduced.y: warning: 2 nonterminals useless in grammar [-Wother]
not-reduced.y: warning: 3 rules 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-reduced.y:11.6-19: warning: nonterminal useless in grammar: non_productive [-Wother]
not-reduced.y:11.6-57: warning: rule useless in grammar: exp: non_productive [-Wother]
not-reduced.y:14.16-56: warning: rule useless in grammar: not_reachable: useful [-Wother]
not-reduced.y:17.17-18.63: warning: rule useless in grammar: non_productive: non_productive useless_token [-Wother]
]]) ]])
AT_CHECK([[sed -n '/^Grammar/q;/^$/!p' not-reduced.output]], 0, AT_CHECK([[sed -n '/^Grammar/q;/^$/!p' not-reduced.output]], 0,
@@ -393,13 +361,13 @@ indirection: underivable;
]]) ]])
AT_BISON_CHECK([[input.y]], 0, [], AT_BISON_CHECK([[input.y]], 0, [],
[[input.y: warning: 2 nonterminals useless in grammar [-Wother] [[input.y:5.15-25: warning: nonterminal useless in grammar: underivable [-Wother]
input.y: warning: 3 rules useless in grammar [-Wother] input.y:5.15-25: warning: rule 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:6.14-24: warning: nonterminal useless in grammar: indirection [-Wother]
input.y:5.15-25: warning: rule useless in grammar: exp: underivable [-Wother] input.y:6.14-24: warning: rule useless in grammar [-Wother]
input.y:6.14-24: warning: rule useless in grammar: underivable: indirection [-Wother] input.y:7.14-24: warning: rule useless in grammar [-Wother]
input.y:7.14-24: warning: rule useless in grammar: indirection: underivable [-Wother] input.y: warning: 2 nonterminals useless in grammar [-Wother]
input.y: warning: 3 rules useless in grammar [-Wother]
]]) ]])
AT_CHECK([[sed -n '/^Grammar/q;/^$/!p' input.output]], 0, AT_CHECK([[sed -n '/^Grammar/q;/^$/!p' input.output]], 0,
@@ -429,9 +397,9 @@ exp: exp;
]]) ]])
AT_BISON_CHECK([[input.y]], 1, [], AT_BISON_CHECK([[input.y]], 1, [],
[[input.y: warning: 2 nonterminals useless in grammar [-Wother] [[input.y:3.1-3: fatal error: start symbol exp does not derive any sentence
input.y: warning: 2 nonterminals useless in grammar [-Wother]
input.y: warning: 2 rules 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
]]) ]])
AT_CLEANUP AT_CLEANUP
@@ -965,7 +933,7 @@ S: 'a' A 'a'
A: 'a' 'a' B A: 'a' 'a' B
; ;
B: 'a' B: 'a'
| %prec 'a' | %empty %prec 'a'
; ;
c: 'a' 'a' 'b' c: 'a' 'a' 'b'
| A | A
@@ -1565,8 +1533,8 @@ a: 'a' ;
and multiple reductions. The first reduction has more lookaheads than the and multiple reductions. The first reduction has more lookaheads than the
second, so the first should always be preferred as the default reduction if second, so the first should always be preferred as the default reduction if
enabled. The second reduction has one lookahead. */ enabled. The second reduction has one lookahead. */
b: ; b: %empty;
c: ; c: %empty;
]], ]],
dnl Visit each state mentioned above. dnl Visit each state mentioned above.
[['a', 'a']], [['a', 'a']],
+15 -15
View File
@@ -263,11 +263,11 @@ AT_CHECK([cat input.output], [],
0 $accept: expr $end 0 $accept: expr $end
1 $@1: /* empty */ 1 $@1: %empty
2 expr: 'a' $@1 'b' 2 expr: 'a' $@1 'b'
3 $@2: /* empty */ 3 $@2: %empty
4 expr: $@2 'c' 4 expr: $@2 'c'
@@ -373,13 +373,13 @@ AT_DATA([input.y],
%token <operator> LE 134 "<=" %token <operator> LE 134 "<="
%left OR "<=" %left OR "<="
%% %%
exp: ; exp: %empty;
%% %%
]]) ]])
AT_BISON_CHECK([-v -o input.c input.y], 0, [], AT_BISON_CHECK([-v -Wall -o input.c input.y], 0, [],
[[input.y:1.29-32: warning: useless associativity for "||" [-Wother] [[input.y:3.1-5: warning: useless precedence and associativity for "||" [-Wprecedence]
input.y:2.29-32: warning: useless associativity for "<=" [-Wother] input.y:3.1-5: warning: useless precedence and associativity for "<=" [-Wprecedence]
]]) ]])
AT_CLEANUP AT_CLEANUP
@@ -573,7 +573,7 @@ AT_CHECK([cat input.output], 0,
2 CONST_DEC_LIST: CONST_DEC 2 CONST_DEC_LIST: CONST_DEC
3 | 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 ';' 5 CONST_DEC: $@1 undef_id_tok '=' const_id_tok ';'
@@ -721,7 +721,7 @@ AT_KEYWORDS([report])
AT_DATA([input.y], AT_DATA([input.y],
[[%% [[%%
statement: struct_stat; statement: struct_stat;
struct_stat: /* empty. */ | if else; struct_stat: %empty | if else;
if: "if" "const" "then" statement; if: "if" "const" "then" statement;
else: "else" statement; else: "else" statement;
%% %%
@@ -869,7 +869,7 @@ type: DATA
| INVALID | INVALID
; ;
body: /* empty */ body: %empty
| body member | body member
; ;
@@ -929,7 +929,7 @@ $1
%token B %token B
%% %%
program: /* empty */ program: %empty
| program e ';' | program e ';'
| program error ';'; | program error ';';
@@ -1145,15 +1145,15 @@ sr_conflict:
]AT_YYLEX_DEFINE([{ 1, 2, 3, 0 }])[ ]AT_YYLEX_DEFINE([{ 1, 2, 3, 0 }])[
]AT_MAIN_DEFINE[ ]AT_MAIN_DEFINE[
]]) ]])
AT_BISON_OPTION_POPDEFS
AT_BISON_CHECK([[-o input.c input.y]], [[0]],, AT_BISON_CHECK([[-Wall -o input.c input.y]], [[0]],,
[[input.y:24.5-19: warning: rule useless in parser due to conflicts: start: start [-Wother] [[input.y:18.1-5: warning: useless precedence and associativity for TK1 [-Wprecedence]
input.y:28.5-19: warning: rule useless in parser due to conflicts: sr_conflict: TK2 "tok alias" [-Wother] input.y:24.5-19: warning: rule useless in parser due to conflicts [-Wother]
input.y:18.7-9: warning: useless associativity for TK1 [-Wother] input.y:28.5-19: warning: rule useless in parser due to conflicts [-Wother]
]]) ]])
AT_COMPILE([[input]]) AT_COMPILE([[input]])
AT_PARSER_CHECK([[./input]]) AT_PARSER_CHECK([[./input]])
AT_BISON_OPTION_POPDEFS
AT_CLEANUP AT_CLEANUP
+5 -5
View File
@@ -86,7 +86,7 @@ AT_CHECK([[cat sets]], [],
0 e $end 0 e $end
e derives e derives
1 'e' 1 'e'
2 /* empty */ 2 %empty
NULLABLE NULLABLE
$accept: no $accept: no
e: yes e: yes
@@ -100,10 +100,10 @@ FDERIVES
$accept derives $accept derives
0 e $end 0 e $end
1 'e' 1 'e'
2 /* empty */ 2 %empty
e derives e derives
1 'e' 1 'e'
2 /* empty */ 2 %empty
]]) ]])
AT_CLEANUP AT_CLEANUP
@@ -113,7 +113,7 @@ AT_CLEANUP
## Broken Closure. ## ## 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 # It resulted in bison dumping core on the following grammar (the
# computation of FIRSTS uses TC). It managed to produce a pretty # computation of FIRSTS uses TC). It managed to produce a pretty
# exotic closure: # exotic closure:
@@ -263,7 +263,7 @@ AT_CLEANUP
# In some weird cases Bison could compute an incorrect final state # In some weird cases Bison could compute an incorrect final state
# number. This happens only if the $end token is used in the user # number. This happens only if the $end token is used in the user
# grammar, which is a very suspicious accidental feature introduced as # 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"'. # "end of file"'.
AT_SETUP([Accept]) AT_SETUP([Accept])
+4 -4
View File
@@ -186,10 +186,10 @@ start: ;
]]) ]])
AT_BISON_CHECK([[input1.y]], [[1]], [[]], AT_BISON_CHECK([[input1.y]], [[1]], [[]],
[[input1.y: warning: foow fubar [-Wother] [[fooc.y:1.1-10.5: error: foocat fubar
foow.y:2.3-5.3: warning: foowat fubar [-Wother] foow.y:2.3-5.3: warning: foowat fubar [-Wother]
input1.y: warning: foow fubar [-Wother]
input1.y: error: fooc fubar input1.y: error: fooc fubar
fooc.y:1.1-10.5: error: foocat fubar
input1.y: fatal error: foof fubar input1.y: fatal error: foof fubar
]]) ]])
@@ -276,8 +276,8 @@ start: ;
]]) ]])
AT_BISON_CHECK([[input2.y]], [[1]], [[]], AT_BISON_CHECK([[input2.y]], [[1]], [[]],
[[input2.y: warning: morning [-Wother] [[foo.y:1.5-6: fatal error: M4 should exit immediately here
foo.y:1.5-6: fatal error: M4 should exit immediately here input2.y: warning: morning [-Wother]
]]) ]])
AT_CLEANUP AT_CLEANUP
+1 -1
View File
@@ -23,7 +23,7 @@ AT_BANNER([[User Actions.]])
# -------------------------- # --------------------------
# Compile FILE expecting an error, and save in the file stdout the # Compile FILE expecting an error, and save in the file stdout the
# normalized output. Ignore the exit status, since some compilers # 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. # errors.
m4_define([AT_SYNCLINES_COMPILE], m4_define([AT_SYNCLINES_COMPILE],
[AT_CHECK([$CC $CFLAGS $CPPFLAGS -c $1], [ignore], [], [stderr]) [AT_CHECK([$CC $CFLAGS $CPPFLAGS -c $1], [ignore], [], [stderr])
+9 -5
View File
@@ -35,6 +35,9 @@ m4_include([sets.at])
# Testing grammar reduction. # Testing grammar reduction.
m4_include([reduce.at]) m4_include([reduce.at])
# Testing conflicts detection and resolution.
m4_include([conflicts.at])
# Testing that #lines are correct. # Testing that #lines are correct.
m4_include([synclines.at]) m4_include([synclines.at])
@@ -44,8 +47,8 @@ m4_include([headers.at])
# Testing that user actions are properly performed. # Testing that user actions are properly performed.
m4_include([actions.at]) m4_include([actions.at])
# Testing conflicts detection and resolution. # Testing semantic types support.
m4_include([conflicts.at]) m4_include([types.at])
# Fulling testing (compilation and execution of the parser) on calc. # Fulling testing (compilation and execution of the parser) on calc.
m4_include([calc.at]) m4_include([calc.at])
@@ -60,17 +63,18 @@ m4_include([existing.at])
# Some old bugs. # Some old bugs.
m4_include([regression.at]) m4_include([regression.at])
# Push parsing specific tests.
m4_include([push.at])
# Some C++ specific tests. # Some C++ specific tests.
m4_include([c++.at]) m4_include([c++.at])
# And some Java specific tests. # And some Java specific tests.
m4_include([java.at]) m4_include([java.at])
m4_include([javapush.at])
# GLR tests: # GLR tests:
# C++ types, simplified # C++ types, simplified
m4_include([cxx-type.at]) m4_include([cxx-type.at])
# Regression tests # Regression tests
m4_include([glr-regression.at]) m4_include([glr-regression.at])
# Push parsing specific tests.
m4_include([push.at])

Some files were not shown because too many files have changed in this diff Show More