Compare commits

...
226 Commits
Author SHA1 Message Date
Akim Demaille 10acc148bb version 3.4.90
* NEWS: Record release date.
2019-10-29 21:41:00 +01:00
Akim Demaille 28f1e1546c C++: finish propagating the unsigned->signed conversion in locations
* data/skeletons/location.cc: Remove the u (for unsigned) suffix from
the initial line and column.
* NEWS: AFAICT, only C++ backends have their location types changed.
2019-10-29 09:15:25 +01:00
Akim Demaille c53b379784 style: fix cpp indentation
Reported by syntax-check.

* src/system.h: here.
2019-10-29 09:00:46 +01:00
Akim Demaille fead28d9e3 style: glr.c: comment changes
* data/skeletons/glr.c: here.
2019-10-29 08:59:18 +01:00
Akim Demaille 7e0b50c524 CI: pass -O1 to GCC8 with sanitizers
This build never finishes in the 50min credit given by Travis.  See if
with optimizations it works better.

* .travis.yml: here.
2019-10-26 10:39:01 +02:00
Akim Demaille 8228d96d33 reader: reduce the "scope" of global variables
We have too many global variables, adding structure would help.  For a
start, let's hide some of the variables closer to their usage.

* src/getargs.c, src/files.h (current_file): Move to...
* src/scan-gram.c: here.
* src/scan-gram.h (gram_in, gram__flex_debug): Remove, make them
private to the scanner.
* src/reader.h, src/reader.c (reader): Take a grammar file as argument.
Move the handling of scanner variables to...
* src/scan-gram.l (gram_scanner_open, gram_scanner_close): here.
(gram_scanner_initialize): Remove, replaced by gram_scanner_open.
* src/main.c: Adjust.
2019-10-26 10:39:01 +02:00
Akim Demaille a5fc4e3b44 regen 2019-10-26 10:39:01 +02:00
Akim Demaille 3be912e4af parser: use grammar_file instead of current_file
* src/parse-gram (%initial-action): here.
(handle_skeleton): Don't depend on the current file name to look for
"local" skeletons (subject to changes coming from "#lines"): depend
only on the initial file name, the one given on the command line.
2019-10-26 10:38:39 +02:00
Akim Demaille 4b4e532748 diagnostics: use grammar_file instead of current_file
Currently there are two globals denoting the input file: grammar_file
is the one from the command line, and current_file which might change
because of #line.  Use only the former.

* src/complain.c (error_message): here.
* tests/diagnostics.at: Adjust.
2019-10-26 09:11:40 +02:00
Akim Demaille 6e7d8ba6a7 reader: let symtab deal with the symbols
* src/reader.c (reader): Move the setting up of the builtin symbols to...
* src/symtab.c (symbols_new): here.
2019-10-25 07:48:07 +02:00
Akim Demaille c680300a29 style: remove incorrect comment
Reported by Paul Eggert.

* src/system.h: here.
2019-10-25 07:41:38 +02:00
Akim Demaille 0cbefb71e8 lalr1.cc: fix previous commit: printing of state numbers
* data/skeletons/lalr1.cc: Printing a char prints... a char.
Print ints instead.
2019-10-24 23:02:26 +02:00
Akim Demaille 402332c4b6 lalr1.cc: use computed state types
This skeleton uses a single stack of state structures, so it is less
likely to benefit from a stack size reduction than yacc.c (which uses
several stacks: state number, value and location).  But it will reduce
the size of the LAC stack.

This skeleton was already using int for state numbers, so, contrary to
yacc.c, this brings nothing for large automata.

Overall, it is still nicer to make the skeletons alike.

* data/skeletons/lalr1.cc (state_type): Here.
2019-10-24 18:16:01 +02:00
kaneko yandAkim Demaille aa244fc5fe README: Fix a typo
* README: Fix a typo. Git command name is submodule.
2019-10-24 18:13:17 +02:00
Akim Demaille 719395c9cd examples: fix missing dependencies
Reported by Thomas Petazzoni.
https://lists.gnu.org/archive/html/bug-bison/2019-08/msg00000.html

* examples/c/reccalc/local.mk: Complete dependencies, including for
earlier versions of Automake (for sake of our CI, on top of Ubuntu
Xenial/Bionic, which feature only Automake 1.15).
(%D%/scan.c %D%/scan.h): Upgrade to the full version provided in
Automake's documentation.
2019-10-24 18:01:53 +02:00
Akim Demaille fa9871a2fb diagnostics: simplify location handling
Locations start at line 1.  Don't accept line 0.

* src/location.c (location_print): Don't print locations with line 0.
(location_caret): Simplify.
2019-10-24 18:00:43 +02:00
Akim Demaille 76597d01f3 build: reenable -Wtype-limits
See https://lists.gnu.org/archive/html/bug-bison/2019-10/msg00061.html
to https://lists.gnu.org/archive/html/bug-bison/2019-10/msg00073.html.

Paul Eggert's changes in gnulib do fix the issue for modern GCCs (7,
8, 9) on macOS.  Unfortunately these warnings are back on the
CI (GNU/Linux) with GCC 4.6, 4.7, (not 4.8) and 4.9.

Disable the warning locally.

* configure.ac (warn_common, warn_tests): Remove -Wtype-limits.
* src/system.h (IGNORE_TYPE_LIMITS_BEGIN, IGNORE_TYPE_LIMITS_END): New.
* src/InadequacyList.c, src/parse-gram.c, src/parse-gram.y,
* src/symtab.c: Use it.
2019-10-24 08:50:14 +02:00
Akim Demaille bc5efb558d build: remove dmalloc support
Today sanitizers are a better alternative.

* m4/dmalloc.m4: Remove.
* configure.ac, src/system.h: Adjust.
2019-10-24 07:22:17 +02:00
Akim Demaille 17e21f6158 gitignore: update 2019-10-23 23:09:56 +02:00
Paul Eggert 6ef8513e7c build: update gnulib submodule to latest 2019-10-23 13:44:58 -07:00
Yuichiro KanekoandAkim Demaille 3945beb1d2 style: update comment in reader.c
rrhs and rlhs were removed by b2ed6e5826.

* src/reader.c (packgram): Update comment.
2019-10-23 08:32:06 +02:00
kaneko yandAkim Demaille c86b7815fc yacc.c: fix a typo
* data/skeletons/yacc.c (yysetstate): fix comment.
2019-10-22 19:05:02 +02:00
Akim Demaille 048730c691 style: pacify syntax-check
* doc/.gitignore, src/complain.c, src/getargs.c,
* src/output.c: here.
2019-10-22 10:40:12 +02:00
Akim Demaille ec64a0bc7e main: also free memory on errors
* src/derives.c (derives_free): Beware of NULL.
* src/main.c (main): Let the 'finish' label include memory release.
2019-10-21 17:18:32 +02:00
Akim Demaille d6fe39cd18 gnulib: update
To get bitset_free accept NULL.  See
https://lists.gnu.org/archive/html/bug-gnulib/2019-10/msg00054.html
2019-10-21 17:18:32 +02:00
Akim Demaille d76ea5ce06 style: reduce scope in derives
* src/derives.c: here.
And prefer prefix to postfix increment.
2019-10-21 17:18:32 +02:00
Akim Demaille fdef997432 build: disable -Wtautological-constant-out-of-range-compare
Also see e31f92495c and
https://lists.gnu.org/archive/html/bug-bison/2019-10/msg00061.html

* configure.ac (warn_common): Disable
-Wtautological-constant-out-of-range-compare.
(warn_tests): Restore it.
2019-10-21 10:35:01 +02:00
Akim Demaille 0073b5ea5f CI: formatting changes
* .travis.yml: Use the single line form of lists, when reduced to a
singletons.
2019-10-21 08:53:07 +02:00
Akim Demaille 717be0a0f0 CI: rename jobs
* .travis.yml (compile, test): Rename as...
(dist, check): these, which are more traditional for GNU projects.
2019-10-21 08:53:07 +02:00
Akim Demaille c6e4b260e0 doc: update README
* README: Be clearer that README-hacking _must_ be read.
Convert to Markdown.
2019-10-21 08:53:06 +02:00
Akim Demaille 8b87da8d12 bootstrap: relieve developpers from Gettext version mismatch issues
* .travis.yml (compile): Move the workaround from here...
* bootstrap.conf (bootstrap_epilogue): to there.
2019-10-21 08:38:03 +02:00
Akim Demaille 41b1f828ae tests: beware of GCC9 warnings in push mode
This is really weird: GCC points to the LHS of the assignment...

    260. headers.at:184: testing Sane headers: api.pure api.push-pull=both ...
    tests/headers.at:184: COLUMNS=1000; export COLUMNS;  bison --color=no -fno-caret -d -o input.c input.y
    tests/headers.at:184: $CC $CFLAGS $CPPFLAGS  -c -o input.o input.c
    stderr:
    input.c: In function 'yyparse':
    input.c:1276:16: error: 'yylval' may be used uninitialized in this function [-Werror=maybe-uninitialized]
     1276 |         yylval = *yypushed_val;
          |         ~~~~~~~^~~~~~~~~~~~~~~
    input.c: In function 'yypull_parse':
    input.c:1276:16: error: 'yylval' may be used uninitialized in this function [-Werror=maybe-uninitialized]
     1276 |         yylval = *yypushed_val;
          |         ~~~~~~~^~~~~~~~~~~~~~~
    cc1: all warnings being treated as errors
    stdout:
    tests/headers.at:184: exit code was 1, expected 0

See also d87c8ac79a
and 9645a2b20e.

* tests/headers.at (Several parsers, Several parsers): Disable these
warnings when in push parser.
2019-10-20 23:01:27 +02:00
Akim Demaille 4e0de4df8c CI: try GCC9 and Clang9
The logs show:

    Disallowing sources: llvm-toolchain-bionic-8, ubuntu-toolchain-r-test
    To add unlisted APT sources, follow instructions in
    https://docs.travis-ci.com/user/installing-dependencies#Installing-Packages-with-the-APT-Addon

* .travis.yml: Remove a few apt sources which are ignored in
Bionic (e.g., see
https://github.com/travis-ci/apt-source-safelist/issues/410).
Where needed, use sources/sourceline instead.
Also, don't use -DNDEBUG with older builds.
2019-10-20 17:57:28 +02:00
Akim Demaille 97d6da0c5b parser: clarify version checking
* src/parse-gram.y: Use the same conventions for gnulib as elsewhere:
<header.h>.
(str_to_version): New.
(handle_require): Use it.
Prefer < to >.
2019-10-20 17:57:28 +02:00
Akim Demaille e31f92495c build: disable -Wtype-limits, except in the test suite
The current implementation of lib/intprops.h results in "unsigned < 0"
comparisons, which triggers warnings.  See

https://lists.gnu.org/archive/html/bug-bison/2019-10/msg00061.html

* configure.ac (warn_common): Disable -Wtype-limits.
(warn_tests): Restore it.
2019-10-20 08:55:44 +02:00
Paul Eggert 54c5d5d1b4 c++: port to Sun C++ 5.12
The documentation for Oracle Solaris Studio 12.3 (Sun C++ 5.12
2011/11/16) says it supports C++03.  This compiler rejects the
location.cc use of std::max for some reason; I don’t know why
since I don’t use C++ as a rule.  The simplest workaround is to
open-code ‘max’.
* data/skeletons/location.cc (add_):
Do max by hand rather than relying on std::max.
Don’t include <algorithm.h>; no longer needed.
2019-10-17 12:25:05 -07:00
Paul Eggert 693e69f289 regen 2019-10-17 11:51:20 -07:00
Paul Eggert 5c2c9fcb17 tests: port to Solaris 10 grep
* tests/scanner.at (Token numbers: $1): Use $EGREP, not grep -E.
2019-10-17 11:51:20 -07:00
Paul Eggert 071f43d5b7 tests: port to Solaris 10 sed
As documented in the Autoconf manual, Solaris 10 sed rejects
script labels contianing more than 7 characters.  POSIX requires
support for at least 8 characters, but we might as well be portable
to Solaris 10 which is still supported.
* tests/local.at (AT_SETS_CHECK): Use only the first 7 characters
in sed labels.
2019-10-17 11:51:20 -07:00
Paul Eggert 8a4ec5d4e4 bison: check for int overflow in token numbers
* src/symtab.c: Include intprops.h
(symbol_user_token_number_set): Don’t allow user_token_number ==
INT_MAX because too much other code adds 1 to the user token number.
(symbols_token_translations_init): Complain on integer overflow
instead of indulging in undefined behavior.
2019-10-17 11:51:20 -07:00
Paul Eggert 052215a138 bison: check for int overflow when scanning
* src/scan-gram.l: Include errno.h, for errno.
(scan_integer, handle_syncline): Check for integer overflow.
* tests/input.at (too-large.y): Adjust to match new diagnostics.
2019-10-17 11:51:20 -07:00
Paul Eggert 15c1b913cf bison: check version numbers more carefully
* src/parse-gram.y: Include intprops.h.
(handle_require): Don’t indulge in undefined behavior if the major
or minor number is out of range.  Instead, check that the
resulting value is nonnegative, fits in int, and that the minor
number is less than 100.  Also, check that a number was parsed.
2019-10-17 11:51:20 -07:00
Paul Eggert 83c9051a64 c: port YY_ATTRIBUTE_UNUSED to Sun C 5.12
Sun C 5.12 defines __SUNPRO_C to 0x5120 but diagnoses
‘__attribute__ ((__unused__))’.  Change the ifdefs to use
the same method as Gnulib in this area.
* data/skeletons/c.m4 (YY_ATTRIBUTE): Remove, since
not all attributes were added in the same compiler version.
(YY_ATTRIBUTE_PURE, YY_ATTRIBUTE_UNUSED):
Use specific GCC version for each attribute.
Pay no attention to __SUNPRO_C.
* tests/headers.at (Several parsers): Tighten tests accordingly.
2019-10-17 11:51:20 -07:00
Paul Eggert 7a557ee7fe c: improve port of stdint.h usage to pre-C99
Oracle Solaris Studio 12.3 (Sun C 5.12 2011/11/16) by default does
not conform to C99; it defines __STDC_VERSION__ to be 199409L, so
the Bison code does not include <stdint.h> (not required by C89
amendment 1) even though this compiler does have <stdint.h>.  On
this platform <limits.h> defines INT_LEAST8_MAX (POSIX allows
this) so the skeleton got confused and thought that <stdint.h> had
been included even though it wasn’t.
* data/skeletons/c.m4 (b4_c99_int_type_define) [!__PTRDIFF_MAX__]:
Always include <limits.h>.
(YY_STDINT_H): Define when <stdint.h> was included.
All uses of expressions like ‘defined INT_LEAST8_MAX’ changed to
‘defined YY_STDINT_H’, since Sun C 5.12 <limits.h> defines macros
like INT_LEAST8_MAX but does not declare types like int_least8_t.
2019-10-17 11:51:20 -07:00
Paul Eggert 08dd5e9feb gnulib:update 2019-10-17 11:51:20 -07:00
Paul Eggert 68cc2631a4 autoconf:update 2019-10-17 11:51:20 -07:00
Akim Demaille b47340982b TODO: more updates 2019-10-15 08:40:50 +02:00
Akim Demaille ee35055b49 TODO: update 2019-10-15 07:28:33 +02:00
Akim Demaille e5cbac98b6 yacc: rename types for states
* data/skeletons/yacc.c (yy_state_num): Rename as...
(yy_state_t): this.
(yy_state_fast_t): New.
Use it.
2019-10-15 07:02:26 +02:00
Akim Demaille d563a01709 glr: style changes
* data/skeletons/glr.c (yytnamerr): here.
(yyprocessOneStack): Initialize variables.
2019-10-15 07:02:26 +02:00
Akim Demaille a428a9fa6c yacc: style changes
* data/skeletons/yacc.c: Move call to lac discard to clarify the
shifting of the token.
Like in lalr1.cc.
2019-10-15 07:02:26 +02:00
Akim Demaille 2a0185b693 tests: avoid $(...)
Reported by Paul Eggert.

* tests/local.at (AT_DATA_NO_FINAL_EOL): here.
2019-10-15 07:01:06 +02:00
Akim Demaille ab3621678a tests: use a portable 'truncate' implementation
Suggested by Paul Eggert.
https://lists.gnu.org/archive/html/bison-patches/2019-10/msg00044.html

* tests/local.at (AT_DATA_NO_FINAL_EOL): Use dd instead of perl.
2019-10-14 07:58:36 +02:00
Akim Demaille 8631f35bf9 tests: factor the generation of files without the final eol
AFAICT Autotest 2.69 still does not support AT_DATA without the final
eol.

* tests/local.at (AT_DATA_NO_FINAL_EOL): New.
* tests/input.at: Use it.
2019-10-13 09:55:44 +02:00
Akim Demaille c483b6593f tests: refactor the handling of Perl
Let's make a difference between places where Perl is required for the
test (AT_PERL_REQUIRE), and the places where it's used to run the
test, but it's not not to run the test (AT_PERL_CHECK).

* tests/local.at (AT_REQUIRE): New.
(AT_PERL_CHECK, AT_PERL_REQUIRE): New.
Use them where appropriate.

* tests/local.mk ($(TESTSUITE)): Beware not to start the line with
'-pi' if Perl is empty, as Make understands this as "it's ok to fail".
Which it is not.
2019-10-13 09:22:05 +02:00
Akim Demaille 59cb1f421c d: comment changes
* data/skeletons/lalr1.d: Here.
2019-10-12 12:11:42 +02:00
Akim Demaille d9d37a1196 i18n: don't push too hard for '…'
Suggested by Paul Eggert.

* src/location.c (ellipsis): Clarify comment for translators.
2019-10-12 10:43:53 +02:00
Akim Demaille c3db1394a1 regen 2019-10-11 08:52:04 +02:00
Akim Demaille 2c20ae9b41 glr: display line numbers in traces
Suggested by Lars Maier.

* data/skeletons/glr.c: Also display rule locations when rules are
deferred, and rejected.
2019-10-11 08:38:24 +02:00
Akim Demaille 0c56c195e0 tests: be really robust to Perl missing
My previous tests (with ./configure PERL=false) have been fooled by
configure, that managed to find perl anyway.  This time, I ran this on
a Fedora in Docker, without Perl.

* tests/calc.at, tests/diagnostics.at, tests/headers.at,
* tests/input.at, tests/local.at, tests/named-refs.at,
* tests/output.at, tests/regression.at, tests/skeletons.at,
* tests/synclines.at, tests/torture.at: Don't require Perl.
2019-10-11 06:53:45 +02:00
Akim Demaille 3dd2ae4415 configure: perl is not required
But it's used in various places, including in some tests.

* configure.ac: here.
2019-10-10 21:57:50 +02:00
Akim Demaille d50df39f1a news: update 2019-10-10 21:57:50 +02:00
Akim Demaille 2c66acfec0 diagnostics: prefer "…" to "..." if the locale supports it
* src/location.c (ellipsis, ellipsize): New.
Use them.
2019-10-10 21:57:50 +02:00
Paul Eggert 3f320159e3 c: improve patch for UCHAR_MAX etc. problem
* data/skeletons/c.m4 (b4_c99_int_type_define): Reorder to put the
signed types first, since they’re simpler and this keeps similar
code closer.  For signed types, don’t bother checking whether the
type promotes to int since the type must be signed anyway.  For
unsigned types, protect a test like ‘UCHAR_MAX <= INT_MAX’ with
‘!defined __UINT_LEAST8_MAX__’, as otherwise the logic is wrong
for oddball platforms; and once we do that, there should no need
for ‘defined INT_MAX’ so remove that.
2019-10-10 12:08:42 -07:00
Akim Demaille f41e0cf73c tests: do not depend on config.h
Currently we face test suite failures in different environments,
because of a conflict between the definitions of isnan by gnulib, and
by the C++ library:

    262. headers.at:186: testing Sane headers: %locations %debug c++ ...
    ./headers.at:186: COLUMNS=1000; export COLUMNS;  bison --color=no -fno-caret -d -o input.cc input.y
    ./headers.at:186: $CXX $CXXFLAGS $CPPFLAGS  -c -o input.o input.cc
    stderr:
    In file included from /usr/include/c++/4.8.2/cmath:44:0,
                     from /usr/include/c++/4.8.2/random:38,
                     from /usr/include/c++/4.8.2/bits/stl_algo.h:65,
                     from /usr/include/c++/4.8.2/algorithm:62,
                     from location.hh:41,
                     from input.hh:90,
                     from input.cc:50:
    /u/cs/fac/eggert/src/gnu/bison/lib/math.h: In function 'bool isnan(double)':
    /u/cs/fac/eggert/src/gnu/bison/lib/math.h:2849:1: error: new declaration 'bool isnan(double)'
     _GL_MATH_CXX_REAL_FLOATING_DECL_2 (isnan, isnan, bool)
     ^
    In file included from /usr/include/features.h:375:0,
                     from /usr/include/c++/4.8.2/x86_64-redhat-linux/bits/os_defines.h:39,
                     from /usr/include/c++/4.8.2/x86_64-redhat-linux/bits/c++config.h:2097,
                     from /usr/include/c++/4.8.2/cstdlib:41,
                     from input.hh:48,
                     from input.cc:50:
    /usr/include/bits/mathcalls.h:235:1: error: ambiguates old declaration 'int isnan(double)'
     __MATHDECL_1 (int,isnan,, (_Mdouble_ __value)) __attribute__ ((__const__));
     ^

There might be something to do in gnulib about this, but I believe
that gnulib should not be used in the test suite in the first place.

The test suite should work with other compilers than the one used to
compile the package.  For a start, Bison sources are more
demanding (C99) than the generated parsers.  Last time I tried, tcc
for example, was not able to compile Bison, yet our generated parsers
should compile cleanly with it.

Besides the problem at hand is with the C++ compiler, with is not the
one used to set up gnulib at configuration-time (config.h is mainly
built from probing the C compiler).

We should really not depend on gnulib in tests.

This was introduced in 2001 to check whether including
stdlib.h/string.h is safe thanks to STDC_HEADERS
(2ce1014469).  Today, we assume at least
a C90 compiler, it should be safe enough.

* tests/local.at, tests/testsuite.h: Do not include config.h.
* tests/atlocal.in (conftest.cc): Likewise.
(CPPFLAGS): Do not expose lib/, as because of this we might picked up
gnulib replacement headers for system headers.

* tests/input.at: Use int instead of ptrdiff_t, for easier portability
(some machine on the CI did not find ptrdiff_t).
* tests/c++.at: Add missing include for getchar.
2019-10-10 17:53:48 +02:00
Akim Demaille d6ce0521cf doc: spell check
* doc/bison.texi: Remove the index about yyoutput, it is no longer
documented.
Spell check.
2019-10-10 17:53:48 +02:00
Akim Demaille cf298ebb7d tests: style changes
* tests/actions.at: Prefer printf to fprintf.
Prefer yyo to yyoutput in %printer.
2019-10-10 17:53:48 +02:00
Akim Demaille 734db67004 tests: formatting changes
* tests/actions.at, tests/local.at: here.
2019-10-10 17:53:48 +02:00
Akim Demaille 7d47d51962 tests: add missing includes
* tests/actions.at, tests/c++.at, tests/headers.at,
* tests/regression.at: here.
2019-10-10 17:53:32 +02:00
Akim Demaille 602d562d6f c: don't assume that UCHAR_MAX, etc. are defined
A number of portability issues with GCC 4.6 .. 4.9 (inclusive):

    input.c:184:7: error: "UCHAR_MAX" is not defined [-Werror=undef]
     #elif UCHAR_MAX <= INT_MAX
           ^
    input.c:184:20: error: "INT_MAX" is not defined [-Werror=undef]
     #elif UCHAR_MAX <= INT_MAX
                        ^
    input.c:202:7: error: "USHRT_MAX" is not defined [-Werror=undef]
     #elif USHRT_MAX <= INT_MAX
           ^
    input.c:202:20: error: "INT_MAX" is not defined [-Werror=undef]
     #elif USHRT_MAX <= INT_MAX
                        ^

* data/skeletons/c.m4 (b4_c99_int_type_define): Don't assume they are
defined.
2019-10-10 16:01:43 +02:00
Akim Demaille 825150b085 configure: don't require Flex
Flex should not be required to build Bison or run the test suite (of
course it is needed for maintaining Bison).  Yet the Automake
conditional FLEX_WORKS does not work.

* m4/flex.m4 (_AC_PROG_LEX_YYTEXT_DECL): Since this is called
conditionally, don't define LEX_IS_FLEX here, but rather...
(AC_PROG_LEX): here.
* configure.ac: Be more cautious about possibly undefined variables.
2019-10-09 07:28:26 +02:00
Paul Eggert d4b6c86c7f Move the integer-type selection into c.m4
That way, glr.c can use it too.
* data/skeletons/c.m4 (b4_int_type):
Do not special-case ‘char’; it’s not worth the trouble,
as clang complains about char subscripts.
(b4_c99_int_type, b4_c99_int_type_define): New macros,
taken from yacc.c.
* data/skeletons/glr.c: Use b4_int_type_define.
* data/skeletons/yacc.c (b4_int_type): Remove, since there’s
no longer any need to redefine it.
Use b4_c99_int_type_define rather than its body.
2019-10-07 00:08:19 -07:00
Paul Eggert 5463291a91 Use “least” types for integers in Yacc tables
This changes the Yacc skeleton to use “least” integer types to
keep tables smaller on some platforms, which should lessen cache
pressure.  Since Bison uses the Yacc skeleton, it follows suit.
* data/skeletons/yacc.c: Include limits.h and stdint.h if this
seems to be needed.
(yytype_uint8, yytype_int8, yytype_uint16, yytype_int16):
If available, use GCC predefined macros __INT_MAX__ etc. to select
a “least” type, as this avoids namespace hassles.  Otherwise, if
available fall back on selecting a “least” type via the C99 macros
INT_MAX, INT_LEAST8_MAX, etc.  Otherwise, fall further back on one of
the builtin C99 types signed char, short, and int.  Make sure that
any selected type promotes to int.  Ignore any macros YYTYPE_INT16,
YYTYPE_INT8, YYTYPE_UINT16, YYTYPE_UINT8 defined by the user.
(ptrdiff_t, PTRDIFF_MAX): Simplify in the light of the above.
(yytype_uint8, yytype_uint16): Do not assume that unsigned char
and unsigned short promote to int, as this isn’t true on some
platforms (e.g., TI TMS320C55x).
* src/parse-gram.y (YYTYPE_INT16, YYTYPE_INT8, YYTYPE_UINT16)
(YYTYPE_UINT8): Remove, as these are no longer effective.
2019-10-07 00:08:19 -07:00
Paul Eggert 6373b90fc8 Port better to C++ platforms
* data/skeletons/yacc.c (YYPTRDIFF_T, YYPTRDIFF_MAXIMUM):
Default to long, not int.
(yy_lac_stack_realloc, yy_lac, yytnamerr, yyparse):
Avoid casts to YYPTRDIFF_T that were masking the problem.
2019-10-06 11:59:16 -07:00
Paul Eggert beceb2fa93 Work around GCC 4.8 false alarms without casts
* data/skeletons/yacc.c (yyparse):
Initialize yyes_capacity with a signed expression.
* tests/local.at (AT_YYLEX_DEFINE(c)):
Use enum to avoid cast.
2019-10-06 11:59:16 -07:00
Akim Demaille 58302c6079 regen 2019-10-06 17:48:51 +02:00
Akim Demaille d2a7a28438 tests: make recheck
* tests/local.mk (recheck): New.
2019-10-06 12:15:12 +02:00
Akim Demaille 9e6c5328d3 diagnostics: also show suggested %empty
* src/reader.c (grammar_rule_check_and_complete): Suggest to add %empty.
* tests/actions.at, tests/diagnostics.at: Adjust expectations.
2019-10-06 12:15:12 +02:00
Akim Demaille fec13ce2db diagnostics: sort symbols per location
Because the checking of the grammar is made by phases after the whole
grammar was read, we sometimes have diagnostics that look weird.  In
some case, within one type of checking, the entities are not checked
in the order in which they appear in the file.  For instance, checking
symbols is done on the list of symbols sorted by tag:

    foo.y:1.20-22: warning: symbol BAR is used, but is not defined as a token and has no rules [-Wother]
        1 | %destructor {} QUX BAR
          |                    ^~~
    foo.y:1.16-18: warning: symbol QUX is used, but is not defined as a token and has no rules [-Wother]
        1 | %destructor {} QUX BAR
          |                ^~~

Let's sort them by location instead:

    foo.y:1.16-18: warning: symbol 'QUX' is used, but is not defined as a token and has no rules [-Wother]
        1 | %destructor {} QUX BAR
          |                ^~~
    foo.y:1.20-22: warning: symbol 'BAR' is used, but is not defined as a token and has no rules [-Wother]
        1 | %destructor {} QUX BAR
          |                    ^~~

* src/location.h (location_cmp): Be robust to empty file names.
* src/symtab.c (symbol_cmp): Sort by location.
* tests/input.at: Adjust expectations.
2019-10-06 09:54:25 +02:00
Akim Demaille be3cf406af diagnostics: suggest fixes for undeclared symbols
From

    input.y:1.17-19: warning: symbol baz is used, but is not defined as a token and has no rules [-Wother]
         1 | %printer {} foo baz
           |                 ^~~

to

    input.y:1.17-19: warning: symbol 'baz' is used, but is not defined as a token and has no rules; did you mean 'bar'? [-Wother]
        1 | %printer {} foo baz
          |                 ^~~
          |                 bar

* bootstrap.conf: We need fstrcmp.
* src/symtab.c (symbol_from_uniqstr_fuzzy): New.
(complain_symbol_undeclared): Use it.
* tests/diagnostics.at (Suggestions): New.
* data/bison-default.css (insertion): Rename as...
(fixit-insert): this, as this is what GCC uses.
2019-10-06 09:54:25 +02:00
Akim Demaille 126c4622de style: isolate complain_symbol_undeclared
* src/symtab.c (complain_symbol_undeclared): New.
Use it.
Use quote on the guilty symbol (like GCC does, and we also do
elsewhere).
* tests/input.at: Adjust.
2019-10-06 09:54:25 +02:00
Akim Demaille dd64eaf9db style: simplify the handling of symbol and semantic_type tables
Both are stored in a hash, and back in the days, we used to iterate
over these tables using hash_do_for_each.  However, the order of
traversal was not deterministic, which was a nuisance for
deterministic output (and therefore also a problem for tests).  So at
some point (83b60c97ee) we generated a
sorted list of these symbols, and symbols_do actually iterated on that
list.  But we kept the constraints of using hash_do_for_each, which
requires a lot of ceremonial code, and makes it hard/unnatural to
preserve data between iterations (see the next commit).

Alas, this is C, not C++.

Let's remove this abstraction, and directly iterate on the sorted
tables.

* src/symtab.c (symbols_do): Remove.
Adjust callers to use a simple for-loop instead.
(table_sort): New.
(symbols_check_defined): Use it.
(symbol_check_defined_processor, symbol_pack_processor)
(semantic_type_check_defined_processor, symbol_translation_processor):
Remove.
Simplify the corresponding functions (that no longer need to return a
bool).
2019-10-06 09:54:20 +02:00
Akim Demaille 0b585c49ae diagnostics: display suggested update after the caret-info
This commit adds the suggestion in green, on the line below the
caret-and-tildes.

    foo.y:1.1-14: warning: deprecated directive: '%error-verbose', use '%define parse.error verbose' [-Wdeprecated]
        1 | %error-verbose
          | ^~~~~~~~~~~~~~
          | %define parse.error verbose

The current approach, with location_caret_suggestion, is fragile:
there's a protocol of calls to the complain functions which is strict.
We should rather have a richer structure describing the diagnostics,
including with submessages such as the suggestions, passed in the end
to the routines in charge of formatting and printing them.

* src/location.h, src/location.c (location_caret_suggestion): New.
* src/complain.c (deprecated_directive): Use it.
* tests/diagnostics.at, tests/input.at: Adjust expectations.
2019-10-06 08:07:57 +02:00
Akim Demaille 37c4d0b175 diagnostics: isolate caret_set_column
* src/location.c (caret_info): Add width and skip members.
(caret_set_column): New.
Use it.
2019-10-06 08:07:57 +02:00
Akim Demaille 56bcccbc51 diagnostics: isolate caret_set_file
* src/location.c (caret_set_file): New.
Store the current line's length in caret_info.line_len.
Pay attention to fseek's return value.
Extracted from...
(location_caret): here.
2019-10-06 08:07:57 +02:00
Akim Demaille 17cc7da519 tests: use tput to get the number of columns
* tests/bison.in: here.
2019-10-06 08:07:57 +02:00
Akim Demaille 2713e7c4ff TODO: update
I no longer agree with that item, there are indeed two things to
report: lack of definition, and being useless.  We could have either
one without the other, they are not directly related.
2019-10-06 08:07:57 +02:00
Akim Demaille 32e5a91a91 yacc.c: work around warnings from G++ 4.8
input.c: In function 'int yyparse()':
input.c: error: conversion to 'long int' from 'long unsigned int'
                may change the sign of the result [-Werror=sign-conversion]
   yyes_capacity = sizeof yyesa / sizeof *yyes;
                                ^
cc1plus: all warnings being treated as errors

* data/skeletons/yacc.c: here.
2019-10-06 08:07:40 +02:00
Akim Demaille 5973d763c0 yacc.c: work around warnings from Clang++ 3.3 and 3.4
When we run the test suite with these C++ compilers to compile C code,
we get:

    239. synclines.at:440: testing syncline escapes: yacc.c ...
    ../../tests/synclines.at:440: $CC $CFLAGS $CPPFLAGS \"\\\"\".c -o \"\\\"\" ||
              exit 77
    stderr:
    stdout:
    ../../tests/synclines.at:440: COLUMNS=1000; export COLUMNS;  bison --color=no -fno-caret  -o \"\\\"\".c \"\\\"\".y
    ../../tests/synclines.at:440: $CC $CFLAGS $CPPFLAGS  $LDFLAGS -o \"\\\"\" \"\\\"\".c $LIBS
    stderr:
    "\"".c:1102:41: error: implicit conversion loses integer precision: 'long' to 'int' [-Werror,-Wshorten-64-to-32]
          YYPTRDIFF_T yysize = yyssp - yyss + 1;
                      ~~~~~~   ~~~~~~~~~~~~~^~~
    1 error generated.

    193. conflicts.at:545: testing parse.error=verbose and consistent errors: lr.type=canonical-lr parse.lac=full ...
    input.c:737:75: error: implicit conversion loses integer precision: 'long' to 'int'
                           [-Werror,-Wshorten-64-to-32]
      YYPTRDIFF_T yysize_old = *yytop == yytop_empty ? 0 : *yytop - *yybottom + 1;
                  ~~~~~~~~~~                               ~~~~~~~~~~~~~~~~~~~^~~
    input.c:901:48: error: implicit conversion loses integer precision: 'long' to 'int'
                           [-Werror,-Wshorten-64-to-32]
                YYPTRDIFF_T yysize = yyesp - *yyes + 1;
                            ~~~~~~   ~~~~~~~~~~~~~~^~~

* data/skeletons/yacc.c: Add more casts.
2019-10-06 08:03:43 +02:00
Akim Demaille 4246cd81df tests: avoid a GCC 4.8 warning
GCC 4.8 reports:

    input.y:57:33: error: conversion to 'int' from 'long unsigned int'
                          may alter its value [-Werror=conversion]
       int input_elts = sizeof input / sizeof input[0];
                                     ^

* tests/local.at (AT_YYLEX_DEFINE(c)): Add a cast (sorry, Paul!).
2019-10-05 23:00:05 +02:00
Paul Eggert e69b47cd18 * data/skeletons/glr.c (yysplitStack): Pacify Clang 8. 2019-10-05 03:42:24 -07:00
Paul Eggert 8f5aaa0e04 Avoid quiet conversion of pointer to bool
* src/location.c (caret_set_file):
* src/scan-code.l (contains_dot_or_dash):
Do not quietly convert pointer to bool, as Oracle Developer Studio
12.6 complains and it is arguably confusing style anyway.
2019-10-05 01:19:39 -07:00
Paul Eggert b75b055288 Port ARGMATCH_DEFINE_GROUP calls to C99
* src/complain.c, src/getargs.c: Omit ‘;’ after call
to ARGMATCH_DEFINE_GROUP, as C99 does not allow ‘;’ there.
2019-10-05 01:19:39 -07:00
Paul Eggert 41e84cddc7 Port lexcalc scan.l to Solaris 10
* examples/c/lexcalc/scan.l: Include errno.h.
2019-10-05 01:19:39 -07:00
Akim Demaille 5709f94a91 yacc.c: use casts instead of pragmas when losing integer width
For instance with Clang 4, 8, etc.:

    input.c:1166:12: error: implicit conversion loses integer precision: 'int' to 'yy_state_num' (aka 'signed char') [-Werror,-Wconversion]
      *yyssp = yystate;
             ~ ^~~~~~~

And GCC 8:

    input.c:1166:12: error: implicit conversion loses integer precision: 'int' to 'yy_state_num' (aka 'signed char') [-Werror,-Wimplicit-int-conversion]
      *yyssp = yystate;
             ~ ^~~~~~~

* data/skeletons/yacc.c (YY_CONVERT_INT_BEGIN): Remove.
Adjust callers.
2019-10-05 09:01:56 +02:00
Akim Demaille bc96b757ca yacc.c: fix warnings about undefined macros
For instance with GCC 4.9 and --enable-gcc-warnings:

    25. input.at:1201: testing Torturing the Scanner ...
    ../../tests/input.at:1344: $CC $CFLAGS $CPPFLAGS  -c -o input.o input.c
    stderr:
    input.c:239:18: error: "__STDC_VERSION__" is not defined [-Werror=undef]
     # elif 199901 <= __STDC_VERSION__
                      ^
    input.c:256:18: error: "__STDC_VERSION__" is not defined [-Werror=undef]
     # elif 199901 <= __STDC_VERSION__
                      ^

* data/skeletons/yacc.c: Check that __STDC_VERSION__ is defined before
using it.
2019-10-04 06:58:44 +02:00
Akim Demaille 1133220416 tests: check more state numbers
* tests/torture.at (State number type): Also check 128, 129 and
32768.
2019-10-04 06:58:44 +02:00
Paul Eggert 39eb80bdbc * doc/bison.texi (Table of Symbols): Mention memory exhaustion. 2019-10-03 11:17:18 -07:00
Paul Eggert 361004aabe Simplify mfcalc error handling
* doc/bison.texi (Mfcalc Symbol Table, Mfcalc Lexer):
Don’t abort on memory allocation failure or integer overflow.
Instead, comment that these things aren’t checked for.
2019-10-03 11:17:18 -07:00
Akim Demaille 032a52be6e c++: fix comments suggesting to use %require
* data/skeletons/location.cc, data/skeletons/stack.hh: Here.
2019-10-03 09:27:41 +02:00
Akim Demaille 843ef49bc3 lalr1.cc: simplify uses of size_t
* data/skeletons/stack.hh (stack::index_type): New type.
(stack::size, stack::operator[]): Be about an index_type rather than a
size_type and an int.
2019-10-03 09:27:41 +02:00
Akim Demaille 5df33278b4 c++: fixes for old compilers
On the CI with GCC 6:

    examples/c++/calc++/parser.cc:845:5: error: 'ptrdiff_t' was not declared in this scope
         ptrdiff_t yycount = 0;
         ^~~~~~~~~
    examples/c++/calc++/parser.cc:845:5: note: suggested alternatives:
    /usr/include/x86_64-linux-gnu/c++/6/bits/c++config.h:202:28: note:   'std::ptrdiff_t'
       typedef __PTRDIFF_TYPE__ ptrdiff_t;
                                ^~~~~~~~~

* data/skeletons/lalr1.cc: Qualify ptrdiff_t and size_t with std::.
2019-10-03 09:27:41 +02:00
Akim Demaille d96fff6115 tests: be robust to -DNDEBUG
input.y: In function 'yylex':
input.y:67:7: error: unused variable 'input_elts' [-Werror=unused-variable]
   int input_elts = sizeof input / sizeof input[0];
       ^~~~~~~~~~
cc1: all warnings being treated as errors

* tests/input.at, tests/local.at: Avoid that.
2019-10-03 09:27:40 +02:00
Akim Demaille be92ad1eb4 CI: remove the symlink before creating it
Currently we fail if we rerun a job that succeeded to push the
tarball.
2019-10-03 07:56:42 +02:00
Paul Eggert ff2f02815b Adjust ‘Big horizontal’ test case
* tests/torture.at (Big horizontal): Adjust to recent changes with
integers.  If there are states 0..256, Bison now uses a signed
rather than an unsigned 16-bit integer.
2019-10-02 18:37:35 -07:00
Paul Eggert 67dcef357c regen 2019-10-02 17:11:33 -07:00
Paul Eggert 133edcd248 Prefer signed to unsigned integers
This patch contains more fixes to prefer signed to unsigned
integer types, as modern tools like 'gcc -fsanitize=undefined'
can check for signed integer overflow but not unsigned overflow.
* NEWS: Document the API change.
* boostrap.conf (gnulib_modules): Add intprops.
* data/skeletons/glr.c: Include stddef.h and stdint.h,
since this skeleton can assume C99 or later.
(YYSIZEMAX): Now signed, and the minimum of SIZE_MAX and PTRDIFF_MAX.
(yybool) [!__cplusplus]: Now signed (which is how bool behaves).
(YYTRANSLATE): Avoid use of unsigned, and make the macro
safe even for values greater than UINT_MAX.
(yytnamerr, struct yyGLRState, struct yyGLRStateSet, struct yyGLRStack)
(yyaddDeferredAction, yyinitStateSet, yyinitGLRStack)
(yyexpandGLRStack, yymarkStackDeleted, yyremoveDeletes)
(yyglrShift, yyglrShiftDefer, yy_reduce_print, yydoAction)
(yyglrReduce, yysplitStack, yyreportTree, yycompressStack)
(yyprocessOneStack, yyreportSyntaxError, yyrecoverSyntaxError)
(yyparse, yy_yypstack, yypstack, yypdumpstack):
* tests/input.at (Torturing the Scanner):
Prefer ptrdiff_t to size_t.
* data/skeletons/c++.m4 (b4_yytranslate_define):
* src/AnnotationList.c (AnnotationList__computePredecessorAnnotations):
* src/AnnotationList.h (AnnotationIndex):
* src/InadequacyList.h (InadequacyListNodeCount):
* src/closure.c (closure_new):
* src/complain.c (error_message, complains, complain_indent)
(complain_args, duplicate_directive, duplicate_rule_directive):
* src/gram.c (nritems, ritem_print, grammar_dump):
* src/ielr.c (ielr_compute_ritem_sees_lookahead_set)
(ielr_item_has_lookahead, ielr_compute_annotation_lists)
(ielr_compute_lookaheads):
* src/location.c (columns, boundary_print, location_print):
* src/muscle-tab.c (muscle_percent_define_insert)
(muscle_percent_define_check_values):
* src/output.c (prepare_rules, prepare_actions):
* src/parse-gram.y (id, handle_require):
* src/reader.c (record_merge_function_type, packgram):
* src/reduce.c (nuseless_productions, nuseless_nonterminals)
(inaccessable_symbols):
* src/relation.c (relation_print):
* src/scan-code.l (variant, variant_table_size, variant_count)
(variant_add, get_at_spec, show_sub_message, show_sub_messages)
(parse_ref):
* src/scan-gram.l (<SC_ESCAPED_STRING,SC_ESCAPED_CHARACTER>)
(scan_integer, convert_ucn_to_byte, handle_syncline):
* src/scan-skel.l (at_complain):
* src/symtab.c (complain_symbol_redeclared)
(complain_semantic_type_redeclared, complain_class_redeclared)
(symbol_class_set, complain_user_token_number_redeclared):
* src/tables.c (conflict_tos, conflrow, conflict_table)
(conflict_list, save_row, pack_vector):
* tests/local.at (AT_YYLEX_DEFINE(c)):
Prefer signed to unsigned integer.
* data/skeletons/lalr1.cc (yy_lac_check_):
* tests/actions.at (_AT_CHECK_PRINTER_AND_DESTRUCTOR):
* tests/local.at (AT_YYLEX_DEFINE(c)):
Omit now-unnecessary casts.
* data/skeletons/location.cc (b4_location_define):
* doc/bison.texi (Mfcalc Lexer, C++ position, C++ location):
Prefer int to unsigned for line and column numbers.
Change example to abort explicitly on memory exhaustion,
and fix an off-by-one bug that led to undefined behavior.
* data/skeletons/stack.hh (stack::operator[]):
Also allow ptrdiff_t indexes.
(stack::pop, slice::slice, slice::operator[]):
Index arg is now ptrdiff_t, not int.
(stack::ssize): New method.
(slice::range_): Now ptrdiff_t, not int.
* data/skeletons/yacc.c (b4_state_num_type): Remove.
All uses replaced by b4_int_type.
(YY_CONVERT_INT_BEGIN, YY_CONVERT_INT_END): New macros.
(yylac, yyparse): Use them around conversions that -Wconversion
would give false alarms about. 	Omit unnecessary casts.
(yy_stack_print): Use int rather than unsigned, and omit
a cast that doesn’t seem to be needed here any more.
* examples/c++/variant.yy (yylex):
* examples/c++/variant-11.yy (yylex):
Omit no-longer-needed conversions to unsigned.
* src/InadequacyList.c (InadequacyList__new_conflict):
Don’t assume *node_count is unsigned.
* src/output.c (muscle_insert_unsigned_table):
Remove; no longer used.
2019-10-02 17:11:33 -07:00
Paul EggertandAkim Demaille 4d9ff272cf Prefer signed types for indexes in skeletons
* NEWS: Mention this.
* data/skeletons/c.m4 (b4_int_type):
Prefer char if it will do, and prefer signed types to unsigned if
either will do.
* data/skeletons/glr.c (yy_reduce_print): No need to
convert rule line to unsigned long.
(yyrecoverSyntaxError): Put action into an int to
avoid GCC warning of using a char subscript.
* data/skeletons/lalr1.cc (yy_lac_check_, yysyntax_error_):
Prefer ptrdiff_t to size_t.
* data/skeletons/yacc.c (b4_int_type):
Prefer signed types to unsigned if either will do.
* data/skeletons/yacc.c (b4_declare_parser_state_variables):
(YYSTACK_RELOCATE, YYCOPY, yy_lac_stack_realloc, yy_lac)
(yytnamerr, yysyntax_error, yyparse): Prefer ptrdiff_t to size_t.
(YYPTRDIFF_T, YYPTRDIFF_MAXIMUM): New macros.
(YYSIZE_T): Fix "! defined YYSIZE_T" typo.
(YYSIZE_MAXIMUM): Take the minimum of PTRDIFF_MAX and SIZE_MAX.
(YYSIZEOF): New macro.
(YYSTACK_GAP_MAXIMUM, YYSTACK_BYTES, YYSTACK_RELOCATE)
(yy_lac_stack_realloc, yyparse): Use it.
(YYCOPY, yy_lac_stack_realloc): Cast to YYSIZE_T to pacify GCC.
(yy_reduce_print): Use int instead of unsigned long when int
will do.
(yy_lac_stack_realloc): Prefer long to unsigned long when
either will do.
* tests/regression.at: Adjust to these changes.
2019-10-02 07:10:03 +02:00
Akim Demaille 2ca6b71967 yacc: use the most appropriate integral type for state numbers
Currently we properly use the "best" integral type for tables,
including those storing state numbers.  However the variables for
state numbers used in yyparse (and its dependencies such as
yy_stack_print) still use int16_t invariably.  As a consequence, very
large models overflow these variables.

Let's use the "best" type for these variables too.  It turns out that
we can still use 16 bits for twice larger automata: stick to unsigned
types.

However using 'unsigned' when 16 bits are not enough is troublesome
and generates tons of warnings about signedness issues.  Instead,
let's use 'int'.

Reported by Tom Kramer.
https://lists.gnu.org/archive/html/bug-bison/2019-09/msg00018.html

* data/skeletons/yacc.c (b4_state_num_type): New.
(yy_state_num): Be computed from YYNSTATES.
* tests/linear: New.
* tests/torture.at (State number type): New.
Use it.
2019-09-30 18:31:55 +02:00
Akim Demaille 871c02b327 yacc: introduce a type for states
* data/skeletons/yacc.c (yy_state_num): New.
Use it for arrays of states.
2019-09-30 07:26:17 +02:00
Akim Demaille a57e74a5bf style: prefer symbolic values rather than litterals
Instead of

    #define YYPACT_NINF -130
    #define yypact_value_is_default(Yystate) \
      (!!((Yystate) == (-130)))

generate

    #define YYPACT_NINF (-130)
    #define yypact_value_is_default(Yyn) \
      ((Yyn) == YYPACT_NINF)

* data/skeletons/c.m4 (b4_table_value_equals): Add support for $4.
* data/skeletons/glr.c, data/skeletons/yacc.c: Use it.
Also, use shorter macro argument names, the name of the macro is clear
enough.
2019-09-30 07:25:56 +02:00
Akim Demaille 4971409e39 style: change misleading macro argument name
* data/skeletons/glr.c, data/skeletons/yacc.c
(yypact_value_is_default): It does not take a rule number as argument.
2019-09-30 07:25:48 +02:00
Akim Demaille b772baef24 Merge remote-tracking branch 'upstream/maint'
* upstream/maint:
  c++: add copy ctors for compatibility with the IAR compiler
  CI: show git status
  CI: disable ICC
  tests: pass -jN from Make to the test suite
  quotearg: avoid leaks
  maint: post-release administrivia
2019-09-28 08:09:33 +02:00
Akim Demaille 406e8c7c02 c++: add copy ctors for compatibility with the IAR compiler
Reported by Andreas Damm.
https://savannah.gnu.org/support/?110032

* data/skeletons/lalr1.cc (stack_symbol_type::operator=): New
overload, const, to please the IAR C++ compiler (version ca 2013).
2019-09-27 08:40:52 +02:00
Akim Demaille 97c4169f23 CI: show git status 2019-09-23 06:06:35 +02:00
Akim Demaille 8add45dbd9 CI: disable ICC
It seems that Intel changed something in their license management.
https://github.com/nemequ/icc-travis/issues/15
2019-09-23 06:06:26 +02:00
Akim Demaille b3e9c20227 tests: pass -jN from Make to the test suite
I am sooooo tired of typing "make -j5 TESTSUITEFLAGS=-j5"...
Should have done this years ago.

* cfg.mk (TESTSUITEFLAGS): here.
2019-09-23 06:05:39 +02:00
Akim Demaille b2c381cd25 quotearg: avoid leaks
Reported by Tomasz Kłoczko.
https://lists.gnu.org/archive/html/bug-bison/2019-09/msg00008.html

* src/main.c (main): Free quotearg's memory later.
2019-09-22 18:15:36 +02:00
Akim Demaille 67bff62e31 diagnostics: get the screen width from the terminal
* bootstrap.conf: We need winsz-ioctl and winsz-termios.
* src/location.c (columns): Use winsize to get the number of
columns.
Code taken from the GNU Coreutils.
* src/location.h, src/location.c (caret_init): New.
* src/complain.c (complain_init): Call it.
* tests/bison.in: Export COLUMNS so that users of tests/bison can
enjoy proper line truncation.
2019-09-22 09:12:08 +02:00
Akim Demaille 5f45cb05f1 diagnostics: don't print ellipsis on the caret line
From

    9 | ...TUVWXYZ  ABCDEFGHIJKLMNOPQRSTUVWXYZ  ABCDEFGHIJKL
      | ...         ^~~~~~~~~~~~~~~~~~~~~~~~~~

to

    9 | ...TUVWXYZ  ABCDEFGHIJKLMNOPQRSTUVWXYZ  ABCDEFGHI...
      |             ^~~~~~~~~~~~~~~~~~~~~~~~~~

* src/location.c (location_caret): here.
* tests/diagnostics.at: Adjust expectations.
2019-09-22 09:12:08 +02:00
Akim Demaille b61b0eb9ac diagnostics: also show truncation at the end of line with "..."
From

    9 | ...TUVWXYZ  ABCDEFGHIJKLMNOPQRSTUVWXYZ  ABCDEFGHIJKL
      | ...         ^~~~~~~~~~~~~~~~~~~~~~~~~~

to

    9 | ...TUVWXYZ  ABCDEFGHIJKLMNOPQRSTUVWXYZ  ABCDEFGHI...
      | ...         ^~~~~~~~~~~~~~~~~~~~~~~~~~

* src/location.c (location_caret): here.
* tests/diagnostics.at: Adjust expectations.
2019-09-22 09:12:08 +02:00
Akim Demaille 69277e109a diagnostics: check that quoted lines are truncated
* tests/diagnostics.at (Screen width: 60 columns, Screen width: 80
columns, Screen width: 200 columns): New tests.
2019-09-22 09:12:08 +02:00
Akim Demaille f716484627 diagnostics: truncate quoted sources to fit the screen
* src/location.c (min_int, columns): New.
(location_caret): Compute the line width.  Based on it, compute how
many columns must be skipped before the quoted location and truncated
after, to fit the sceen width.
* tests/local.at (AT_QUELL_VALGRIND): Transform into...
(AT_SET_ENV_IF, AT_SET_ENV): these.
Define COLUMNS to protect the test suite from the user's environment.
2019-09-22 09:12:08 +02:00
Akim Demaille 945b917da2 diagnostics: learn how to count column number with multibyte chars
So far diagnostics were cheating: in addition to the 'column' field of
locations (based on actual screen width per multibyte characters and
on tabulation expansion), the scanner sets the 'byte' field.
Diagnostics used this byte count to decide where to insert (color)
style.

We want to be able to truncate the quoted lines when there are too
wide to fit the screen.  This requires that the diagnostics learn how
to count columns, the byte-in-boundary trick no longer works.

Bytes are still used for fix-its.

* bootstrap.conf: We need mbfile for mbf_getc.
* src/location.c (caret_info): We need an mbfile.
(caret_set_file): Initialize it.
(caret_getc): Convert to mbfile.
(location_caret): Instead of relying on the byte position to decide
where to insert the color style, count the current column using
boundary_compute.
2019-09-22 09:12:08 +02:00
Akim Demaille 1ef407d923 diagnostics: style: rename member for clariy
* src/location.c (caret_info): Now that we no longer have a 'file'
member (see previous commit), rename 'source' as 'file'.
2019-09-22 09:12:08 +02:00
Akim Demaille 576b863e91 diagnostics: style: use a boundary to track the caret_info
* src/location.c (caret_info): Replace file and line with pos, a
boundary.  This will allow us to use features of the boundary type,
such as boundary_compute.
2019-09-22 09:12:08 +02:00
Akim Demaille 2274c34e91 diagnostics: extract boundary_compute from location_compute
The handling of the contributions of the tabulations in the columns is
burried inside location_compute.  We will soon be willing to use the
boundary part of the computation (to compute the current column number
each time we read a multibyte char).

* src/location.c (boundary_compute): New, extracted from...
(location_compute): here.
2019-09-22 09:12:08 +02:00
Akim Demaille fccab9bc40 diagnostics: style: add caret_set_file
To make the following commits easier to read.

* src/location.c (caret_set_file): New.
2019-09-22 09:12:08 +02:00
Akim Demaille 488607534a diagnostics: style: minor changes
* src/location.c (location_caret): Factor two branches of an if.
2019-09-22 09:12:08 +02:00
Akim Demaille 4db572dd21 CI: show git status 2019-09-22 09:12:08 +02:00
Akim Demaille 8faf075fd7 git: update ignores 2019-09-22 09:12:08 +02:00
Akim Demaille 453639dfac git: update ignores 2019-09-22 07:48:10 +02:00
Akim Demaille 4901ee115b quotearg: avoid leaks
Reported by Tomasz Kłoczko.
https://lists.gnu.org/archive/html/bug-bison/2019-09/msg00008.html

* src/main.c (main): Free quotearg's memory later.
2019-09-21 15:01:45 +02:00
Akim Demaille 6c7b2dfe51 tests: pass -jN from Make to the test suite
I am sooooo tired of typing "make -j5 TESTSUITEFLAGS=-j5"...
Should have done this years ago.

* cfg.mk (TESTSUITEFLAGS): here.
2019-09-14 10:19:13 +02:00
Akim Demaille a3e201de02 java: handle eof in yytranslate
* data/skeletons/lalr1.java (yytranslate_): Handle eof here, as is done
in lalr1.cc.
* tests/javapush.at: Adjust.
2019-09-14 10:09:08 +02:00
Akim Demaille 5e95bb6251 d: handle eof in yytranslate
This changes the traces from

    Reading a token:
    Now at end of input.

to

    Reading a token:
    Next token is token $end (7FFEE56E6474)

which is ok.  Actually it is even better, as it gives the location
when locations are enabled, and is clearer when rules explicitly use
the EOF token.

* data/skeletons/lalr1.d (yytranslate_): Handle eof here, as is done
in lalr1.cc.
2019-09-14 10:09:08 +02:00
Akim Demaille 569125a6bf regen 2019-09-14 10:09:08 +02:00
Akim Demaille 8ac28ba1f0 parser: use api.token.raw
* src/parse-gram.y: Here.
2019-09-14 10:09:08 +02:00
Akim Demaille 3ca713abd0 api.token.raw: document it
* doc/bison.texi: here.
2019-09-14 10:09:08 +02:00
Akim Demaille 8c18e3f18c api.token.raw: cannot be used with character literals
* src/parse-gram.y (CHAR): api.token.raw and character literals are
mutually exclusive.
* tests/input.at (Character literals and api.token.raw): New.
2019-09-14 10:09:08 +02:00
Akim Demaille 1e5e274972 api.token.raw: apply to the other skeletons
* data/skeletons/c++.m4, data/skeletons/glr.c,
* data/skeletons/lalr1.c, data/skeletons/lalr1.java:
Add support for api.token.raw.

* tests/scanner.at: Check them.
2019-09-14 09:55:17 +02:00
Akim Demaille b1679f8346 api.token.raw: check it
* tests/local.at (AT_TOKEN_RAW_IF): New.
* tests/local.mk: New.
Use it.
2019-09-14 09:55:17 +02:00
Akim Demaille 9861bcc540 api.token.raw: implement
Bison used to feature %raw, documented as follows:

    @item %raw
    The output file @file{@var{name}.h} normally defines the tokens with
    Yacc-compatible token numbers.  If this option is specified, the
    internal Bison numbers are used instead.  (Yacc-compatible numbers start
    at 257 except for single character tokens; Bison assigns token numbers
    sequentially for all tokens starting at 3.)

Unfortunately, as far as I can tell, it never worked: token numbers
are indeed changed in the generated tables (from external token number
to internal), yet the code was still applying the mapping from
external token numbers to internal token numbers.

This commit reintroduces the feature as it was expected to be.

* data/skeletons/bison.m4 (b4_token_format): When api.token.raw is
enabled, use the internal token number.
* data/skeletons/yacc.c (yytranslate): Don't emit if api.token.raw is
enabled.
(YYTRANSLATE): Adjust.
2019-09-14 09:55:17 +02:00
Akim Demaille d94d83e10b style: tidy yacc.c
* data/skeletons/yacc.c: Include 'c.m4' first.
Then sort the handling of %define variables.
* tests/input.at: Adjust.
2019-09-14 09:55:17 +02:00
Akim Demaille 2f6e377953 CI: disable ICC
It seems that Intel changed something in their license management.
https://github.com/nemequ/icc-travis/issues/15
2019-09-14 09:55:17 +02:00
Akim Demaille 32dff87c1d diagnostics: fix use of complain_indent
* src/symtab.c (symbol_class_set): Here.
* tests/diagnostics.at, tests/input.at, tests/regression.at: Adjust
expectations.
2019-09-14 09:47:49 +02:00
Akim Demaille 19da501e06 input: stop treating lone CRs as end-of-lines
We used to treat lone CRs (\r, aka ^M) as regular NLs (\n), probably
to please Classic MacOS.  As of today, it makes more sense to treat \r
like a plain white space character.

https://lists.gnu.org/archive/html/bison-patches/2019-09/msg00027.html

* src/scan-gram.l (no_cr_read): Remove.  Instead, use...
(eol): this new abbreviation denoting end-of-line.
* src/location.c (caret_getc): New.
(location_caret): Use it.
* tests/diagnostics.at (Carriage return): Adjust expectations.
(CR NL): New.
2019-09-14 09:23:47 +02:00
Akim Demaille 5e4133175d Merge tag 'v3.4.2' into HEAD
bison 3.4.2

* tag 'v3.4.2': (24 commits)
  version 3.4.2
  CI: always uninstall icc
  news: more bug fixes thanks to Marc Schönefeld
  diagnostics: beware of unexpected EOF when quoting the source file
  gnulib: update
  build: fix distcheck
  tests: add noexcept to please GCC 9
  news: update
  fix: don't die when EOF token is defined twice
  tests: check token redeclaration
  yacc.c: beware of GCC's -Wmaybe-uninitialized
  glr.c: initialize vector of bools
  gnulib: update
  check for memory exhaustion
  diagnostics: avoid global variables
  diagnostics: fix invalid error message indentation
  git: ignore files generated in gnulib-po
  c++: avoid duplicate definition of YYUSE
  gnulib: update
  CI: more compilers
  ...
2019-09-12 19:12:24 +02:00
Akim Demaille 0b093ac4d9 maint: post-release administrivia
* NEWS: Add header line for next release.
* .prev-version: Record previous version.
* cfg.mk (old_NEWS_hash): Auto-update.
2019-09-12 18:09:26 +02:00
Akim Demaille 4eed3a0f0c diagnostics: beware of unexpected EOF when quoting the source file
When the input file contains lone CRs (aka, ^M, \r), the locations see
a new line.  Diagnostics look only at \n as end-of-line, so sometimes
there is an offset in diagnostics.  Worse yet: sometimes we loop
endlessly waiting for \n to come from a continuous stream of EOF.

Fix that:
- check for EOF
- beware not to call end_use_class if begin_use_class was not
  called (which would abort).  This could happen if the actual
  line is shorter that the expected one.

Prompted by a (private) report from Marc Schönefeld.

* src/location.c (location_caret): here.
* tests/diagnostics.at (Carriage return): New.
2019-09-12 07:02:46 +02:00
Akim Demaille 84a6621c78 gnulib: update
Contains the creation of the xhash module.
https://lists.gnu.org/archive/html/bug-gnulib/2019-09/msg00046.html

* src/muscle-tab.c, src/state.c, src/symtab.c, src/uniqstr.c:
Use hash_xinitialize.
2019-09-11 09:07:27 +02:00
Akim Demaille 06a273625b build: fix distcheck
* configure.ac (gl_LIBOBJS): Adjust so that the generated files are
indeed the expected ones.
2019-09-11 08:27:27 +02:00
Akim Demaille f6fd9be688 tests: add noexcept to please GCC 9
bison/tests/c++.at:552: bison --color=no -fno-caret  -o list.cc list.y
    bison/tests/c++.at:552: $CXX $CXXFLAGS $CPPFLAGS  $LDFLAGS -o list list.cc $LIBS
    stderr:
    gcc9/c++/ext/new_allocator.h: In instantiation of 'void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = string; _Args = {string}; _Tp = string]':
    gcc9/c++/bits/alloc_traits.h:482:2:   required from 'static void std::allocator_traits<std::allocator<_CharT> >::construct(std::allocator_traits<std::allocator<_CharT> >::allocator_type&, _Up*, _Args&& ...) [with _Up = string; _Args = {string}; _Tp = string; std::allocator_traits<std::allocator<_CharT> >::allocator_type = std::allocator<string>]'
    gcc9/c++/bits/stl_uninitialized.h:888:67:   required from 'void std::__relocate_object_a(_Tp*, _Up*, _Allocator&) [with _Tp = string; _Up = string; _Allocator = std::allocator<string>]'
    gcc9/c++/bits/stl_uninitialized.h:920:47:   required from '_ForwardIterator std::__relocate_a_1(_InputIterator, _InputIterator, _ForwardIterator, _Allocator&) [with _InputIterator = string*; _ForwardIterator = string*; _Allocator = std::allocator<string>]'
    gcc9/c++/bits/stl_uninitialized.h:942:37:   required from '_ForwardIterator std::__relocate_a(_InputIterator, _InputIterator, _ForwardIterator, _Allocator&) [with _InputIterator = string*; _ForwardIterator = string*; _Allocator = std::allocator<string>]'
    gcc9/c++/bits/stl_vector.h:430:35:   required from 'static constexpr bool std::vector<_Tp, _Alloc>::_S_nothrow_relocate(std::true_type) [with _Tp = string; _Alloc = std::allocator<string>; std::true_type = std::integral_constant<bool, true>]'
    gcc9/c++/bits/stl_vector.h:446:28:   required from 'void std::vector<_Tp, _Alloc>::_M_realloc_insert(std::vector<_Tp, _Alloc>::iterator, _Args&& ...) [with _Args = {const string&}; _Tp = string; _Alloc = std::allocator<string>; std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<string*, std::vector<string> >; typename std::_Vector_base<_Tp, _Alloc>::pointer = string*]'
    gcc9/c++/bits/stl_vector.h:1195:4:   required from 'void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = string; _Alloc = std::allocator<string>; std::vector<_Tp, _Alloc>::value_type = string]'
    list.y:126:110:   required from here
    gcc9/c++/bits/vector.tcc:459:44:   in 'constexpr' expansion of 'std::vector<string>::_S_use_relocate()'
    list.y:41:7: error: but 'string::string(string&&)' does not throw; perhaps it should be declared 'noexcept' [-Werror=noexcept]
       41 |       string (string&& s)
          |       ^~~~~~

* tests/c++.at (Variants): Add noexcept where appropriate.
2019-09-08 12:02:30 +02:00
Akim Demaille a9499e6ea2 regen 2019-09-08 08:58:55 +02:00
Akim Demaille 09a4bfdab4 gnulib: update
Contains a fix for
https://lists.gnu.org/archive/html/bug-bison/2019-08/msg00016.html.
See
https://lists.gnu.org/archive/html/bug-gnulib/2019-09/msg00005.html.
Reported by 江 祖铭 (Zu-Ming Jiang).
2019-09-08 08:40:17 +02:00
Akim Demaille 7d701f4378 fix: don't die when EOF token is defined twice
With

    %token EOF 0 EOF 0

we get

    input.y:3.14-16: warning: symbol EOF redeclared [-Wother]
        3 | %token EOF 0 EOF 0
          |              ^~~
    input.y:3.8-10: previous declaration
        3 | %token EOF 0 EOF 0
          |        ^~~
    Assertion failed: (nsyms == ntokens + nvars), function check_and_convert_grammar,
        file /Users/akim/src/gnu/bison/src/reader.c, line 839.

Reported by Marc Schönefeld.

* src/symtab.c (symbol_user_token_number_set): Register only the
first definition of the end of input token.
* tests/input.at (Symbol redeclared): Check that case.
2019-09-07 17:09:43 +02:00
Akim Demaille 378963b139 tests: check token redeclaration
* src/symtab.c (symbol_class_set): Report previous definitions when
redeclared.
* tests/input.at (Symbol redeclared): New.
2019-09-07 17:09:43 +02:00
Akim Demaille 2dd882bce5 glr.c: initialize vector of bools
The CI, with CC='gcc-7 -fsanitize=undefined,address
-fno-omit-frame-pointer', reports:

    calc.cc:1652:50: runtime error: load of value 190, which is not a valid value for type 'bool'
    ../../tests/calc.at:867: cat stderr
    --- expout	2019-09-05 20:30:37.887257545 +0000
    +++ /home/travis/build/bison-3.4.1.72-79a1-dirty/_build/tests/testsuite.dir/at-groups/438/stdout	2019-09-05 20:30:37.887257545 +0000
    @@ -1 +1,2 @@
     syntax error
    +calc.cc:1652:50: runtime error: load of value 190, which is not a valid value for type 'bool'
    438. calc.at:867: 438. Calculator glr.cc  (calc.at:867): FAILED (calc.at:867)

The problem is that yylookaheadNeeds is not initialized in
yyinitStateSet, and when it is copied, the value is not 0 or 1.

* data/skeletons/glr.c (yylookaheadNeeds): Initialize yylookaheadNeeds.
2019-09-06 17:27:56 +02:00
Akim Demaille 989503b1ba yacc.c: beware of GCC's -Wmaybe-uninitialized
Test 400 (calc.at:773: testing Calculator api.push-pull=both
api.pure=full parse.error=verbose %debug %locations %defines
api.prefix={calc} %verbose %yacc) fails on the CI with GCC 8 on
Bionic:

    400. calc.at:773: testing Calculator api.push-pull=both api.pure=full parse.error=verbose %debug %locations %defines api.prefix={calc} %verbose %yacc  ...
    ../../tests/calc.at:773: bison --color=no -fno-caret -Wno-deprecated -o calc.c calc.y
    ../../tests/calc.at:773: $CC $CFLAGS $CPPFLAGS  $LDFLAGS -o calc calc.c calc-lex.c calc-main.c $LIBS
    stderr:
    calc.y: In function 'int calcpush_parse(calcpstate*, int, const CALCSTYPE*, CALCLTYPE*)':
    calc.y:26:20: error: 'yylval.CALCSTYPE::ival' may be used uninitialized in this function [-Werror=maybe-uninitialized]
     %printer { fprintf (yyo, "%d", $$); } <ival>;
                        ^
    calc.c:1272:9: note: 'yylval.CALCSTYPE::ival' was declared here
     YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
             ^~~~~~
    cc1plus: all warnings being treated as errors
    stdout:
    ../../tests/calc.at:773: exit code was 1, expected 0
    400. calc.at:773: 400. Calculator api.push-pull=both api.pure=full parse.error=verbose %debug %locations %defines api.prefix={calc} %verbose %yacc  (calc.at:773): FAILED (calc.at:773)

* data/skeletons/c.m4 (yy_symbol_value_print): Disable the warning
locally.
2019-09-06 17:27:55 +02:00
Akim Demaille 61c2c40092 lalr1.cc: fix LAC support
* data/skeletons/lalr1.cc (ctor): Initialize yy_lac_established_.
This is quite painful to write, and ugly to read.
2019-09-06 17:27:55 +02:00
Akim Demaille 3953c61362 style: fix comment
* tests/atlocal.in: here.
2019-09-06 17:27:55 +02:00
Akim Demaille 39e584c018 CI: more compilers
* .travis.yml: Bionic is now available, with GCC8.
GCC7 sanitizers work, but they are too longer: cover only part 1.
Redefine part 1 and part 2 so that part 1 is really the core of the
tests: not playing with POSIX and C++ compiler for C code.
2019-09-06 17:26:00 +02:00
Akim Demaille 611eaffd28 CI: fail fast 2019-09-06 07:21:54 +02:00
Akim Demaille 3f4ad2cd24 gnulib: update
This update brings file from Gettext 0.20, which is not available on
the CI yet.

.travis.yml: Adjust.
Use Bionic now that it's available.
2019-09-04 18:17:38 +02:00
Akim Demaille 989a7aa865 check for memory exhaustion
hash_initialize returns NULL when out of memory.  Check for it, and
die cleanly instead of crashing.

Reported by 江 祖铭 (Zu-Ming Jiang).
https://lists.gnu.org/archive/html/bug-bison/2019-08/msg00015.html

* src/muscle-tab.c, src/state.c, src/symtab.c, src/uniqstr.c:
Check the value returned by hash_initialize.
2019-09-01 17:53:22 +02:00
Akim Demaille 95cbd56882 news: LAC for C++ 2019-08-30 11:16:57 -05:00
Akim Demaille 92124d27c1 d: remove useless imports
* examples/d/calc.y, tests/calc.at: here.
2019-08-29 07:26:33 -05:00
László VáradyandAkim Demaille 6d81b91ae0 diagnostics: avoid global variables
* src/complain.c (indent_ptr): Remove.
(error_message, complains): Take indent as an argument.
Adjust callers.
2019-08-18 09:40:58 -05:00
László VáradyandAkim Demaille 9145bd0b61 diagnostics: fix invalid error message indentation
https://lists.gnu.org/archive/html/bison-patches/2019-08/msg00007.html

When Bison is started with a flag that suppresses warning messages, the
error_message() function can produce a few gigabytes of indentation
because of a dangling pointer.

* src/complain.c (error_message): Don't reset indent_ptr here, but...
(complain_indent): here.
* tests/diagnostics.at (Indentation with message suppression): Check
this case.
2019-08-18 09:40:44 -05:00
Akim Demaille d7cf3f5b18 c++: use resize to shrink a vector
Suggested by Adrian Vogelsgesang.
https://lists.gnu.org/archive/html/bison-patches/2019-08/msg00009.html

* data/skeletons/lalr1.cc (yy_lac_check_): here.
2019-08-18 06:54:56 -05:00
Akim Demaille f49598a1e1 lalr1.cc: check LAC support
* tests/conflicts.at, tests/input.at, tests/regression.at: here.
2019-08-09 06:40:38 -05:00
Adrian VogelsgesangandAkim Demaille 72d4ae5306 lalr1.cc: add LAC support
Implement lookahead correction (LAC) for the C++ skeleton.  LAC is a
mechanism to make sure that we report the correct list of expected
tokens if a syntax error occurs.  So far, LAC was only supported for
the C skeleton "yacc.c".

* data/skeletons/lalr1.cc: Add LAC support.
* doc/bison.texi: Update.
2019-08-09 06:39:59 -05:00
Adrian VogelsgesangandAkim Demaille 996abe62d7 style: readability improvements to yacc.c
* data/skeletons/yacc.c (yysyntax_error): Change the nesting of `m4`
conditions slightly to make it more readable.
The generated C code stays unchanged.
2019-08-09 06:06:02 -05:00
Adrian VogelsgesangandAkim Demaille 0420362ee8 lalr1.cc: reduce "scope"
* data/skeletons/lalr1.cc (yy_lr_goto_state_): Make it static.
2019-08-09 06:06:00 -05:00
Adrian VogelsgesangandAkim Demaille 6f47eea7ab lalr1.cc: fix indentation of table declarations in the header
* data/skeletons/lalr1.cc: Fix indentation of table declarations in
the generated header.
2019-08-09 05:39:30 -05:00
Akim Demaille 99bfdc09cb tests: prepare LAC tests for more languages
* tests/regression.at: Use %expect to avoid warnings.
Set the keywords to facilitate running specific tests.
Use macros such as AT_YYLEX_DECLARE to facilitate tests for other
languages.
Likewise for AT_FULL_COMPILE.
2019-08-09 05:39:30 -05:00
Akim Demaille 52f21717f7 git: ignore files generated in gnulib-po
Because of them, the CI generates "-dirty" tarballs.
2019-08-09 05:38:19 -05:00
Akim Demaille cbdc22af10 diagnostics: use the modern argmatch interface
* src/complain.h (warnings): Remove Werror.
Adjust dependencies.
Sort.
Remove useless comments (see the doc in argmatch group).
* src/complain.c (warnings_args, warnings_types): Remove.
(warning_argmatch): Use argmatch_warning_value.
(warnings_print_categories): Use argmatch_warning_argument.
2019-07-26 07:57:15 +02:00
Akim Demaille 220c593a79 doc: avoid spurious empty lines in the option table
In Texinfo. empty lines in multitable rows generate empty lines in the
output.  Avoid them altogether.

With help from Gavin Smith.
https://lists.gnu.org/archive/html/bug-texinfo/2019-07/msg00000.html

* build-aux/cross-options.pl: Separate rows with empty lines.
So, to be more readable, generate a single line for each row.
Use Perl format to this end.
2019-07-19 07:46:09 +02:00
Akim Demaille e29ac453d0 --fixed-output-files: detach from --yacc
See the previous commit.  This option should be removed, -o suffices.

* src/getargs.c (FIXED_OUTPUT_FILES): New.
Add support for it.
(getargs): Define loc, and use it.
This is safer when we need to pass a pointer to a location.
2019-07-07 15:59:54 +02:00
Akim Demaille 44a56b20ac %fixed-output-files: detach from %yacc
The name fixed-output-files is pretty clear: generate y.tab.c, as Yacc
does.  So let's detach this from %yacc which does more: it requires
POSIX Yacc behavior.

This directive is obsolete since December 29th 2001
8c9a50bee1.  It does not show in the
doc.  I don't want to spend more time on improving its diagnostics, it
could be removed just as well as far as I'm concerned.

* src/scan-gram.l, src/parse-gram.y (%fixed-output-files): Detach from
%yacc.
2019-07-07 15:54:20 +02:00
Akim Demaille f99956b550 style: clarify control flow
* src/getargs.c (language_argmatch): Initialize msg.
Check it instead of relying on a return.
2019-07-07 15:01:45 +02:00
Akim Demaille 1f02348d6c remove MS-DOS support
DJGPP support was dropped in Bison 3.3
(c239e53bab).

AS_FILE_NAME was introduced in
ae40480115.

* src/getargs.c (AS_FILE_NAME): Remove.
2019-07-07 14:38:49 +02:00
Akim Demaille 421ff03018 style: declare options in the same order as in --help
* src/getargs.c (long_options): here.
2019-07-07 14:27:39 +02:00
Akim Demaille 5d3468e0d1 regen 2019-07-07 14:03:37 +02:00
Akim Demaille 40a8dddde1 gnulib: update
Contains a fix for argmatch to get proper man pages.
See https://lists.gnu.org/archive/html/bug-gnulib/2019-07/msg00038.html
2019-07-07 12:22:02 +02:00
Akim Demaille 9bdefd7984 style: comment change
* src/getargs.c: here.
2019-07-07 12:13:30 +02:00
Akim Demaille d233a2e314 doc: remove the --report=look-aheads alias
Years ago we moved from 'look-ahead' to 'lookahead', and that alias
was kept for backward compatibility.  But now that we use argmatch to
generate the documentation, that value clutters the doc.

* src/getargs.c (argmatch_report_args): Remove the
--report=look-aheads alias.
2019-07-07 08:11:35 +02:00
Akim Demaille d90023af5f doc: fix inaccuracies wrt --define and --force-define
The doc says that -Dfoo=bar is the same as %define foo "bar".  It is
not: the quotes are not added (and it makes a difference).

* doc/bison.texi (Tuning the Parser): Fix the definition of -D/-F
* src/getargs.c (usage): Likewise.
2019-07-07 08:11:35 +02:00
Akim Demaille 964c6508b1 doc: put diagnostics related options together
* doc/bison.texi (Diagnostics): New section.
Move --warning, --color and --style there.
* src/getargs.c (usage): Likewise.
2019-07-07 08:11:35 +02:00
Akim Demaille 4e3c6f59cc doc: move -y's documentation into "Tuning the Parser"
Let's clarify --help: use clearer "section" names, as in the doc.
Move --yacc to where it belongs.

* src/getargs.c (usage): Rename "Parser" as "Tuning the Parser", as in
the doc.
Rename "Output" as "Output Files"
Move --yacc to "Tuning the Parser".
* doc/bison.texi: Likewise.
2019-07-07 08:01:37 +02:00
Akim Demaille 801582b410 doc: document colorized diagnostics
* src/getargs.c (argmatch_color_group): New.
(usage): Document --color and --style.
* doc/bison.texi (Bison Options): Split into three subsections.
Document --color and --style.
2019-07-07 08:01:37 +02:00
Akim Demaille 6d35340556 gnulib: use new features of the argmatch module
It can now generate the usage message.

* src/complain.h (feature_fixit_parsable): Rename as...
(feature_fixit): this, for column economy.
Adjust dependencies.
(warning_usage): New.
Use it.
* src/complain.h, src/complain.c, src/getargs.h, src/getargs.c:
Use ARGMATCH_DEFINE_GROUP instead of the older interface.
2019-07-03 07:02:44 +02:00
Akim Demaille 1161649446 preserve the indentation in the ouput
Preserve the actions' initial indentation.  For instance, on

    | %define api.value.type {int}
    | %%
    | exp: exp '/' exp { if ($3)
    |                     $$ = $1 + $3;
    |                   else
    |                     $$ = 0; }

we used to generate

    |     { if (yyvsp[0])
    |                     yyval = yyvsp[-2] + yyvsp[0];
    |                   else
    |                    yyval = 0; }

now we produce

    |                  { if (yyvsp[0])
    |                     yyval = yyvsp[-2] + yyvsp[0];
    |                   else
    |                     yyval = 0; }

See https://lists.gnu.org/archive/html/bison-patches/2019-06/msg00012.html.

* data/skeletons/bison.m4 (b4_symbol_action): Output the code in
column 0, leave indentation matters to the C code.
* src/output.c (user_actions_output): Preserve the incoming
indentation in the output.
(prepare_symbol_definitions): Likewise for %printer/%destructor.
* tests/synclines.at (Output columns): New.
2019-07-02 07:38:52 +02:00
Akim Demaille 13577a809e style: prefer passing locations by pointer
The code is inconsistent: sometimes we pass by value, sometimes by
reference.  Let's stick to the last, more conventional for large
values in C.

* src/scan-code.l: Pass locations by reference.
2019-07-01 07:23:42 +02:00
Akim Demaille afc219a765 c++: avoid duplicate definition of YYUSE
Reported by Frank Heckenbach.
https://lists.gnu.org/archive/html/bug-bison/2019-06/msg00009.html

* data/skeletons/lalr1.cc (b4_shared_declarations): Remove the
duplicate definition of YYUSE, the other one coming from
b4_attribute_define.
2019-06-30 19:19:43 +02:00
Akim Demaille 21aa4b2713 style: comment changes
* examples/c/lexcalc/local.mk, examples/c/reccalc/local.mk:
Here.
2019-06-27 07:57:21 +02:00
Akim Demaille 63f4dca78f tests: restructure for clarity
* tests/calc.at (AT_CALC_MAIN, AT_CALC_LEX): Rewrite on top of
AT_LANG_DISPATCH.
2019-06-23 19:26:13 +02:00
Akim Demaille 0984f70e08 d: track locations
* configure.ac (DCFLAGS): Pass -g.
* data/skeletons/d.m4 (b4_locations_if): Remove, let bison.m4's one do
its job.
* data/skeletons/lalr1.d (position): Leave filename empty by default.
(position::toString): Don't print empty file names.
(location::this): New ctor.
(location::toString): Match the implementations of C/C++.
(yy_semantic_null): Leave undefined, the previous implementation does
not compile.
* tests/calc.at: Improve the implementation for D.
Enable more checks, in particular using locations.
* tests/local.at (AT_YYERROR_DEFINE(d)): Fix its implementation.
2019-06-23 11:20:18 +02:00
Akim Demaille f26bd45da3 d: style changes
* data/skeletons/lalr1.d: Use a more traditional quotation scheme.
Formatting changes.
2019-06-23 11:20:16 +02:00
Akim Demaille a3adc1701b d: put internal details inside the parser
Avoid name clashes, etc.

* data/skeletons/lalr1.d (YYStackElement, YYStack): Move inside the
parser.
2019-06-23 11:19:46 +02:00
Akim Demaille 7ab275214b gnulib: update 2019-06-22 09:03:19 +02:00
Akim Demaille 0428c429a1 remove "experimental" warnings
Sadly enough, AFAIK, there were never answers to the "More user
feedback will help to stabilize it" sentences.  Remove them.

* src/getargs.c: IELR, canonical LR and XML output are here to stay,
and they are no more experimental than some other features.
* doc/bison.texi: Likewise.
Also remove "experimental" warning for Java, LAC, LR tuning options,
and named references.
2019-06-22 08:29:06 +02:00
Akim Demaille 14fb2cc820 CI: propagate sftp failures
* .travis.yml (stage: "compile"): here.
2019-06-22 08:29:06 +02:00
Akim Demaille faf033957c d: honor %define parse.trace
* data/skeletons/lalr1.d: Don't generate debug code if parse.trace is
not enabled.
2019-06-20 06:57:27 +02:00
Akim Demaille 0555e25a41 d: style changes
* data/skeletons/lalr1.d: here.
2019-06-20 06:57:27 +02:00
Akim Demaille cde8c0a0e6 d: prefer delegation to duplication
* data/skeletons/lalr1.d: Delegate the construction of the scanner.
2019-06-20 06:57:27 +02:00
Akim Demaille 5b525e86a5 d: enable #line output
* data/skeletons/d.m4 (b4_sync_start): New.
2019-06-20 06:57:27 +02:00
Akim Demaille df77a98edf d: style changes
* data/skeletons/lalr1.d: here.
* examples/d/calc.y: Remove incorrect support for decimal numbers.
Formatting changes.
2019-06-20 06:57:27 +02:00
Akim Demaille c23fa0fc97 style: reduce scopes in glr.c
* data/skeletons/glr.c: here.
2019-06-20 06:57:27 +02:00
Akim Demaille 08c0571613 java: honor %define parse.trace
* data/skeletons/lalr1.java: Don't generate debug code if parse.trace
is not enabled.
2019-06-20 06:57:27 +02:00
Akim Demaille f2b210a901 java: fix support for api.prefix
* data/skeletons/java.m4: here.
* tests/java.at: Check it.
2019-06-19 19:15:31 +02:00
Akim Demaille 66ac4acc6c java: style changes
* data/skeletons/lalr1.java: Use more conventional function names for
Java.
Prefer < and <= to => and >.
Use the same approach for m4 quotation as in the other skeletons.
Fix indentation issues.

* tests/calc.at, tests/java.at, tests/javapush.at: Fix quotation style.
(main): Use 'args', not 'argv', the former seems more conventional and
is used elsewhere in Bison.
Prefer character literals to integers to denote characters.
* examples/java/Calc.y: Likewise.
2019-06-19 19:15:26 +02:00
Akim Demaille cd0f25df5f CI: avoid useless git costs
Travis answered favorably to my suggestion to provide a means to
disable git clone on some jobs (issue 7542).  See
https://docs.travis-ci.com/user/customizing-the-build/#disabling-git-clone.

* .travis.yml: Disable git globally, enable it for i. the compile job,
and ii. the test job on ICC which needs the install-icc.sh script.
2019-06-15 10:28:50 +02:00
Akim Demaille 0f46038589 style: simplify strings to translate
* src/conflicts.c (log_resolution): Don't translate indentation.
2019-06-12 21:41:16 +02:00
Akim Demaille 1105cf841b style: reduce scopes, propagate const
* src/conflicts.c (conflicts_output): here.
2019-06-12 21:41:16 +02:00
Akim Demaille a298a6d82b style: use clearer types
* src/conflicts.c (conflicts): Array of Booleans.
2019-06-12 06:59:31 +02:00
Akim Demaille 5f33acefd1 tests: prefer %empty
* tests/regression.at: here.
2019-06-11 20:40:36 +02:00
Akim Demaille 849ba01b8b CI: factor
* .travis.yml (Clang 7 libc++ and ASAN part 2): Reuse bits from "Clang
7 libc++ and ASAN part 1".
2019-06-09 11:11:14 +02:00
Akim Demaille 29c9cb3188 lr0: more debug traces
* src/lr0.c (kernel_check): New.
(new_itemsets, save_reductions): Add traces.
2019-06-09 11:11:12 +02:00
Akim Demaille ec4d49e129 traces: add some colors
This is an experiment.  Maybe more styles will be used (in which case
a short-hand function will be useful), maybe it will be just reverted.
* data/bison-default.css (.traces0): New.
* src/lalr.c (lalr): Use it.
2019-06-09 08:36:01 +02:00
Akim Demaille d84b245c63 tests: make sure the default action properly works in C++
See e3fdc37049: in C++ we generate
explicitly the code for the default action instead of simply copying
blindly the semantic value buffer.  This is important when copying
raw memory is not enough, as exemplified by move-only types.

This is currently tested by examples/c++/variant.yy and variant-11.yy.
But it is safer to also have a test in the main test suite.

* tests/local.at (AT_REQUIRE_CXX_STD): Fix.
(AT_BISON_OPTION_PUSHDEFS, AT_BISON_OPTION_POPDEFS): Define/undefine
AT_BISON_OPTIONS.
* tests/c++.at (Default action): New.
2019-06-09 08:36:01 +02:00
Akim Demaille 73797b2552 tests: main: support -s and -p
* tests/local.at (AT_MAIN_DEFINE(c), AT_MAIN_DEFINE(c++)): here.
2019-06-09 08:36:01 +02:00
Akim Demaille dfef525920 tests: remove useless support of '.' in integers
* tests/calc.at: here.
* doc/bison.texi: Avoid uninitialized variables.
2019-06-04 08:36:43 +02:00
Akim Demaille 7f017ae1c9 tests: refactor checks on sets
It will be convenient to check sets elsewhere.

* tests/sets.at (AT_EXTRACT_SETS): Transform into...
* tests/local.at (AT_SETS_CHECK): this.
* tests/sets.at: Adjust.
2019-05-29 08:38:16 +02:00
Akim Demaille 65126716d7 update-test: some file names have dashes in them
* build-aux/update-test (log): Rename as...
(trace): this, to avoid clashes with the log variable.
(getargs): Clarify the type of the arguments.
2019-05-29 08:26:20 +02:00
114 changed files with 4731 additions and 2855 deletions
-3
View File
@@ -1,9 +1,6 @@
/ABOUT-NLS~
*.eps
*.log *.log
*.o *.o
*.pdf *.pdf
*.png
*.stamp *.stamp
*.trs *.trs
*~ *~
+1 -1
View File
@@ -1 +1 @@
3.4.1 3.4.2
+125 -121
View File
@@ -17,10 +17,10 @@ env:
# Less dependencies, and little git content (we would like to have none, but it's not # Less dependencies, and little git content (we would like to have none, but it's not
# an option on Travis). # an option on Travis).
stages: stages:
- compile - dist
- test - check
# The 'test' jobs do not need the repo at all, only the 'compile' # The 'check' jobs do not need the repo at all, only the 'dist'
# does. Let's save time, bandwith, energy, and polar bears. # does. Let's save time, bandwith, energy, and polar bears.
git: git:
clone: false clone: false
@@ -29,7 +29,8 @@ git:
# (https://docs.travis-ci.com/user/conditional-builds-stages-jobs/). # (https://docs.travis-ci.com/user/conditional-builds-stages-jobs/).
jobs: jobs:
include: include:
- stage: "compile" - stage: dist
name: "Make dist"
git: git:
clone: true clone: true
dist: bionic dist: bionic
@@ -49,23 +50,24 @@ jobs:
- git submodule update --init --recursive - git submodule update --init --recursive
- ./bootstrap - ./bootstrap
# gnulib-po/Makefile.in.in is about Gettext 0.20, which is not available in bionic. So it will break here. Override it. Don't use autopoint, which sends some other files in the past.
- cp po/Makefile.in.in gnulib-po
- ./configure --enable-gcc-warnings || { cat config.log && false; } - ./configure --enable-gcc-warnings || { cat config.log && false; }
- make -j2 - make -j2
- make -j2 dist - make -j2 dist
# Can help understanding why we get "dirty" tarballs.
- git status
- dist=$(echo bison*.xz) - dist=$(echo bison*.xz)
# Unfortunately we cannot deterministically know the name of the tarball without the full # Unfortunately we cannot deterministically know the name of the tarball without the full
# git history (because git describe --abbrev=4 may use more than 4 characters if there are # git history (because git describe --abbrev=4 may use more than 4 characters if there are
# conflicts). # conflicts).
# #
# So for the sake of the 'test' jobs (that don't even have the repo at all), also expose this # So for the sake of the 'check' jobs (that don't even have the repo at all), also expose this
# tarball on a name that only depends on the Travis build number. # tarball on a name that only depends on the Travis build number.
# #
# Without -b -, exit status is always 0. # Without -b -, exit status is always 0.
- sftp -b - [email protected] <<< "put $dist"$'\n'"ln -s $dist bison-$TRAVIS_BUILD_NUMBER.tar.xz" #
# If we rerun a job that was already uploaded, 'ln -s' will fail: remove beforehand.
- sftp -b - [email protected] <<< "put $dist"$'\n'"-rm bison-$TRAVIS_BUILD_NUMBER.tar.xz"$'\n'"ln -s $dist bison-$TRAVIS_BUILD_NUMBER.tar.xz"
## ------- ## ## ------- ##
## First. ## ## First. ##
@@ -74,163 +76,167 @@ jobs:
# Start with three completely different environments, to get # Start with three completely different environments, to get
# errors asap. # errors asap.
- name: "GCC 8 -O3" - name: "GCC 9 -O3"
stage: test stage: check
os: linux os: linux
dist: bionic dist: bionic
addons: addons:
apt: apt:
packages: sources:
- g++-8 # See https://github.com/travis-ci/apt-source-safelist/issues/410.
- sourceline: 'ppa:ubuntu-toolchain-r/test'
packages: g++-9
env: env:
- MATRIX_EVAL="CC=gcc-8 && CXX=g++-8 && CONFIGUREFLAGS='CPPFLAGS=-DNDEBUG CFLAGS=-O3 CXXFLAGS=-O3'" - MATRIX_EVAL="CC=gcc-9 && CXX=g++-9 && CONFIGUREFLAGS='CPPFLAGS=-DNDEBUG CFLAGS=-O3 CXXFLAGS=-O3'"
# ASAN is time consuming, and we timeout the 50min granted by # ASAN is time consuming, and we timeout the 50min granted by
# Travis if we run all the tests in one go. Run in two parts. # Travis if we run all the tests in one go. Run in two parts.
- name: "Clang 8 libc++ and ASAN part 1" - name: "Clang 9 libc++ and ASAN part 1"
stage: test stage: check
os: linux os: linux
dist: bionic dist: bionic
addons: &clang8 addons: &clang9
apt: apt:
sources: sources:
- llvm-toolchain-bionic-8 # See https://github.com/travis-ci/apt-source-safelist/issues/410.
- ubuntu-toolchain-r-test - sourceline: 'ppa:ubuntu-toolchain-r/test'
- sourceline: 'deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-9 main'
key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'
packages: packages:
- clang-8 - clang-9
- libc++-8-dev - libc++-9-dev
- libc++abi-8-dev - libc++abi-9-dev
env: env:
# Do not use ASAN with ubuntu's libc++: https://bugs.llvm.org/show_bug.cgi?id=17379 # Do not use ASAN with ubuntu's libc++: https://bugs.llvm.org/show_bug.cgi?id=17379
- MATRIX_EVAL="PART=1 CC='clang-8 -fsanitize=address' CXX='clang++-8 -fsanitize=address -stdlib=libc++'" - MATRIX_EVAL="CC='clang-9 -fsanitize=address' CXX='clang++-9 -fsanitize=address -stdlib=libc++'"
- PART=1
- name: "Clang 8 libc++ and ASAN part 2" - name: "Clang 9 libc++ and ASAN part 2"
stage: test stage: check
os: linux os: linux
dist: bionic dist: bionic
addons: *clang8 addons: *clang9
env: env:
# Do not use ASAN with ubuntu's libc++: https://bugs.llvm.org/show_bug.cgi?id=17379 # Do not use ASAN with ubuntu's libc++: https://bugs.llvm.org/show_bug.cgi?id=17379
- MATRIX_EVAL="PART=2 CC='clang-8 -fsanitize=address' CXX='clang++-8 -fsanitize=address -stdlib=libc++'" - MATRIX_EVAL="CC='clang-9 -fsanitize=address' CXX='clang++-9 -fsanitize=address -stdlib=libc++'"
- PART=2
- name: "ICC" # Currently no longer works (https://github.com/nemequ/icc-travis/issues/15).
stage: test # - name: "ICC"
# We need the build-aux/install-icc.sh script. # stage: check
git: # # We need the build-aux/install-icc.sh script.
clone: true # git:
submodules: false # clone: true
depth: 1 # submodules: false
os: linux # depth: 1
dist: xenial # os: linux
env: # dist: xenial
# ICC's warnings are often very wrong (e.g., it thinks foo ? # env:
# "bar" : "baz" is char* instead of const char*), so don't try # # ICC's warnings are often very wrong (e.g., it thinks foo ?
# to work around the, and obviously, don't die on them. # # "bar" : "baz" is char* instead of const char*), so don't try
- MATRIX_EVAL="CC=icc && CXX=icpc" # # to work around the, and obviously, don't die on them.
- MAKE_ARGS='WERROR_CFLAGS= WERROR_CXXFLAGS=' # - MATRIX_EVAL="CC=icc && CXX=icpc"
# - MAKE_ARGS='WERROR_CFLAGS= WERROR_CXXFLAGS='
## ----- ## ## ----- ##
## GCC. ## ## GCC. ##
## ----- ## ## ----- ##
- name: "GCC 7 with sanitizers" - name: "GCC 8 with sanitizers part 1"
os: linux os: linux
dist: bionic dist: bionic
addons: addons:
apt: apt:
packages: packages: g++-8
- g++-7
env: env:
- MATRIX_EVAL="CC='gcc-7 -fsanitize=undefined,address -fno-omit-frame-pointer' CXX='g++-7 -fsanitize=undefined,address -fno-omit-frame-pointer'" - MATRIX_EVAL="CC='gcc-8 -fsanitize=undefined,address -fno-omit-frame-pointer' CXX='g++-8 -fsanitize=undefined,address -fno-omit-frame-pointer'"
- CONFIGUREFLAGS='CFLAGS=-O1 CXXFLAGS=-O1'
- PART=1 - PART=1
- name: "GCC 7" - name: "GCC 8"
stage: test stage: check
os: linux os: linux
dist: bionic dist: bionic
addons: addons:
apt: apt:
packages: packages: g++-8
- g++-7 env:
- MATRIX_EVAL="CC=gcc-8 && CXX=g++-8"
- name: "GCC 7"
stage: check
os: linux
dist: bionic
addons:
apt:
packages: g++-7
env: env:
- MATRIX_EVAL="CC=gcc-7 && CXX=g++-7" - MATRIX_EVAL="CC=gcc-7 && CXX=g++-7"
- name: "GCC 6" - name: "GCC 6"
stage: test stage: check
os: linux os: linux
dist: xenial dist: xenial
addons: addons:
apt: apt:
sources: sources: ubuntu-toolchain-r-test
- ubuntu-toolchain-r-test packages: g++-6
packages:
- g++-6
env: env:
- MATRIX_EVAL="CC=gcc-6 && CXX=g++-6" - MATRIX_EVAL="CC=gcc-6 && CXX=g++-6"
- name: "GCC 5" - name: "GCC 5"
stage: test stage: check
os: linux os: linux
dist: xenial dist: xenial
addons: addons:
apt: apt:
sources: sources: ubuntu-toolchain-r-test
- ubuntu-toolchain-r-test packages: g++-5
packages:
- g++-5
env: env:
- MATRIX_EVAL="CC=gcc-5 && CXX=g++-5" - MATRIX_EVAL="CC=gcc-5 && CXX=g++-5"
- name: "GCC 4.9" - name: "GCC 4.9"
stage: test stage: check
os: linux os: linux
dist: xenial dist: xenial
addons: addons:
apt: apt:
sources: sources: ubuntu-toolchain-r-test
- ubuntu-toolchain-r-test packages: g++-4.9
packages:
- g++-4.9
env: env:
- MATRIX_EVAL="CC=gcc-4.9 && CXX=g++-4.9" - MATRIX_EVAL="CC=gcc-4.9 && CXX=g++-4.9"
- name: "GCC 4.8" - name: "GCC 4.8"
stage: test stage: check
os: linux os: linux
dist: xenial dist: xenial
addons: addons:
apt: apt:
sources: sources: ubuntu-toolchain-r-test
- ubuntu-toolchain-r-test packages: g++-4.8
packages:
- g++-4.8
env: env:
- MATRIX_EVAL="CC=gcc-4.8 && CXX=g++-4.8" - MATRIX_EVAL="CC=gcc-4.8 && CXX=g++-4.8"
- name: "GCC 4.7" - name: "GCC 4.7"
stage: test stage: check
os: linux os: linux
dist: xenial dist: xenial
addons: addons:
apt: apt:
sources: sources: ubuntu-toolchain-r-test
- ubuntu-toolchain-r-test packages: g++-4.7
packages:
- g++-4.7
env: env:
- MATRIX_EVAL="CC=gcc-4.7 && CXX=g++-4.7" - MATRIX_EVAL="CC=gcc-4.7 && CXX=g++-4.7"
- name: "GCC 4.6" - name: "GCC 4.6"
stage: test stage: check
os: linux os: linux
dist: xenial dist: xenial
addons: addons:
apt: apt:
sources: sources: ubuntu-toolchain-r-test
- ubuntu-toolchain-r-test packages: g++-4.6
packages:
- g++-4.6
env: env:
- MATRIX_EVAL="CC=gcc-4.6 && CXX=g++-4.6" - MATRIX_EVAL="CC=gcc-4.6 && CXX=g++-4.6"
@@ -238,25 +244,35 @@ jobs:
## Clang. ## ## Clang. ##
## ------- ## ## ------- ##
- name: "Clang 7 -O3 and libc++" - name: "Clang 8 -O3"
stage: test stage: check
os: linux
dist: bionic
addons:
apt:
packages:
- clang-8
- libc++-8-dev
- libc++abi-8-dev
env:
- MATRIX_EVAL="CC=clang-8 && CXX='clang++-8 -stdlib=libc++'"
- CONFIGUREFLAGS='CPPFLAGS=-DNDEBUG CFLAGS=-O3 CXXFLAGS=-O3'
- name: "Clang 7"
stage: check
os: linux os: linux
dist: bionic dist: bionic
addons: addons:
apt: apt:
sources:
- llvm-toolchain-bionic-7
- ubuntu-toolchain-r-test
packages: packages:
- clang-7 - clang-7
- libc++-7-dev - libc++-7-dev
- libc++abi-7-dev - libc++abi-7-dev
env: env:
- MATRIX_EVAL="CC=clang-7 && CXX='clang++-7 -stdlib=libc++'" - MATRIX_EVAL="CC=clang-7 && CXX='clang++-7 -stdlib=libc++'"
- CONFIGUREFLAGS='CPPFLAGS=-DNDEBUG CFLAGS=-O3 CXXFLAGS=-O3'
- name: "Clang 6 -O3 and libc++" - name: "Clang 6 and libc++"
stage: test stage: check
os: linux os: linux
dist: xenial dist: xenial
addons: addons:
@@ -269,16 +285,14 @@ jobs:
- libc++-dev - libc++-dev
env: env:
- MATRIX_EVAL="CC=clang-6.0 && CXX='clang++-6.0 -stdlib=libc++'" - MATRIX_EVAL="CC=clang-6.0 && CXX='clang++-6.0 -stdlib=libc++'"
- CONFIGUREFLAGS='CPPFLAGS=-DNDEBUG CFLAGS=-O3 CXXFLAGS=-O3'
- name: "Clang 5" - name: "Clang 5"
stage: test stage: check
os: linux os: linux
dist: xenial dist: xenial
addons: addons:
apt: apt:
sources: sources: llvm-toolchain-xenial-5.0
- llvm-toolchain-xenial-5.0
packages: packages:
- clang-5.0 - clang-5.0
- libc++-dev - libc++-dev
@@ -286,33 +300,29 @@ jobs:
- MATRIX_EVAL="CC='clang-5.0' CXX='clang++-5.0'" - MATRIX_EVAL="CC='clang-5.0' CXX='clang++-5.0'"
- name: "Clang 4" - name: "Clang 4"
stage: test stage: check
os: linux os: linux
dist: xenial dist: xenial
addons: addons:
apt: apt:
sources: sources: llvm-toolchain-xenial-4.0
- llvm-toolchain-xenial-4.0 packages: clang-4.0
packages:
- clang-4.0
env: env:
- MATRIX_EVAL="CC=clang-4.0 && CXX=clang++-4.0" - MATRIX_EVAL="CC=clang-4.0 && CXX=clang++-4.0"
- name: "Clang 3.9" - name: "Clang 3.9"
stage: test stage: check
os: linux os: linux
dist: xenial dist: xenial
addons: addons:
apt: apt:
sources: sources: llvm-toolchain-xenial-3.9
- llvm-toolchain-xenial-3.9 packages: clang-3.9
packages:
- clang-3.9
env: env:
- MATRIX_EVAL="CC=clang-3.9 && CXX=clang++-3.9" - MATRIX_EVAL="CC=clang-3.9 && CXX=clang++-3.9"
- name: "Clang 3.8" - name: "Clang 3.8"
stage: test stage: check
os: linux os: linux
dist: xenial dist: xenial
addons: addons:
@@ -320,13 +330,12 @@ jobs:
sources: sources:
- ubuntu-toolchain-r-test - ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.8 - llvm-toolchain-precise-3.8
packages: packages: clang-3.8
- clang-3.8
env: env:
- MATRIX_EVAL="CC=clang-3.8 && CXX=clang++-3.8" - MATRIX_EVAL="CC=clang-3.8 && CXX=clang++-3.8"
- name: "CLang 3.7" - name: "CLang 3.7"
stage: test stage: check
os: linux os: linux
dist: xenial dist: xenial
addons: addons:
@@ -334,13 +343,12 @@ jobs:
sources: sources:
- ubuntu-toolchain-r-test - ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.7 - llvm-toolchain-precise-3.7
packages: packages: clang-3.7
- clang-3.7
env: env:
- MATRIX_EVAL="CC=clang-3.7 && CXX=clang++-3.7" - MATRIX_EVAL="CC=clang-3.7 && CXX=clang++-3.7"
- name: "Clang 3.6" - name: "Clang 3.6"
stage: test stage: check
os: linux os: linux
dist: xenial dist: xenial
addons: addons:
@@ -348,13 +356,12 @@ jobs:
sources: sources:
- ubuntu-toolchain-r-test - ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.6 - llvm-toolchain-precise-3.6
packages: packages: clang-3.6
- clang-3.6
env: env:
- MATRIX_EVAL="CC=clang-3.6 && CXX=clang++-3.6" - MATRIX_EVAL="CC=clang-3.6 && CXX=clang++-3.6"
- name: "Clang 3.5" - name: "Clang 3.5"
stage: test stage: check
os: linux os: linux
dist: xenial dist: xenial
addons: addons:
@@ -362,34 +369,31 @@ jobs:
sources: sources:
- ubuntu-toolchain-r-test - ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.5 - llvm-toolchain-precise-3.5
packages: packages: clang-3.5
- clang-3.5
env: env:
- MATRIX_EVAL="CC=clang-3.5 && CXX=clang++-3.5" - MATRIX_EVAL="CC=clang-3.5 && CXX=clang++-3.5"
- name: "Clang 3.4" - name: "Clang 3.4"
stage: test stage: check
os: linux os: linux
# Not available on Xenial. # Not available on Xenial.
dist: trusty dist: trusty
addons: addons:
apt: apt:
packages: packages: clang-3.4
- clang-3.4
env: env:
# No versioned name installed, but beware that Travis installs # No versioned name installed, but beware that Travis installs
# a more modern clang earlier in the default PATH. # a more modern clang earlier in the default PATH.
- MATRIX_EVAL='CC=/usr/bin/clang && CXX=/usr/bin/clang++' - MATRIX_EVAL='CC=/usr/bin/clang && CXX=/usr/bin/clang++'
- name: "Clang 3.3" - name: "Clang 3.3"
stage: test stage: check
os: linux os: linux
# Not available on Xenial. # Not available on Xenial.
dist: trusty dist: trusty
addons: addons:
apt: apt:
packages: packages: clang-3.3
- clang-3.3
env: env:
# See comment for 3.4. # See comment for 3.4.
- MATRIX_EVAL='CC=/usr/bin/clang && CXX=/usr/bin/clang++' - MATRIX_EVAL='CC=/usr/bin/clang && CXX=/usr/bin/clang++'
@@ -408,7 +412,7 @@ before_script:
- echo '|1|bpc51UGxoDZjCPiwRlCStW32trI=|rfh6mLoLZv/vAvOVrpZXI1hTLxg= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIR+ckMoJTNXHvAQLHWSfrRnrNJGW2ZR6kr5pBVDGCkz1v1RcQ5rleq0NAt9kS3v4hgnuLiEVnK7KDRzcEH3ikc=' >>~/.ssh/known_hosts - echo '|1|bpc51UGxoDZjCPiwRlCStW32trI=|rfh6mLoLZv/vAvOVrpZXI1hTLxg= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIR+ckMoJTNXHvAQLHWSfrRnrNJGW2ZR6kr5pBVDGCkz1v1RcQ5rleq0NAt9kS3v4hgnuLiEVnK7KDRzcEH3ikc=' >>~/.ssh/known_hosts
- chmod 600 ~/.ssh/known_hosts - chmod 600 ~/.ssh/known_hosts
# Applies only to the jobs that don't have a 'script', i.e., applies to all the 'test' jobs, but not the 'compile' one. # Applies only to the jobs that don't have a 'script', i.e., applies to all the 'check' jobs, but not the 'dist' one.
script: script:
- eval "$MATRIX_EVAL" - eval "$MATRIX_EVAL"
# Beware not too leak $SSH_PRIVATE_KEY. # Beware not too leak $SSH_PRIVATE_KEY.
+107 -3
View File
@@ -1,5 +1,109 @@
GNU Bison NEWS GNU Bison NEWS
* Noteworthy changes in release 3.4.90 (2019-10-29) [beta]
** Backward incompatible changes
Lone carriage-return characters (aka \r or ^M) in the grammar files are no
longer treated as end-of-lines. This changes the diagnostics, and in
particular their locations.
In C++, line numbers and columns are now represented as 'int' not
'unsigned', so that integer overflow on positions is easily checkable via
'gcc -fsanitize=undefined' and the like. This affects the API for
positions.
** Bug fixes
In Java, %define api.prefix was ignored. It now behaves as expected.
** New features
*** Lookahead correction in C++
Contributed by Adrian Vogelsgesang.
The C++ deterministic skeleton (lalr1.cc) now supports LAC, via the
%define variable parse.lac.
*** Variable api.token.raw: Optimized token numbers (all skeletons)
In the generated parsers, tokens have two numbers: the "external" token
number as returned by yylex (which starts at 257), and the "internal"
symbol number (which starts at 3). Each time yylex is called, a table
lookup maps the external token number to the internal symbol number.
When the %define variable api.token.raw is set, tokens are assigned their
internal number, which saves one table lookup per token, and also saves
the generation of the mapping table.
The gain is typically moderate, but in extreme cases (very simple user
actions), a 10% improvement can be observed.
*** Diagnostics with insertion
The diagnostics now display suggestion below the underlined source.
Replacement for undeclared symbols are now also suggested.
$ cat /tmp/foo.y
%%
list: lis '.' |
$ bison -Wall foo.y
foo.y:2.7-9: error: symbol 'lis' is used, but is not defined as a token and has no rules; did you mean 'list'?
2 | list: lis '.' |
| ^~~
| list
foo.y:2.16: warning: empty rule without %empty [-Wempty-rule]
2 | list: lis '.' |
| ^
| %empty
foo.y: warning: fix-its can be applied. Rerun with option '--update'. [-Wother]
*** Diagnostics about long lines
Quoted sources may now be truncated to fit the screen. For instance, on a
30-column wide terminal:
$ cat foo.y
%token FOO FOO FOO
%%
exp: FOO
$ bison foo.y
foo.y:1.34-36: warning: symbol FOO redeclared [-Wother]
1 | … FOO …
| ^~~
foo.y:1.8-10: previous declaration
1 | %token FOO …
| ^~~
foo.y:1.62-64: warning: symbol FOO redeclared [-Wother]
1 | … FOO
| ^~~
foo.y:1.8-10: previous declaration
1 | %token FOO …
| ^~~
*** Debug traces in Java
The Java backend no longer emits code and data for parser tracing if the
%define variable parse.trace is not defined.
*** Generated parsers prefer signed integer types
Bison skeletons now prefer signed to unsigned integer types when either
will do, as the signed types are less error-prone and allow for better
checking with 'gcc -fsanitize=undefined'. Also, the types chosen are now
portable to unusual machines where char, short and int are all the same
width. On non-GNU platforms this may entail including <limits.h> and (if
available) <stdint.h> to define integer types and constants.
*** Generated parsers use better types for states
Stacks now use the best integral type for state numbers, instead of always
using 15 bits. As a result "small" parsers now have a smaller memory
footprint (they use 8 bits), and there is support for large automata (16
bits), and extra large (using int, i.e., typically 31 bits).
* Noteworthy changes in release 3.4.2 (2019-09-12) [stable] * Noteworthy changes in release 3.4.2 (2019-09-12) [stable]
** Bug fixes ** Bug fixes
@@ -900,10 +1004,10 @@ GNU Bison NEWS
bison used to report: bison used to report:
/tmp/foo.yy:2.10-11: error: %printer redeclaration for FOO foo.yy:2.10-11: error: %printer redeclaration for FOO
%printer {} "foo" %printer {} "foo"
^^ ^^
/tmp/foo.yy:3.10-11: previous declaration foo.yy:3.10-11: previous declaration
%printer {} FOO %printer {} FOO
^^ ^^
@@ -3650,7 +3754,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
LocalWords: Heimbigner AST src ast Makefile srcdir MinGW xxlex XXSTYPE LocalWords: Heimbigner AST src ast Makefile srcdir MinGW xxlex XXSTYPE
LocalWords: XXLTYPE strictfp IDEs ffixit fdiagnostics parseable fixits LocalWords: XXLTYPE strictfp IDEs ffixit fdiagnostics parseable fixits
LocalWords: Wdeprecated yytext Variadic variadic yyrhs yyphrs RCS README LocalWords: Wdeprecated yytext Variadic variadic yyrhs yyphrs RCS README
LocalWords: noexcept constexpr ispell american deprecations LocalWords: noexcept constexpr ispell american deprecations backend
Local Variables: Local Variables:
ispell-dictionary: "american" ispell-dictionary: "american"
+17 -15
View File
@@ -1,25 +1,25 @@
This package contains the GNU Bison parser generator. This package contains the GNU Bison parser generator.
* Installation # Installation
** Build from git ## Build from git
Here are basic installation instructions for a repository checkout: Here are basic installation instructions for a repository checkout:
$ git submodules update --init $ git submodule update --init
$ ./bootstrap $ ./bootstrap
then proceed with the usual 'configure && make' steps. then proceed with the usual 'configure && make' steps.
README-hacking contains more information about building and modifying the Be sure to read README-hacking, which contains all the needed information
software. about building, modifying and checking Bison.
** Build for tarball ## Build from tarball
See the file INSTALL for generic compilation and installation instructions. See the file INSTALL for generic compilation and installation instructions.
Bison requires GNU m4 1.4.6 or later. See: Bison requires GNU m4 1.4.6 or later. See:
https://ftp.gnu.org/gnu/m4/m4-1.4.6.tar.gz https://ftp.gnu.org/gnu/m4/m4-1.4.6.tar.gz
** Relocatability ## Relocatability
If you pass '--enable-relocatable' to 'configure', Bison is relocatable. If you pass '--enable-relocatable' to 'configure', Bison is relocatable.
A relocatable program can be moved or copied to a different location on the A relocatable program can be moved or copied to a different location on the
@@ -29,7 +29,7 @@ invoke them through the symlink.
See "Enabling Relocatability" in the documentation. See "Enabling Relocatability" in the documentation.
** Internationalization ## Internationalization
Bison supports two catalogs: one for Bison itself (i.e., for the Bison supports two catalogs: one for Bison itself (i.e., for the
maintainer-side parser generation), and one for the generated parsers (i.e., maintainer-side parser generation), and one for the generated parsers (i.e.,
for the user-side parser execution). The requirements between both differ: for the user-side parser execution). The requirements between both differ:
@@ -39,7 +39,7 @@ generated parsers could have been localized. See
http://lists.gnu.org/archive/html/bug-bison/2009-08/msg00006.html for more http://lists.gnu.org/archive/html/bug-bison/2009-08/msg00006.html for more
details. details.
* Questions # Questions
See the section FAQ in the documentation (doc/bison.info) for frequently See the section FAQ in the documentation (doc/bison.info) for frequently
asked questions. The documentation is also available in PDF and HTML, asked questions. The documentation is also available in PDF and HTML,
provided you have a recent version of Texinfo installed: run "make pdf" or provided you have a recent version of Texinfo installed: run "make pdf" or
@@ -48,19 +48,19 @@ provided you have a recent version of Texinfo installed: run "make pdf" or
If you have questions about using Bison and the documentation does not If you have questions about using Bison and the documentation does not
answer them, please send mail to <[email protected]>. answer them, please send mail to <[email protected]>.
* Bug reports # Bug reports
Please send bug reports to <[email protected]>. Be sure to include the Please send bug reports to <[email protected]>. Be sure to include the
version number from 'bison --version', and a complete, self-contained test version number from 'bison --version', and a complete, self-contained test
case in each bug report. case in each bug report.
* Copyright statements # Copyright statements
For any copyright year range specified as YYYY-ZZZZ in this package, note For any copyright year range specified as YYYY-ZZZZ in this package, note
that the range specifies every single year in that closed interval. that the range specifies every single year in that closed interval.
----- <!--
Local Variables: Local Variables:
mode: outline mode: markdown
fill-column: 76 fill-column: 76
ispell-dictionary: "american" ispell-dictionary: "american"
End: End:
@@ -83,5 +83,7 @@ GNU General Public License for more details.
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/>.
# LocalWords: parsers ngettext Texinfo pdf html YYYY ZZZZ ispell american LocalWords: parsers ngettext Texinfo pdf html YYYY ZZZZ ispell american
# LocalWords: MERCHANTABILITY LocalWords: MERCHANTABILITY
-->
+11 -4
View File
@@ -45,8 +45,8 @@ processes tabs in its input.
* Working from the repository * Working from the repository
These notes intend to help people working on the checked-out sources. These notes intend to help people working on the checked-out sources. These
These requirements do not apply when building from a distribution tarball. requirements do not apply when building from a distribution tarball.
** Requirements ** Requirements
@@ -201,7 +201,6 @@ added the "[-Wother]" part to all the warnings). Part of the update can be
done with a crude tool: tests/update-test. Read it for more information. done with a crude tool: tests/update-test. Read it for more information.
** TESTSUITEFLAGS ** TESTSUITEFLAGS
To run just the testsuite (not the tests related to the examples), run `make To run just the testsuite (not the tests related to the examples), run `make
check-local`. check-local`.
@@ -212,6 +211,10 @@ can be sped up in two ways:
Using -j, in a make-like fashion, for example: Using -j, in a make-like fashion, for example:
$ make check-local TESTSUITEFLAGS='-j8' $ make check-local TESTSUITEFLAGS='-j8'
Actually, when using GNU Make, TESTSUITEFLAGS defaults to the -jN passed to
it, so you may simply run
$ make check-local -j8
Running only the tests of a certain category, as specified in the AT files Running only the tests of a certain category, as specified in the AT files
with AT_KEYWORDS([[category]]). Categories include: with AT_KEYWORDS([[category]]). Categories include:
- c++, for c++ parsers - c++, for c++ parsers
@@ -224,6 +227,10 @@ To run a specific set of tests, use -k (for "keyword"). For example:
$ make check-local TESTSUITEFLAGS='-k c++' $ make check-local TESTSUITEFLAGS='-k c++'
Both can be combined. Both can be combined.
$ make check-local TESTSUITEFLAGS='-j8 -k c++'
To rerun the tests that failed:
$ make recheck -j5
** Typical errors ** Typical errors
If the test suite shows failures such as the following one If the test suite shows failures such as the following one
@@ -309,7 +316,7 @@ re-run the tests, run:
./gnulib-tool --symlink --create-test --dir=/tmp/gnutest bitset-tests ./gnulib-tool --symlink --create-test --dir=/tmp/gnutest bitset-tests
cd /tmp/gnutest cd /tmp/gnutest
./configure CC='gcc-mp-8 -fsanitize=undefined' ./configure -C CC='gcc-mp-8 -fsanitize=undefined' CFLAGS='-ggdb'
make check make check
* Release Procedure * Release Procedure
Symlink
+1
View File
@@ -0,0 +1 @@
README
+7 -1
View File
@@ -10,6 +10,7 @@ Albert Chin-A-Young [email protected]
Alexander Belopolsky [email protected] Alexander Belopolsky [email protected]
Alexandre Duret-Lutz [email protected] Alexandre Duret-Lutz [email protected]
Andre da Costa Barros [email protected] Andre da Costa Barros [email protected]
Andreas Damm [email protected]
Andreas Schwab [email protected] Andreas Schwab [email protected]
Andrew Suffield [email protected] Andrew Suffield [email protected]
Angelo Borsotti [email protected] Angelo Borsotti [email protected]
@@ -94,8 +95,9 @@ Kees Zeelenberg [email protected]
Keith Browne [email protected] Keith Browne [email protected]
Ken Moffat [email protected] Ken Moffat [email protected]
Kiyoshi Kanazawa [email protected] Kiyoshi Kanazawa [email protected]
Laurent Mascherpa [email protected] Lars Maier [email protected]
László Várady [email protected] László Várady [email protected]
Laurent Mascherpa [email protected]
Lie Yan [email protected] Lie Yan [email protected]
Magnus Fromreide [email protected] Magnus Fromreide [email protected]
Marc Autret [email protected] Marc Autret [email protected]
@@ -173,13 +175,16 @@ Sum Wu [email protected]
Théophile Ranquet [email protected] Théophile Ranquet [email protected]
Thiru Ramakrishnan [email protected] Thiru Ramakrishnan [email protected]
Thomas Jahns [email protected] Thomas Jahns [email protected]
Thomas Petazzoni [email protected]
Tim Josling [email protected] Tim Josling [email protected]
Tim Landscheidt [email protected] Tim Landscheidt [email protected]
Tim Van Holder [email protected] Tim Van Holder [email protected]
Tobias Frost [email protected] Tobias Frost [email protected]
Todd Freed [email protected] Todd Freed [email protected]
Tom Kramer [email protected]
Tom Lane [email protected] Tom Lane [email protected]
Tom Tromey [email protected] Tom Tromey [email protected]
Tomasz Kłoczko [email protected]
Tommy Nordgren [email protected] Tommy Nordgren [email protected]
Troy A. Johnson [email protected] Troy A. Johnson [email protected]
Tys Lefering [email protected] Tys Lefering [email protected]
@@ -198,6 +203,7 @@ Wolfgang Thaller [email protected]
Wolfram Wagner [email protected] Wolfram Wagner [email protected]
Wwp [email protected] Wwp [email protected]
xolodho [email protected] xolodho [email protected]
Yuichiro Kaneko [email protected]
Zack Weinberg [email protected] Zack Weinberg [email protected]
長田偉伸 [email protected] 長田偉伸 [email protected]
江 祖铭 [email protected] 江 祖铭 [email protected]
+159 -42
View File
@@ -1,25 +1,3 @@
* Bison 3.4
** bad diagnostics
%token <val> NUM
%type <val> expr term fact
%%
res: expr { printf ("%d\n", $1); };
expr: expr '+' term { $$ = $1 + $3; } | term;
term: NUM | { $$ = 0; };
The second warning about fact is... useless.
$ bison /tmp/bar.y
/tmp/bar.y:2.24-27: warning: symbol fact is used, but is not defined as a token and has no rules [-Wother]
%type <val> expr term fact
^~~~
/tmp/bar.y: warning: 1 nonterminal useless in grammar [-Wother]
/tmp/bar.y:2.24-27: warning: nonterminal useless in grammar: fact [-Wother]
%type <val> expr term fact
^~~~
* Bison 3.5 * Bison 3.5
** doc ** doc
I feel its ugly to use the GNU style to declare functions in the doc. It I feel its ugly to use the GNU style to declare functions in the doc. It
@@ -29,9 +7,6 @@ breaks.
Also, we seem to teach YYPRINT very early on, although it should be Also, we seem to teach YYPRINT very early on, although it should be
considered deprecated: %printer is superior. considered deprecated: %printer is superior.
** glr.cc
move glr.c into the yy namespace
** improve syntax errors (UTF-8, internationalization) ** improve syntax errors (UTF-8, internationalization)
Bison depends on the current locale. For instance: Bison depends on the current locale. For instance:
@@ -73,10 +48,15 @@ syntax error, unexpected $end, expecting ↦ or 🎅🐃 or '\n'
While at it, we should stop using "$end" by default, in favor of "end of While at it, we should stop using "$end" by default, in favor of "end of
file", or "end of input", whatever. file", or "end of input", whatever. See how lalr1.java does that.
** api.token.raw
Maybe we should exhibit the YYUNDEFTOK token. It could also be assigned a
semantic value so that yyerror could be used to report invalid lexemes.
See also the item "$undefined" below.
* Bison 3.6 * Bison 3.6
** Unit rules ** Unit rules / Injection rules (Akim Demaille)
Maybe we could expand unit rules (or "injections", see Maybe we could expand unit rules (or "injections", see
https://homepages.cwi.nl/~daybuild/daily-books/syntax/2-sdf/sdf.html), i.e., https://homepages.cwi.nl/~daybuild/daily-books/syntax/2-sdf/sdf.html), i.e.,
transform transform
@@ -95,10 +75,12 @@ Practice' is impossible to find, but according to 'Parsing Techniques: a
Practical Guide', it includes information about this issue. Does anybody Practical Guide', it includes information about this issue. Does anybody
have it? have it?
** Injection rules ** clean up (Akim Demaille)
See above. Do not work on these items now, as I (Akim) have branches with a lot of
changes in this area (hitting several files), and no desire to have to fix
conflicts. Addressing these items will happen after my branches have been
merged.
** clean up
*** lalr.c *** lalr.c
Introduce a goto struct, and use it in place of from_state/to_state. Introduce a goto struct, and use it in place of from_state/to_state.
Rename states1 as path, length as pathlen. Rename states1 as path, length as pathlen.
@@ -119,7 +101,20 @@ introduce lr(0) and lalr, just the way we have ielr categories. The
"set" can still be used for summariring the important sets. That would make "set" can still be used for summariring the important sets. That would make
tests easy to maintain. tests easy to maintain.
*** complain.*
Rename these guys as "diagnostics.*" (or "diagnose.*"), since that's the
name they have in gcc, clang, etc. Likewise for the complain_* series of
functions.
*** ritem
states/nstates, rules/nrules, ..., ritem/nritems
Fix the latter.
* Modernization
Fix data/skeletons/yacc.c so that it defines YYPTRDIFF_T properly for modern
and older C++ compilers. Currently the code defaults to defining it to
'long' for non-GCC compilers, but it should use the proper C++ magic to
define it to the same type as the C ptrdiff_t type.
* Completion * Completion
Several features are not available in all the backends. Several features are not available in all the backends.
@@ -139,8 +134,88 @@ $ ./tests/testsuite -l | grep errors | sed q
38: input.at:1730 errors 38: input.at:1730 errors
* Short term * Short term
** Stop indentation in diagnostics
Before Bison 2.7, we printed "flatly" the dependencies in long diagnostics:
input.y:2.7-12: %type redeclaration for exp
input.y:1.7-12: previous declaration
In Bison 2.7, we indented them
input.y:2.7-12: error: %type redeclaration for exp
input.y:1.7-12: previous declaration
Later we quoted the source in the diagnostics, and today we have:
/tmp/foo.y:1.12-14: warning: symbol FOO redeclared [-Wother]
1 | %token FOO FOO
| ^~~
/tmp/foo.y:1.8-10: previous declaration
1 | %token FOO FOO
| ^~~
The indentation is no longer helping. We should probably get rid of it, or
maybe keep it only when -fno-caret. GCC displays this as a "note":
$ g++-mp-9 -Wall /tmp/foo.c -c
/tmp/foo.c:1:10: error: redefinition of 'int foo'
1 | int foo, foo;
| ^~~
/tmp/foo.c:1:5: note: 'int foo' previously declared here
1 | int foo, foo;
| ^~~
Likewise for Clang, contrary to what I believed (because "note:" is written
in black, so it doesn't show in my terminal :-)
$ clang++-mp-8.0 -Wall /tmp/foo.c -c
clang: warning: treating 'c' input as 'c++' when in C++ mode, this behavior is deprecated [-Wdeprecated]
/tmp/foo.c:1:10: error: redefinition of 'foo'
int foo, foo;
^
/tmp/foo.c:1:5: note: previous definition is here
int foo, foo;
^
1 error generated.
See also the item "Complaint submessage indentation" below.
** Better design for diagnostics
The current implementation of diagnostics is adhoc, it grew organically. It
works as a series of calls to several functions, with dependency of the
latter calls on the former. For instance:
complain (&sym->location,
sym->content->status == needed ? complaint : Wother,
_("symbol %s is used, but is not defined as a token"
" and has no rules; did you mean %s?"),
quote_n (0, sym->tag),
quote_n (1, best->tag));
if (feature_flag & feature_caret)
location_caret_suggestion (sym->location, best->tag, stderr);
We should rewrite this in a more FP way:
1. build a rich structure that denotes the (complete) diagnostic.
"Complete" in the sense that it also contains the suggestions, the list
of possible matches, etc.
2. send this to the pretty-printing routine. The diagnostic structure
should be sufficient so that we can generate all the 'format' of
diagnostics, including the fixits.
If properly done, this diagnostic module can be detached from Bison and be
put in gnulib. It could be used, for instance, for errors caught by
xgettext.
There's certainly already something alike in GCC. At least that's the
impression I get from reading the "-fdiagnostics-format=FORMAT" part of this
page:
https://gcc.gnu.org/onlinedocs/gcc/Diagnostic-Message-Formatting-Options.html
** consistency ** consistency
token vs terminal token vs terminal, variable vs non terminal.
** C++ ** C++
Move to int everywhere instead of unsigned? stack_size, etc. The parser Move to int everywhere instead of unsigned? stack_size, etc. The parser
@@ -148,11 +223,10 @@ itself uses int (for yylen for instance), yet stack is based on size_t.
Maybe locations should also move to ints. Maybe locations should also move to ints.
** C Paul Eggert already covered most of this. But before publishing these
Introduce state_type rather than spreading yytype_int16 everywhere? changes, we need to ask our C++ users if they agree with that change, or if
we need some migration path. Could be a %define variable, or simply
** glr.c %require "3.5".
yyspaceLeft should probably be a pointer diff.
** 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
@@ -173,9 +247,6 @@ Little effort seems to have been given to factoring these files and their
rint{,-xml} counterpart. We would very much like to re-use the pretty format rint{,-xml} counterpart. We would very much like to re-use the pretty format
of states from .output for the graphs, etc. 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? Since graphviz dies on medium-to-big grammars, maybe consider an other tool?
** push-parser ** push-parser
@@ -233,11 +304,13 @@ since it is no longer bound to a particular parser, it's just a
(standalone symbol). (standalone symbol).
* Various * Various
** Rewrite glr.cc in C++ ** Rewrite glr.cc in C++ (Valentin Tolmer)
As a matter of fact, it would be very interesting to see how much we can As a matter of fact, it would be very interesting to see how much we can
share between lalr1.cc and glr.cc. Most of the skeletons should be common. share between lalr1.cc and glr.cc. Most of the skeletons should be common.
It would be a very nice source of inspiration for the other languages. It would be a very nice source of inspiration for the other languages.
Valentin Tolmer is working on this.
** YYERRCODE ** YYERRCODE
Defined to 256, but not used, not documented. Probably the token Defined to 256, but not used, not documented. Probably the token
number for the error token, which POSIX wants to be 256, but which number for the error token, which POSIX wants to be 256, but which
@@ -307,10 +380,21 @@ other improvements and also made it faster (probably because memory
management is performed once instead of three times). I suggest that management is performed once instead of three times). I suggest that
we do the same in yacc.c. we do the same in yacc.c.
(Some time later): it's also very nice to have three stacks: it's more dense
as we don't lose bits to padding. For instance the typical stack for states
will use 8 bits, while it is likely to consume 32 bits in a struct.
We need trustworthy benchmarks for Bison, for all our backends. Akim has a
few things scattered around; we need to put them in the repo, and make them
more useful.
** yysyntax_error ** yysyntax_error
The code bw glr.c and yacc.c is really alike, we can certainly factor The code bw glr.c and yacc.c is really alike, we can certainly factor
some parts. some parts.
This should be worked on when we also address the expected improvements for
error generation (e.g., i18n).
* Report * Report
@@ -350,7 +434,26 @@ LORIA, INRIA Nancy - Grand Est, Nancy, France
* Extensions * Extensions
** Multiple start symbols ** Multiple start symbols
Would be very useful when parsing closely related languages. Would be very useful when parsing closely related languages. The idea is to
declare several start symbols, for instance
%start stmt expr
%%
stmt: ...
expr: ...
and to generate parse(), parse_stmt() and parse_expr(). Technically, the
above grammar would be transformed into
%start yy_start
%token YY_START_STMT YY_START_EXPR
%%
yy_start: YY_START_STMT stmt | YY_START_EXPR expr
so that there are no new conflicts in the grammar (as would undoubtedly
happen with yy_start: stmt | expr). Then adjust the skeletons so that this
initial token (YY_START_STMT, YY_START_EXPR) be shifted first in the
corresponding parse function.
** Better error messages ** Better error messages
The users are not provided with enough tools to forge their error messages. The users are not provided with enough tools to forge their error messages.
@@ -368,6 +471,12 @@ should make this reasonably easy to implement.
Bruce Mardle <[email protected]> Bruce Mardle <[email protected]>
https://lists.gnu.org/archive/html/bison-patches/2015-09/msg00000.html https://lists.gnu.org/archive/html/bison-patches/2015-09/msg00000.html
However, there are many other things to do before having such a feature,
because I don't want a % equivalent to #include (which we all learned to
hate). I want something that builds "modules" of grammars, and assembles
them together, paying attention to keep separate bits separated, in pseudo
name spaces.
** Push parsers ** Push parsers
There is demand for push parsers in Java and C++. And GLR I guess. There is demand for push parsers in Java and C++. And GLR I guess.
@@ -394,6 +503,10 @@ must be in the scanner: we must not parse what is in a switched off
part of %if. Akim Demaille thinks it should be in the parser, so as part of %if. Akim Demaille thinks it should be in the parser, so as
to avoid falling into another CPP mistake. to avoid falling into another CPP mistake.
(Later): I'm sure there's actually good case for this. People who need that
feature can use m4/cpp on top of Bison. I don't think it is worth the
trouble in Bison itself.
** XML Output ** XML Output
There are couple of available extensions of Bison targeting some XML There are couple of available extensions of Bison targeting some XML
output. Some day we should consider including them. One issue is output. Some day we should consider including them. One issue is
@@ -413,6 +526,9 @@ XML output for GNU Bison
https://lists.gnu.org/archive/html/bug-bison/2016-06/msg00000.html https://lists.gnu.org/archive/html/bug-bison/2016-06/msg00000.html
http://www.cs.cornell.edu/andru/papers/cupex/ http://www.cs.cornell.edu/andru/papers/cupex/
Andrew Myers and Vincent Imbimbo are working on this item, see
https://github.com/akimd/bison/issues/12
* Coding system independence * Coding system independence
Paul notes: Paul notes:
@@ -430,7 +546,7 @@ Paul notes:
tokens, either via escapes (e.g., "x\0y") or via a NUL byte in tokens, either via escapes (e.g., "x\0y") or via a NUL byte in
the source code. This should get fixed. the source code. This should get fixed.
* Broken options ? * Broken options?
** %token-table ** %token-table
** Skeleton strategy ** Skeleton strategy
Must we keep %token-table? Must we keep %token-table?
@@ -442,6 +558,7 @@ It is unfortunate that there is a total order for precedence. It
makes it impossible to have modular precedence information. We should makes it impossible to have modular precedence information. We should
move to partial orders (sounds like series/parallel orders to me). move to partial orders (sounds like series/parallel orders to me).
This is a prerequisite for modules.
* $undefined * $undefined
From Hans: From Hans:
+1 -1
View File
@@ -166,7 +166,7 @@ bootstrap_epilogue() { :; }
# specified directory. Fill in the first %s with the destination # specified directory. Fill in the first %s with the destination
# directory and the second with the domain name. # directory and the second with the domain name.
po_download_command_format=\ po_download_command_format=\
"wget --mirror --level=1 -nd -q -A.po -P '%s' \ "wget --mirror --level=1 -nd -nv -A.po -P '%s' \
https://translationproject.org/latest/%s/" https://translationproject.org/latest/%s/"
# Prefer a non-empty tarname (4th argument of AC_INIT if given), else # Prefer a non-empty tarname (4th argument of AC_INIT if given), else
+13 -3
View File
@@ -22,15 +22,16 @@ gnulib_modules='
calloc-posix close closeout config-h c-strcase calloc-posix close closeout config-h c-strcase
configmake configmake
dirname dirname
error extensions fdl fopen-safer error extensions
fdl fopen-safer fstrcmp
getopt-gnu getopt-gnu
gettext-h git-version-gen gitlog-to-changelog gettext-h git-version-gen gitlog-to-changelog
gpl-3.0 inttypes isnan javacomp-script gpl-3.0 intprops inttypes isnan javacomp-script
javaexec-script javaexec-script
ldexpl ldexpl
libtextstyle-optional libtextstyle-optional
malloc-gnu malloc-gnu
mbswidth mbfile mbswidth
non-recursive-gnulib-prefix-hack non-recursive-gnulib-prefix-hack
obstack obstack
obstack-printf obstack-printf
@@ -45,6 +46,8 @@ gnulib_modules='
unistd unistd-safer unlink unlocked-io unistd unistd-safer unlink unlocked-io
update-copyright unsetenv verify update-copyright unsetenv verify
warnings warnings
winsz-ioctl
winsz-termios
xalloc xalloc
xalloc-die xalloc-die
xconcat-filename xconcat-filename
@@ -87,6 +90,13 @@ bootstrap_epilogue()
touch src/parse-gram.[ch] touch src/parse-gram.[ch]
perl -pi -e "s/\@PACKAGE\@/$package/g" README-release perl -pi -e "s/\@PACKAGE\@/$package/g" README-release
# Bison currently uses Gettext 0.19, but the gnulib-po module
# imports files from more recent versions of Gettext that are not
# yet available widely enough (e.g., not in bionic, used by the CI).
# Work around this. Don't use autopoint, which sends some other
# files in the past.
cp po/Makefile.in.in gnulib-po
} }
# Keep our bootstrap script in sync with gnulib's. If we ever need to # Keep our bootstrap script in sync with gnulib's. If we ever need to
+12 -10
View File
@@ -12,7 +12,7 @@ while (<STDIN>)
{ {
if (/^\s* # Initial spaces. if (/^\s* # Initial spaces.
(?:(-\w),\s+)? # $1: $short: Possible short option. (?:(-\w),\s+)? # $1: $short: Possible short option.
(--[-\w]+) # $2: $long: Long option. (--[-\w]+) # $2: $long: Mandatory long option.
(\[?) # $3: $opt: '[' iff the argument is optional. (\[?) # $3: $opt: '[' iff the argument is optional.
(?:=(\S+))? # $4: $arg: Possible argument name. (?:=(\S+))? # $4: $arg: Possible argument name.
\s # Spaces. \s # Spaces.
@@ -32,7 +32,6 @@ while (<STDIN>)
# if $opt, $arg contains the closing ]. # if $opt, $arg contains the closing ].
substr ($arg, -1) = '' substr ($arg, -1) = ''
if $opt eq '['; if $opt eq '[';
$arg =~ s/^=//;
$arg = lc ($arg); $arg = lc ($arg);
my $dir_arg = $arg; my $dir_arg = $arg;
# If the argument is complete (e.g., for --define[=NAME[=VALUE]]), # If the argument is complete (e.g., for --define[=NAME[=VALUE]]),
@@ -72,12 +71,15 @@ while (<STDIN>)
my $sep = ''; my $sep = '';
foreach my $long (sort keys %option) foreach my $long (sort keys %option)
{ {
# Avoid trailing spaces. # Couldn't find a means to escape @ in the format (for @item, @tab), so
print $sep; # pass it as a literal to print.
$sep = "\n"; format STDOUT =
print '@item @option{', $long, "}\n\@tab"; @item @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @tab @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @tab @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
print ' @option{', $option{$long}, '}' if $option{$long}; {
print "\n\@tab"; '@', '@option{' . $long . '}',
print ' @code{', $directive{$long}, '}' if $directive{$long}; '@', $option{$long} ? ('@option{' . $option{$long} . '}') : '',
print "\n"; '@', $directive{$long} ? ('@code{' . $directive{$long} . '}') : ''
}
.
write;
} }
+13 -12
View File
@@ -1,7 +1,7 @@
#! /usr/bin/env python #! /usr/bin/env python
# usage: # usage:
# update-test _build/8d/tests/testsuite.dir/*.testsuite.log # update-test _build/8d/tests/testsuite.dir/*/testsuite.log
import argparse import argparse
import os import os
@@ -11,8 +11,8 @@ import re
def getargs(): def getargs():
p = argparse.ArgumentParser(description='Update test cases.') p = argparse.ArgumentParser(description='Update test cases.')
opt = p.add_argument opt = p.add_argument
opt('tests', metavar='test', nargs='+', type=str, default=None, opt('logs', metavar='log', nargs='+', type=str, default=None,
help='test files to update') help='log files to process')
opt('-v', '--verbose', action='store_true', opt('-v', '--verbose', action='store_true',
help='Be verbose') help='Be verbose')
return p.parse_args() return p.parse_args()
@@ -21,14 +21,14 @@ args = getargs()
subst = dict() subst = dict()
def log(*args_): def trace(*args_):
if args.verbose: if args.verbose:
print(*args_) print(*args_)
def contents(file): def contents(file):
'''The contents of a file.''' '''The contents of a file.'''
log(file) trace(file)
f = open(file) f = open(file)
return f.read() return f.read()
@@ -60,9 +60,9 @@ def diff_to_re(match):
def update(at_file, logfile): def update(at_file, logfile):
test = contents(at_file) test = contents(at_file)
if os.path.isfile(logfile): if os.path.isfile(logfile):
log("LOG: ", logfile) trace("LOG: ", logfile)
l = contents(logfile) l = contents(logfile)
log("LOG: ", l) trace("LOG: ", l)
global subst global subst
subst = {} subst = {}
re.sub(r'(?:^@@.*\n)((?:^[-+ ].*\n)+)', re.sub(r'(?:^@@.*\n)((?:^[-+ ].*\n)+)',
@@ -71,7 +71,7 @@ def update(at_file, logfile):
if subst: if subst:
# Turn "subst{frm} -> to" into a large RE. # Turn "subst{frm} -> to" into a large RE.
frm = '|'.join([re.escape(x) for x in subst]) frm = '|'.join([re.escape(x) for x in subst])
log("FROM:", frm) trace("FROM:", frm)
test = re.sub("(" + frm + ")", test = re.sub("(" + frm + ")",
lambda m: subst[m.group(1)], lambda m: subst[m.group(1)],
test, flags=re.MULTILINE) test, flags=re.MULTILINE)
@@ -81,13 +81,14 @@ def update(at_file, logfile):
def process(logfile): def process(logfile):
log = contents(logfile) log = contents(logfile)
# Look for the file to update. # Look for the file to update.
m = re.search(r'^\d+\. (\w+\.at):\d+: ', log, re.MULTILINE) m = re.search(r'^\d+\. ([-\w]+\.at):\d+: ', log, re.MULTILINE)
if not m: if not m:
trace("no diff found:", logfile)
return return
at_file = 'tests/' + m.group(1) at_file = 'tests/' + m.group(1)
print(at_file) print(at_file)
update(at_file, logfile) update(at_file, logfile)
for t in args.tests: for logfile in args.logs:
log("FILE:", t) trace("FILE:", logfile)
process(t) process(logfile)
+3
View File
@@ -26,6 +26,9 @@ regen: _version
manual_title = The Yacc-compatible Parser Generator manual_title = The Yacc-compatible Parser Generator
gendocs_options_ = -I $(abs_top_srcdir)/doc -I $(abs_top_builddir)/doc gendocs_options_ = -I $(abs_top_srcdir)/doc -I $(abs_top_builddir)/doc
# By default, propagate -j from make to Bison's test suite.
TESTSUITEFLAGS = $(filter -j%,$(MAKEFLAGS))
# It's useful to run maintainer-check* targets during development, but we # It's useful to run maintainer-check* targets during development, but we
# don't want to wait on a recompile because of an update to $(VERSION). Thus, # don't want to wait on a recompile because of an update to $(VERSION). Thus,
# override the _is-dist-target from GNUmakefile so that maintainer-check* # override the _is-dist-target from GNUmakefile so that maintainer-check*
+12 -8
View File
@@ -36,6 +36,9 @@ AC_CONFIG_MACRO_DIR([m4])
# We use Automake 1.14's %D% and %C%. # We use Automake 1.14's %D% and %C%.
# #
# When we move to Automake 1.16, simplify examples/c/reccalc/local.mk.
# Our CI runs on Xenial, which has only Automake 1.15.
#
# We want gnits strictness only when rolling a stable release. For # We want gnits strictness only when rolling a stable release. For
# release candidates, we use version strings like 2.4.3_rc1, but gnits # release candidates, we use version strings like 2.4.3_rc1, but gnits
# doesn't like that, so we let the underscore disable gnits. Between # doesn't like that, so we let the underscore disable gnits. Between
@@ -94,9 +97,13 @@ AC_ARG_ENABLE([gcc-warnings],
[enable_gcc_warnings=no]) [enable_gcc_warnings=no])
AM_CONDITIONAL([ENABLE_GCC_WARNINGS], [test "$enable_gcc_warnings" = yes]) AM_CONDITIONAL([ENABLE_GCC_WARNINGS], [test "$enable_gcc_warnings" = yes])
if test "$enable_gcc_warnings" = yes; then if test "$enable_gcc_warnings" = yes; then
warn_common='-Wall -Wextra -Wno-sign-compare -Wcast-align # -Wno-tautological-constant-out-of-range-compare for Clang 3.3 and
# 3.4 on GNU/Linux that choke on intprops.h's INT_MULTIPLY_WRAPV,
# etc.
warn_common='-Wall -Wextra -Wcast-align
-fparse-all-comments -Wdocumentation -fparse-all-comments -Wdocumentation
-Wformat -Wimplicit-fallthrough -Wnull-dereference -Wformat -Wimplicit-fallthrough -Wnull-dereference
-Wno-sign-compare -Wno-tautological-constant-out-of-range-compare
-Wpointer-arith -Wshadow -Wpointer-arith -Wshadow
-Wwrite-strings' -Wwrite-strings'
warn_c='-Wbad-function-cast -Wstrict-prototypes' warn_c='-Wbad-function-cast -Wstrict-prototypes'
@@ -112,6 +119,7 @@ if test "$enable_gcc_warnings" = yes; then
# details for lalr1.cc. # details for lalr1.cc.
warn_tests='-Wundef -pedantic -Wconversion warn_tests='-Wundef -pedantic -Wconversion
-Wdeprecated -Wsign-compare -Wsign-conversion -Wdeprecated -Wsign-compare -Wsign-conversion
-Wtautological-constant-out-of-range-compare
-fno-color-diagnostics -fno-color-diagnostics
-Wno-keyword-macro' -Wno-keyword-macro'
@@ -192,7 +200,7 @@ BISON_CXX_COMPILER_POSIXLY_CORRECT
# D. # D.
AC_CHECK_PROGS([DC], [dmd]) AC_CHECK_PROGS([DC], [dmd])
AC_CHECK_PROGS([DCFLAGS], []) AC_CHECK_PROGS([DCFLAGS], [-g])
AM_CONDITIONAL([ENABLE_D], [test x"$DC" != x]) AM_CONDITIONAL([ENABLE_D], [test x"$DC" != x])
# Java. # Java.
@@ -211,10 +219,10 @@ AC_CONFIG_FILES([src/yacc], [chmod +x src/yacc])
# Checks for programs. # Checks for programs.
AM_MISSING_PROG([DOT], [dot]) AM_MISSING_PROG([DOT], [dot])
AC_PROG_LEX AC_PROG_LEX
$LEX_IS_FLEX || test "X$LEX" = X: || { if ! "$LEX_IS_FLEX" || test "X$LEX" = X:; then
AC_MSG_WARN([bypassing lex because flex is required]) AC_MSG_WARN([bypassing lex because flex is required])
LEX=: LEX=:
} fi
AM_CONDITIONAL([FLEX_WORKS], [$LEX_IS_FLEX]) AM_CONDITIONAL([FLEX_WORKS], [$LEX_IS_FLEX])
AM_CONDITIONAL([FLEX_CXX_WORKS], AM_CONDITIONAL([FLEX_CXX_WORKS],
[$LEX_IS_FLEX && test $bison_cv_cxx_works = yes]) [$LEX_IS_FLEX && test $bison_cv_cxx_works = yes])
@@ -225,9 +233,6 @@ AC_DEFINE_UNQUOTED([M4], ["$M4"], [Define to the GNU M4 executable name.])
AC_DEFINE_UNQUOTED([M4_GNU_OPTION], ["$M4_GNU"], [Define to "-g" if GNU M4 AC_DEFINE_UNQUOTED([M4_GNU_OPTION], ["$M4_GNU"], [Define to "-g" if GNU M4
supports -g, otherwise to "".]) supports -g, otherwise to "".])
AC_PATH_PROG([PERL], [perl]) AC_PATH_PROG([PERL], [perl])
if test -z "$PERL"; then
AC_MSG_ERROR([perl not found])
fi
AM_MISSING_PROG([HELP2MAN], [help2man]) AM_MISSING_PROG([HELP2MAN], [help2man])
AC_PATH_PROG([XSLTPROC], [xsltproc]) AC_PATH_PROG([XSLTPROC], [xsltproc])
AC_SUBST([XSLTPROC]) AC_SUBST([XSLTPROC])
@@ -244,7 +249,6 @@ gl_INIT
# Checks for library functions. # Checks for library functions.
AC_CHECK_FUNCS_ONCE([setlocale]) AC_CHECK_FUNCS_ONCE([setlocale])
AM_WITH_DMALLOC
# Gettext. # Gettext.
# We use gnulib, which is only guaranteed to work properly with the # We use gnulib, which is only guaranteed to work properly with the
+7
View File
@@ -17,8 +17,15 @@
/* This is an experimental feature. The class names may change in the /* This is an experimental feature. The class names may change in the
future. */ future. */
/* Diagnostics. */
.warning { color: purple; } .warning { color: purple; }
.error { color: red; } .error { color: red; }
.note { color: cyan; } .note { color: cyan; }
.fixit-insert { color: green; }
/* Semantic values in Bison's own parser traces. */ /* Semantic values in Bison's own parser traces. */
.value { color: green; } .value { color: green; }
/* "Sections" in traces (--trace). */
.trace0 { color: green; }
+3 -2
View File
@@ -449,7 +449,7 @@ m4_define([b4_symbol_action],
[(*yylocationp)])dnl [(*yylocationp)])dnl
_b4_symbol_case([$1])[]dnl _b4_symbol_case([$1])[]dnl
b4_syncline([b4_symbol([$1], [$2_line])], [b4_symbol([$1], [$2_file])])dnl b4_syncline([b4_symbol([$1], [$2_line])], [b4_symbol([$1], [$2_file])])dnl
b4_symbol([$1], [$2]) b4_symbol([$1], [$2])
b4_syncline([@oline@], [@ofile@])dnl b4_syncline([@oline@], [@ofile@])dnl
break; break;
@@ -535,7 +535,7 @@ m4_define([b4_token_format],
[b4_token_visible_if([$2], [b4_token_visible_if([$2],
[m4_quote(m4_format([$1], [m4_quote(m4_format([$1],
[b4_symbol([$2], [id])], [b4_symbol([$2], [id])],
[b4_symbol([$2], [user_number])]))])]) [b4_symbol([$2], b4_api_token_raw_if([[number]], [[user_number]]))]))])])
## ------- ## ## ------- ##
@@ -1002,6 +1002,7 @@ m4_define([b4_percent_code_ifdef],
# b4_parse_trace_if([IF-DEBUG-TRACES-ARE-ENABLED], [IF-NOT]) # b4_parse_trace_if([IF-DEBUG-TRACES-ARE-ENABLED], [IF-NOT])
# b4_token_ctor_if([IF-YYLEX-RETURNS-A-TOKEN], [IF-NOT]) # b4_token_ctor_if([IF-YYLEX-RETURNS-A-TOKEN], [IF-NOT])
# ---------------------------------------------------------- # ----------------------------------------------------------
b4_percent_define_if_define([api.token.raw])
b4_percent_define_if_define([token_ctor], [api.token.constructor]) b4_percent_define_if_define([token_ctor], [api.token.constructor])
b4_percent_define_if_define([locations]) # Whether locations are tracked. b4_percent_define_if_define([locations]) # Whether locations are tracked.
b4_percent_define_if_define([parse.assert]) b4_percent_define_if_define([parse.assert])
+6 -4
View File
@@ -532,7 +532,9 @@ m4_define([b4_yytranslate_define],
]b4_parser_class[::yytranslate_ (]b4_token_ctor_if([token_type], ]b4_parser_class[::yytranslate_ (]b4_token_ctor_if([token_type],
[int])[ t) [int])[ t)
{ {
// YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to ]b4_api_token_raw_if(
[[ return static_cast<yy::parser::token_number_type> (t);]],
[[ // YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to
// TOKEN-NUM as returned by yylex. // TOKEN-NUM as returned by yylex.
static static
const token_number_type const token_number_type
@@ -540,15 +542,15 @@ m4_define([b4_yytranslate_define],
{ {
]b4_translate[ ]b4_translate[
}; };
const unsigned user_token_number_max_ = ]b4_user_token_number_max[; const int user_token_number_max_ = ]b4_user_token_number_max[;
const token_number_type undef_token_ = ]b4_undef_token_number[; const token_number_type undef_token_ = ]b4_undef_token_number[;
if (static_cast<int> (t) <= yyeof_) if (static_cast<int> (t) <= yyeof_)
return yyeof_; return yyeof_;
else if (static_cast<unsigned> (t) <= user_token_number_max_) else if (static_cast<int> (t) <= user_token_number_max_)
return translate_table[t]; return translate_table[t];
else else
return undef_token_; return undef_token_;]])[
} }
]]) ]])
+93 -23
View File
@@ -167,38 +167,110 @@ b4_parse_param_for([Decl], [Formal], [ YYUSE (Formal);
# b4_int_type(MIN, MAX) # b4_int_type(MIN, MAX)
# --------------------- # ---------------------
# Return the smallest int type able to handle numbers ranging from # Return a narrow int type able to handle integers ranging from MIN
# MIN to MAX (included). # to MAX (included) in portable C code. Assume MIN and MAX fall in
# 'int' range.
m4_define([b4_int_type], m4_define([b4_int_type],
[m4_if(b4_ints_in($@, [0], [255]), [1], [unsigned char], [m4_if(b4_ints_in($@, [-127], [127]), [1], [signed char],
b4_ints_in($@, [-128], [127]), [1], [signed char], b4_ints_in($@, [0], [255]), [1], [unsigned char],
b4_ints_in($@, [-32767], [32767]), [1], [short],
b4_ints_in($@, [0], [65535]), [1], [unsigned short], b4_ints_in($@, [0], [65535]), [1], [unsigned short],
b4_ints_in($@, [-32768], [32767]), [1], [short],
m4_eval([0 <= $1]), [1], [unsigned],
[int])]) [int])])
# b4_c99_int_type(MIN, MAX)
# -------------------------
# Like b4_int_type, but for C99.
# b4_c99_int_type_define replaces b4_int_type with this.
m4_define([b4_c99_int_type],
[m4_if(b4_ints_in($@, [-127], [127]), [1], [yytype_int8],
b4_ints_in($@, [0], [255]), [1], [yytype_uint8],
b4_ints_in($@, [-32767], [32767]), [1], [yytype_int16],
b4_ints_in($@, [0], [65535]), [1], [yytype_uint16],
[int])])
# b4_c99_int_type_define
# ----------------------
# Define private types suitable for holding small integers in C99 or later.
m4_define([b4_c99_int_type_define],
[m4_copy_force([b4_c99_int_type], [b4_int_type])dnl
[/* On compilers that do not define __PTRDIFF_MAX__ etc., make sure
<limits.h> and (if available) <stdint.h> are included
so that the code can choose integer types of a good width. */
#ifndef __PTRDIFF_MAX__
# include <limits.h> /* INFRINGES ON USER NAME SPACE */
# if defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__
# include <stdint.h> /* INFRINGES ON USER NAME SPACE */
# define YY_STDINT_H
# endif
#endif
/* Narrow types that promote to a signed type and that can represent a
signed or unsigned integer of at least N bits. In tables they can
save space and decrease cache pressure. Promoting to a signed type
helps avoid bugs in integer arithmetic. */
#ifdef __INT_LEAST8_MAX__
typedef __INT_LEAST8_TYPE__ yytype_int8;
#elif defined YY_STDINT_H
typedef int_least8_t yytype_int8;
#else
typedef signed char yytype_int8;
#endif
#ifdef __INT_LEAST16_MAX__
typedef __INT_LEAST16_TYPE__ yytype_int16;
#elif defined YY_STDINT_H
typedef int_least16_t yytype_int16;
#else
typedef short yytype_int16;
#endif
#if defined __UINT_LEAST8_MAX__ && __UINT_LEAST8_MAX__ <= __INT_MAX__
typedef __UINT_LEAST8_TYPE__ yytype_uint8;
#elif (!defined __UINT_LEAST8_MAX__ && defined YY_STDINT_H \
&& UINT_LEAST8_MAX <= INT_MAX)
typedef uint_least8_t yytype_uint8;
#elif !defined __UINT_LEAST8_MAX__ && UCHAR_MAX <= INT_MAX
typedef unsigned char yytype_uint8;
#else
typedef short yytype_uint8;
#endif
#if defined __UINT_LEAST16_MAX__ && __UINT_LEAST16_MAX__ <= __INT_MAX__
typedef __UINT_LEAST16_TYPE__ yytype_uint16;
#elif (!defined __UINT_LEAST16_MAX__ && defined YY_STDINT_H \
&& UINT_LEAST16_MAX <= INT_MAX)
typedef uint_least16_t yytype_uint16;
#elif !defined __UINT_LEAST16_MAX__ && USHRT_MAX <= INT_MAX
typedef unsigned short yytype_uint16;
#else
typedef int yytype_uint16;
#endif]])
# b4_int_type_for(NAME) # b4_int_type_for(NAME)
# --------------------- # ---------------------
# Return the smallest int type able to handle numbers ranging from # Return a narrow 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)])
# b4_table_value_equals(TABLE, VALUE, LITERAL) # b4_table_value_equals(TABLE, VALUE, LITERAL, SYMBOL)
# -------------------------------------------- # ----------------------------------------------------
# Without inducing a comparison warning from the compiler, check if the # Without inducing a comparison warning from the compiler, check if the
# literal value LITERAL equals VALUE from table TABLE, which must have # literal value LITERAL equals VALUE from table TABLE, which must have
# TABLE_min and TABLE_max defined. # TABLE_min and TABLE_max defined. SYMBOL denotes
m4_define([b4_table_value_equals], m4_define([b4_table_value_equals],
[m4_if(m4_eval($3 < m4_indir([b4_]$1[_min]) [m4_if(m4_eval($3 < m4_indir([b4_]$1[_min])
|| m4_indir([b4_]$1[_max]) < $3), [1], || m4_indir([b4_]$1[_max]) < $3), [1],
[[0]], [[0]],
[(!!(($2) == ($3)))])]) [(($2) == $4)])])
## ----------------- ## ## ----------------- ##
@@ -210,22 +282,20 @@ m4_define([b4_table_value_equals],
# Provide portable compiler "attributes". If "noreturn" is passed, define # Provide portable compiler "attributes". If "noreturn" is passed, define
# _Noreturn. # _Noreturn.
m4_define([b4_attribute_define], m4_define([b4_attribute_define],
[[#ifndef YY_ATTRIBUTE [[#ifndef YY_ATTRIBUTE_PURE
# if (defined __GNUC__ \ # if defined __GNUC__ && 2 < __GNUC__ + (96 <= __GNUC_MINOR__)
&& (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \ # define YY_ATTRIBUTE_PURE __attribute__ ((__pure__))
|| defined __SUNPRO_C && 0x5110 <= __SUNPRO_C
# define YY_ATTRIBUTE(Spec) __attribute__(Spec)
# else # else
# define YY_ATTRIBUTE(Spec) /* empty */ # define YY_ATTRIBUTE_PURE
# endif # endif
#endif #endif
#ifndef YY_ATTRIBUTE_PURE
# define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__))
#endif
#ifndef YY_ATTRIBUTE_UNUSED #ifndef YY_ATTRIBUTE_UNUSED
# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__)) # if defined __GNUC__ && 2 < __GNUC__ + (7 <= __GNUC_MINOR__)
# define YY_ATTRIBUTE_UNUSED __attribute__ ((__unused__))
# else
# define YY_ATTRIBUTE_UNUSED
# endif
#endif #endif
]m4_bmatch([$1], [\bnoreturn\b], [[/* The _Noreturn keyword of C11. */ ]m4_bmatch([$1], [\bnoreturn\b], [[/* The _Noreturn keyword of C11. */
+5 -6
View File
@@ -38,6 +38,11 @@ m4_define([b4_comment],
[_b4_comment([$1], [$2/* ], [$2 ], [ */])]) [_b4_comment([$1], [$2/* ], [$2 ], [ */])])
# b4_sync_start(LINE, FILE)
# -------------------------
m4_define([b4_sync_start], [[#]line $1 $2])
# b4_list2(LIST1, LIST2) # b4_list2(LIST1, LIST2)
# ---------------------- # ----------------------
# Join two lists with a comma if necessary. # Join two lists with a comma if necessary.
@@ -95,12 +100,6 @@ m4_define([b4_location_type_if],
[b4_percent_define_ifdef([[location_type]], [$1], [$2])]) [b4_percent_define_ifdef([[location_type]], [$1], [$2])])
# b4_locations_if(TRUE, FALSE)
# ----------------------------
m4_define([b4_locations_if],
[m4_if(b4_locations_flag, 1, [$1], [$2])])
# b4_identification # b4_identification
# ----------------- # -----------------
m4_define([b4_identification], m4_define([b4_identification],
+134 -130
View File
@@ -259,10 +259,14 @@ static YYLTYPE yyloc_default][]b4_yyloc_default;])[
]b4_user_post_prologue[ ]b4_user_post_prologue[
]b4_percent_code_get[]dnl ]b4_percent_code_get[]dnl
[#include <stdio.h> [#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
]b4_c99_int_type_define[
#ifndef YY_ #ifndef YY_
# if defined YYENABLE_NLS && YYENABLE_NLS # if defined YYENABLE_NLS && YYENABLE_NLS
# if ENABLE_NLS # if ENABLE_NLS
@@ -285,7 +289,7 @@ static YYLTYPE yyloc_default][]b4_yyloc_default;])[
# define YYREALLOC realloc # define YYREALLOC realloc
#endif #endif
#define YYSIZEMAX ((size_t) -1) #define YYSIZEMAX (PTRDIFF_MAX < SIZE_MAX ? PTRDIFF_MAX : (ptrdiff_t) SIZE_MAX)
#ifdef __cplusplus #ifdef __cplusplus
typedef bool yybool; typedef bool yybool;
@@ -293,7 +297,7 @@ static YYLTYPE yyloc_default][]b4_yyloc_default;])[
# define yyfalse false # define yyfalse false
#else #else
/* When we move to stdbool, get rid of the various casts to yybool. */ /* When we move to stdbool, get rid of the various casts to yybool. */
typedef unsigned char yybool; typedef signed char yybool;
# define yytrue 1 # define yytrue 1
# define yyfalse 0 # define yyfalse 0
#endif #endif
@@ -346,15 +350,17 @@ static YYLTYPE yyloc_default][]b4_yyloc_default;])[
/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM /* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM
as returned by yylex, with out-of-bounds checking. */ as returned by yylex, with out-of-bounds checking. */
#define YYTRANSLATE(YYX) \ ]b4_api_token_raw_if(dnl
((unsigned) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) [[#define YYTRANSLATE(YYX) (YYX)]],
[[#define YYTRANSLATE(YYX) \
(0 <= (YYX) && (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM /* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
as returned by yylex. */ as returned by yylex. */
static const ]b4_int_type_for([b4_translate])[ yytranslate[] = static const ]b4_int_type_for([b4_translate])[ yytranslate[] =
{ {
]b4_translate[ ]b4_translate[
}; };]])[
#if ]b4_api_PREFIX[DEBUG #if ]b4_api_PREFIX[DEBUG
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ /* YYRLINE[YYN] -- source line where rule number YYN was defined. */
@@ -373,8 +379,8 @@ static const char *const yytname[] =
}; };
#endif #endif
#define YYPACT_NINF ]b4_pact_ninf[ #define YYPACT_NINF (]b4_pact_ninf[)
#define YYTABLE_NINF ]b4_table_ninf[ #define YYTABLE_NINF (]b4_table_ninf[)
]b4_parser_tables_define[ ]b4_parser_tables_define[
@@ -488,7 +494,7 @@ typedef enum { yyok, yyaccept, yyabort, yyerr } YYRESULTTAG;
int yydebug; int yydebug;
struct yyGLRStack; struct yyGLRStack;
static void yypstack (struct yyGLRStack* yystackp, size_t yyk) static void yypstack (struct yyGLRStack* yystackp, ptrdiff_t yyk)
YY_ATTRIBUTE_UNUSED; YY_ATTRIBUTE_UNUSED;
static void yypdumpstack (struct yyGLRStack* yystackp) static void yypdumpstack (struct yyGLRStack* yystackp)
YY_ATTRIBUTE_UNUSED; YY_ATTRIBUTE_UNUSED;
@@ -572,12 +578,12 @@ yystpcpy (char *yydest, const char *yysrc)
backslash-backslash). YYSTR is taken from yytname. If YYRES is backslash-backslash). YYSTR is taken from yytname. If YYRES is
null, do not copy; instead, return the length of what the result null, do not copy; instead, return the length of what the result
would have been. */ would have been. */
static size_t static ptrdiff_t
yytnamerr (char *yyres, const char *yystr) yytnamerr (char *yyres, const char *yystr)
{ {
if (*yystr == '"') if (*yystr == '"')
{ {
size_t yyn = 0; ptrdiff_t yyn = 0;
char const *yyp = yystr; char const *yyp = yystr;
for (;;) for (;;)
@@ -608,25 +614,25 @@ yytnamerr (char *yyres, const char *yystr)
do_not_strip_quotes: ; do_not_strip_quotes: ;
} }
if (! yyres) if (yyres)
return strlen (yystr); return yystpcpy (yyres, yystr) - yyres;
else
return (size_t) (yystpcpy (yyres, yystr) - yyres); return (ptrdiff_t) strlen (yystr);
} }
# endif # endif
#endif /* !YYERROR_VERBOSE */ #endif /* !YYERROR_VERBOSE */
/** State numbers, as in LALR(1) machine */ /** State numbers. */
typedef int yyStateNum; typedef int yyStateNum;
/** Rule numbers, as in LALR(1) machine */ /** Rule numbers. */
typedef int yyRuleNum; typedef int yyRuleNum;
/** Grammar symbol */ /** Grammar symbol. */
typedef int yySymbol; typedef int yySymbol;
/** Item references, as in LALR(1) machine */ /** Item references. */
typedef short yyItemNum; typedef short yyItemNum;
typedef struct yyGLRState yyGLRState; typedef struct yyGLRState yyGLRState;
@@ -646,7 +652,7 @@ struct yyGLRState {
/** Preceding state in this stack */ /** Preceding state in this stack */
yyGLRState* yypred; yyGLRState* yypred;
/** Source position of the last token produced by my symbol */ /** Source position of the last token produced by my symbol */
size_t yyposn; ptrdiff_t yyposn;
union { union {
/** First in a chain of alternative reductions producing the /** First in a chain of alternative reductions producing the
* nonterminal corresponding to this state, threaded through * nonterminal corresponding to this state, threaded through
@@ -666,7 +672,8 @@ struct yyGLRStateSet {
* operation, yylookaheadNeeds[0] is not maintained since it would merely * operation, yylookaheadNeeds[0] is not maintained since it would merely
* duplicate yychar != YYEMPTY. */ * duplicate yychar != YYEMPTY. */
yybool* yylookaheadNeeds; yybool* yylookaheadNeeds;
size_t yysize, yycapacity; ptrdiff_t yysize;
ptrdiff_t yycapacity;
}; };
struct yySemanticOption { struct yySemanticOption {
@@ -706,7 +713,7 @@ struct yyGLRStack {
YYJMP_BUF yyexception_buffer; YYJMP_BUF yyexception_buffer;
yyGLRStackItem* yyitems; yyGLRStackItem* yyitems;
yyGLRStackItem* yynextFree; yyGLRStackItem* yynextFree;
size_t yyspaceLeft; ptrdiff_t yyspaceLeft;
yyGLRState* yysplitPoint; yyGLRState* yysplitPoint;
yyGLRState* yylastDeleted; yyGLRState* yylastDeleted;
yyGLRStateSet yytops; yyGLRStateSet yytops;
@@ -965,8 +972,8 @@ yylhsNonterm (yyRuleNum yyrule)
return yyr1[yyrule]; return yyr1[yyrule];
} }
#define yypact_value_is_default(Yystate) \ #define yypact_value_is_default(Yyn) \
]b4_table_value_equals([[pact]], [[Yystate]], [b4_pact_ninf])[ ]b4_table_value_equals([[pact]], [[Yyn]], [b4_pact_ninf], [YYPACT_NINF])[
/** True iff LR state YYSTATE has only a default reduction (regardless /** True iff LR state YYSTATE has only a default reduction (regardless
* of token). */ * of token). */
@@ -983,8 +990,8 @@ yydefaultAction (yyStateNum yystate)
return yydefact[yystate]; return yydefact[yystate];
} }
#define yytable_value_is_error(Yytable_value) \ #define yytable_value_is_error(Yyn) \
]b4_table_value_equals([[table]], [[Yytable_value]], [b4_table_ninf])[ ]b4_table_value_equals([[table]], [[Yyn]], [b4_table_ninf], [YYTABLE_NINF])[
/** The action to take in YYSTATE on seeing YYTOKEN. /** The action to take in YYSTATE on seeing YYTOKEN.
* Result R means * Result R means
@@ -1064,7 +1071,7 @@ yynewGLRStackItem (yyGLRStack* yystackp, yybool yyisState)
* alternative actions for YYSTATE. Assumes that YYRHS comes from * alternative actions for YYSTATE. Assumes that YYRHS comes from
* stack #YYK of *YYSTACKP. */ * stack #YYK of *YYSTACKP. */
static void static void
yyaddDeferredAction (yyGLRStack* yystackp, size_t yyk, yyGLRState* yystate, yyaddDeferredAction (yyGLRStack* yystackp, ptrdiff_t yyk, yyGLRState* yystate,
yyGLRState* yyrhs, yyRuleNum yyrule) yyGLRState* yyrhs, yyRuleNum yyrule)
{ {
yySemanticOption* yynewOption = yySemanticOption* yynewOption =
@@ -1095,19 +1102,21 @@ yyinitStateSet (yyGLRStateSet* yyset)
yyset->yysize = 1; yyset->yysize = 1;
yyset->yycapacity = 16; yyset->yycapacity = 16;
yyset->yystates yyset->yystates
= (yyGLRState**) YYMALLOC (yyset->yycapacity * sizeof yyset->yystates[0]); = (yyGLRState**) YYMALLOC ((size_t) yyset->yycapacity
* sizeof yyset->yystates[0]);
if (! yyset->yystates) if (! yyset->yystates)
return yyfalse; return yyfalse;
yyset->yystates[0] = YY_NULLPTR; yyset->yystates[0] = YY_NULLPTR;
yyset->yylookaheadNeeds yyset->yylookaheadNeeds
= (yybool*) YYMALLOC (yyset->yycapacity * sizeof yyset->yylookaheadNeeds[0]); = (yybool*) YYMALLOC ((size_t) yyset->yycapacity
* sizeof yyset->yylookaheadNeeds[0]);
if (! yyset->yylookaheadNeeds) if (! yyset->yylookaheadNeeds)
{ {
YYFREE (yyset->yystates); YYFREE (yyset->yystates);
return yyfalse; return yyfalse;
} }
memset (yyset->yylookaheadNeeds, memset (yyset->yylookaheadNeeds,
0, yyset->yycapacity * sizeof yyset->yylookaheadNeeds[0]); 0, (size_t) yyset->yycapacity * sizeof yyset->yylookaheadNeeds[0]);
return yytrue; return yytrue;
} }
@@ -1120,13 +1129,14 @@ static void yyfreeStateSet (yyGLRStateSet* yyset)
/** Initialize *YYSTACKP to a single empty stack, with total maximum /** Initialize *YYSTACKP to a single empty stack, with total maximum
* capacity for all stacks of YYSIZE. */ * capacity for all stacks of YYSIZE. */
static yybool static yybool
yyinitGLRStack (yyGLRStack* yystackp, size_t yysize) yyinitGLRStack (yyGLRStack* yystackp, ptrdiff_t yysize)
{ {
yystackp->yyerrState = 0; yystackp->yyerrState = 0;
yynerrs = 0; yynerrs = 0;
yystackp->yyspaceLeft = yysize; yystackp->yyspaceLeft = yysize;
yystackp->yyitems = yystackp->yyitems =
(yyGLRStackItem*) YYMALLOC (yysize * sizeof yystackp->yynextFree[0]); (yyGLRStackItem*) YYMALLOC ((size_t) yysize
* sizeof yystackp->yynextFree[0]);
if (!yystackp->yyitems) if (!yystackp->yyitems)
return yyfalse; return yyfalse;
yystackp->yynextFree = yystackp->yyitems; yystackp->yynextFree = yystackp->yyitems;
@@ -1150,15 +1160,16 @@ yyexpandGLRStack (yyGLRStack* yystackp)
{ {
yyGLRStackItem* yynewItems; yyGLRStackItem* yynewItems;
yyGLRStackItem* yyp0, *yyp1; yyGLRStackItem* yyp0, *yyp1;
size_t yynewSize; ptrdiff_t yynewSize;
size_t yyn; ptrdiff_t yyn;
size_t yysize = (size_t) (yystackp->yynextFree - yystackp->yyitems); ptrdiff_t yysize = yystackp->yynextFree - yystackp->yyitems;
if (YYMAXDEPTH - YYHEADROOM < yysize) if (YYMAXDEPTH - YYHEADROOM < yysize)
yyMemoryExhausted (yystackp); yyMemoryExhausted (yystackp);
yynewSize = 2*yysize; yynewSize = 2*yysize;
if (YYMAXDEPTH < yynewSize) if (YYMAXDEPTH < yynewSize)
yynewSize = YYMAXDEPTH; yynewSize = YYMAXDEPTH;
yynewItems = (yyGLRStackItem*) YYMALLOC (yynewSize * sizeof yynewItems[0]); yynewItems = (yyGLRStackItem*) YYMALLOC ((size_t) yynewSize
* sizeof yynewItems[0]);
if (! yynewItems) if (! yynewItems)
yyMemoryExhausted (yystackp); yyMemoryExhausted (yystackp);
for (yyp0 = yystackp->yyitems, yyp1 = yynewItems, yyn = yysize; for (yyp0 = yystackp->yyitems, yyp1 = yynewItems, yyn = yysize;
@@ -1222,7 +1233,7 @@ yyupdateSplit (yyGLRStack* yystackp, yyGLRState* yys)
/** Invalidate stack #YYK in *YYSTACKP. */ /** Invalidate stack #YYK in *YYSTACKP. */
static inline void static inline void
yymarkStackDeleted (yyGLRStack* yystackp, size_t yyk) yymarkStackDeleted (yyGLRStack* yystackp, ptrdiff_t yyk)
{ {
if (yystackp->yytops.yystates[yyk] != YY_NULLPTR) if (yystackp->yytops.yystates[yyk] != YY_NULLPTR)
yystackp->yylastDeleted = yystackp->yytops.yystates[yyk]; yystackp->yylastDeleted = yystackp->yytops.yystates[yyk];
@@ -1246,7 +1257,7 @@ yyundeleteLastStack (yyGLRStack* yystackp)
static inline void static inline void
yyremoveDeletes (yyGLRStack* yystackp) yyremoveDeletes (yyGLRStack* yystackp)
{ {
size_t yyi, yyj; ptrdiff_t yyi, yyj;
yyi = yyj = 0; yyi = yyj = 0;
while (yyj < yystackp->yytops.yysize) while (yyj < yystackp->yytops.yysize)
{ {
@@ -1270,8 +1281,8 @@ yyremoveDeletes (yyGLRStack* yystackp)
yystackp->yytops.yylookaheadNeeds[yyi]; yystackp->yytops.yylookaheadNeeds[yyi];
if (yyj != yyi) if (yyj != yyi)
{ {
YYDPRINTF ((stderr, "Rename stack %lu -> %lu.\n", YYDPRINTF ((stderr, "Rename stack %ld -> %ld.\n",
(unsigned long) yyi, (unsigned long) yyj)); (long) yyi, (long) yyj));
} }
yyj += 1; yyj += 1;
} }
@@ -1283,8 +1294,8 @@ yyremoveDeletes (yyGLRStack* yystackp)
* state YYLRSTATE, at input position YYPOSN, with (resolved) semantic * state YYLRSTATE, at input position YYPOSN, with (resolved) semantic
* value *YYVALP and source location *YYLOCP. */ * value *YYVALP and source location *YYLOCP. */
static inline void static inline void
yyglrShift (yyGLRStack* yystackp, size_t yyk, yyStateNum yylrState, yyglrShift (yyGLRStack* yystackp, ptrdiff_t yyk, yyStateNum yylrState,
size_t yyposn, ptrdiff_t yyposn,
YYSTYPE* yyvalp]b4_locations_if([, YYLTYPE* yylocp])[) YYSTYPE* yyvalp]b4_locations_if([, YYLTYPE* yylocp])[)
{ {
yyGLRState* yynewState = &yynewGLRStackItem (yystackp, yytrue)->yystate; yyGLRState* yynewState = &yynewGLRStackItem (yystackp, yytrue)->yystate;
@@ -1304,8 +1315,8 @@ yyglrShift (yyGLRStack* yystackp, size_t yyk, yyStateNum yylrState,
* state YYLRSTATE, at input position YYPOSN, with the (unresolved) * state YYLRSTATE, at input position YYPOSN, with the (unresolved)
* semantic value of YYRHS under the action for YYRULE. */ * semantic value of YYRHS under the action for YYRULE. */
static inline void static inline void
yyglrShiftDefer (yyGLRStack* yystackp, size_t yyk, yyStateNum yylrState, yyglrShiftDefer (yyGLRStack* yystackp, ptrdiff_t yyk, yyStateNum yylrState,
size_t yyposn, yyGLRState* yyrhs, yyRuleNum yyrule) ptrdiff_t yyposn, yyGLRState* yyrhs, yyRuleNum yyrule)
{ {
yyGLRState* yynewState = &yynewGLRStackItem (yystackp, yytrue)->yystate; yyGLRState* yynewState = &yynewGLRStackItem (yystackp, yytrue)->yystate;
YYASSERT (yynewState->yyisState); YYASSERT (yynewState->yyisState);
@@ -1335,15 +1346,14 @@ yyglrShiftDefer (yyGLRStack* yystackp, size_t yyk, yyStateNum yylrState,
`----------------------------------------------------------------------*/ `----------------------------------------------------------------------*/
static inline void static inline void
yy_reduce_print (yybool yynormal, yyGLRStackItem* yyvsp, size_t yyk, yy_reduce_print (yybool yynormal, yyGLRStackItem* yyvsp, ptrdiff_t yyk,
yyRuleNum yyrule]b4_user_formals[) yyRuleNum yyrule]b4_user_formals[)
{ {
int yynrhs = yyrhsLength (yyrule);]b4_locations_if([ int yynrhs = yyrhsLength (yyrule);]b4_locations_if([
int yylow = 1;])[ int yylow = 1;])[
int yyi; int yyi;
YYFPRINTF (stderr, "Reducing stack %lu by rule %d (line %lu):\n", YYFPRINTF (stderr, "Reducing stack %ld by rule %d (line %d):\n",
(unsigned long) yyk, yyrule - 1, (long) yyk, yyrule - 1, yyrline[yyrule]);
(unsigned long) yyrline[yyrule]);
if (! yynormal) if (! yynormal)
yyfillin (yyvsp, 1, -yynrhs); yyfillin (yyvsp, 1, -yynrhs);
/* The symbols being reduced. */ /* The symbols being reduced. */
@@ -1369,7 +1379,7 @@ yy_reduce_print (yybool yynormal, yyGLRStackItem* yyvsp, size_t yyk,
* and *YYLOCP to the computed location (if any). Return value is as * and *YYLOCP to the computed location (if any). Return value is as
* for userAction. */ * for userAction. */
static inline YYRESULTTAG static inline YYRESULTTAG
yydoAction (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule, yydoAction (yyGLRStack* yystackp, ptrdiff_t yyk, yyRuleNum yyrule,
YYSTYPE* yyvalp]b4_locuser_formals[) YYSTYPE* yyvalp]b4_locuser_formals[)
{ {
int yynrhs = yyrhsLength (yyrule); int yynrhs = yyrhsLength (yyrule);
@@ -1380,7 +1390,7 @@ yydoAction (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
yyGLRStackItem* yyrhs = (yyGLRStackItem*) yystackp->yytops.yystates[yyk]; yyGLRStackItem* yyrhs = (yyGLRStackItem*) yystackp->yytops.yystates[yyk];
YYASSERT (yyk == 0); YYASSERT (yyk == 0);
yystackp->yynextFree -= yynrhs; yystackp->yynextFree -= yynrhs;
yystackp->yyspaceLeft += (size_t) yynrhs; yystackp->yyspaceLeft += yynrhs;
yystackp->yytops.yystates[0] = & yystackp->yynextFree[-1].yystate; yystackp->yytops.yystates[0] = & yystackp->yynextFree[-1].yystate;
YY_REDUCE_PRINT ((yytrue, yyrhs, yyk, yyrule]b4_user_args[)); YY_REDUCE_PRINT ((yytrue, yyrhs, yyk, yyrule]b4_user_args[));
return yyuserAction (yyrule, yynrhs, yyrhs, yystackp, return yyuserAction (yyrule, yynrhs, yyrhs, yystackp,
@@ -1388,11 +1398,10 @@ yydoAction (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
} }
else else
{ {
int yyi;
yyGLRState* yys;
yyGLRStackItem yyrhsVals[YYMAXRHS + YYMAXLEFT + 1]; yyGLRStackItem yyrhsVals[YYMAXRHS + YYMAXLEFT + 1];
yys = yyrhsVals[YYMAXRHS + YYMAXLEFT].yystate.yypred yyGLRState* yys = yyrhsVals[YYMAXRHS + YYMAXLEFT].yystate.yypred
= yystackp->yytops.yystates[yyk];]b4_locations_if([[ = yystackp->yytops.yystates[yyk];
int yyi;]b4_locations_if([[
if (yynrhs == 0) if (yynrhs == 0)
/* Set default location. */ /* Set default location. */
yyrhsVals[YYMAXRHS + YYMAXLEFT - 1].yystate.yyloc = yys->yyloc;]])[ yyrhsVals[YYMAXRHS + YYMAXLEFT - 1].yystate.yyloc = yys->yyloc;]])[
@@ -1421,10 +1430,10 @@ yydoAction (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
* added to the options for the existing state's semantic value. * added to the options for the existing state's semantic value.
*/ */
static inline YYRESULTTAG static inline YYRESULTTAG
yyglrReduce (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule, yyglrReduce (yyGLRStack* yystackp, ptrdiff_t yyk, yyRuleNum yyrule,
yybool yyforceEval]b4_user_formals[) yybool yyforceEval]b4_user_formals[)
{ {
size_t yyposn = yystackp->yytops.yystates[yyk]->yyposn; ptrdiff_t yyposn = yystackp->yytops.yystates[yyk]->yyposn;
if (yyforceEval || yystackp->yysplitPoint == YY_NULLPTR) if (yyforceEval || yystackp->yysplitPoint == YY_NULLPTR)
{ {
@@ -1434,8 +1443,9 @@ yyglrReduce (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
YYRESULTTAG yyflag = yydoAction (yystackp, yyk, yyrule, &yysval]b4_locuser_args([&yyloc])[); YYRESULTTAG yyflag = yydoAction (yystackp, yyk, yyrule, &yysval]b4_locuser_args([&yyloc])[);
if (yyflag == yyerr && yystackp->yysplitPoint != YY_NULLPTR) if (yyflag == yyerr && yystackp->yysplitPoint != YY_NULLPTR)
{ {
YYDPRINTF ((stderr, "Parse on stack %lu rejected by rule #%d.\n", YYDPRINTF ((stderr,
(unsigned long) yyk, yyrule - 1)); "Parse on stack %ld rejected by rule %d (line %d).\n",
(long) yyk, yyrule - 1, yyrline[yyrule - 1]));
} }
if (yyflag != yyok) if (yyflag != yyok)
return yyflag; return yyflag;
@@ -1447,7 +1457,7 @@ yyglrReduce (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
} }
else else
{ {
size_t yyi; ptrdiff_t yyi;
int yyn; int yyn;
yyGLRState* yys, *yys0 = yystackp->yytops.yystates[yyk]; yyGLRState* yys, *yys0 = yystackp->yytops.yystates[yyk];
yyStateNum yynewLRState; yyStateNum yynewLRState;
@@ -1461,9 +1471,9 @@ yyglrReduce (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
yyupdateSplit (yystackp, yys); yyupdateSplit (yystackp, yys);
yynewLRState = yyLRgotoState (yys->yylrState, yylhsNonterm (yyrule)); yynewLRState = yyLRgotoState (yys->yylrState, yylhsNonterm (yyrule));
YYDPRINTF ((stderr, YYDPRINTF ((stderr,
"Reduced stack %lu by rule #%d; action deferred. " "Reduced stack %ld by rule %d (line %d); action deferred. "
"Now in state %d.\n", "Now in state %d.\n",
(unsigned long) yyk, yyrule - 1, yynewLRState)); (long) yyk, yyrule - 1, yyrline[yyrule - 1], yynewLRState));
for (yyi = 0; yyi < yystackp->yytops.yysize; yyi += 1) for (yyi = 0; yyi < yystackp->yytops.yysize; yyi += 1)
if (yyi != yyk && yystackp->yytops.yystates[yyi] != YY_NULLPTR) if (yyi != yyk && yystackp->yytops.yystates[yyi] != YY_NULLPTR)
{ {
@@ -1475,9 +1485,8 @@ yyglrReduce (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
{ {
yyaddDeferredAction (yystackp, yyk, yyp, yys0, yyrule); yyaddDeferredAction (yystackp, yyk, yyp, yys0, yyrule);
yymarkStackDeleted (yystackp, yyk); yymarkStackDeleted (yystackp, yyk);
YYDPRINTF ((stderr, "Merging stack %lu into stack %lu.\n", YYDPRINTF ((stderr, "Merging stack %ld into stack %ld.\n",
(unsigned long) yyk, (long) yyk, (long) yyi));
(unsigned long) yyi));
return yyok; return yyok;
} }
yyp = yyp->yypred; yyp = yyp->yypred;
@@ -1489,8 +1498,8 @@ yyglrReduce (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
return yyok; return yyok;
} }
static size_t static ptrdiff_t
yysplitStack (yyGLRStack* yystackp, size_t yyk) yysplitStack (yyGLRStack* yystackp, ptrdiff_t yyk)
{ {
if (yystackp->yysplitPoint == YY_NULLPTR) if (yystackp->yysplitPoint == YY_NULLPTR)
{ {
@@ -1501,15 +1510,16 @@ yysplitStack (yyGLRStack* yystackp, size_t yyk)
{ {
yyGLRState** yynewStates = YY_NULLPTR; yyGLRState** yynewStates = YY_NULLPTR;
yybool* yynewLookaheadNeeds; yybool* yynewLookaheadNeeds;
ptrdiff_t state_size = sizeof yynewStates[0];
ptrdiff_t half_max_capacity = YYSIZEMAX / 2 / state_size;
if (yystackp->yytops.yycapacity if (half_max_capacity < yystackp->yytops.yycapacity)
> (YYSIZEMAX / (2 * sizeof yynewStates[0])))
yyMemoryExhausted (yystackp); yyMemoryExhausted (yystackp);
yystackp->yytops.yycapacity *= 2; yystackp->yytops.yycapacity *= 2;
yynewStates = yynewStates =
(yyGLRState**) YYREALLOC (yystackp->yytops.yystates, (yyGLRState**) YYREALLOC (yystackp->yytops.yystates,
(yystackp->yytops.yycapacity ((size_t) yystackp->yytops.yycapacity
* sizeof yynewStates[0])); * sizeof yynewStates[0]));
if (yynewStates == YY_NULLPTR) if (yynewStates == YY_NULLPTR)
yyMemoryExhausted (yystackp); yyMemoryExhausted (yystackp);
@@ -1517,7 +1527,7 @@ yysplitStack (yyGLRStack* yystackp, size_t yyk)
yynewLookaheadNeeds = yynewLookaheadNeeds =
(yybool*) YYREALLOC (yystackp->yytops.yylookaheadNeeds, (yybool*) YYREALLOC (yystackp->yytops.yylookaheadNeeds,
(yystackp->yytops.yycapacity ((size_t) yystackp->yytops.yycapacity
* sizeof yynewLookaheadNeeds[0])); * sizeof yynewLookaheadNeeds[0]));
if (yynewLookaheadNeeds == YY_NULLPTR) if (yynewLookaheadNeeds == YY_NULLPTR)
yyMemoryExhausted (yystackp); yyMemoryExhausted (yystackp);
@@ -1719,10 +1729,10 @@ yyreportTree (yySemanticOption* yyx, int yyindent)
yyindent, "", yytokenName (yylhsNonterm (yyx->yyrule)), yyindent, "", yytokenName (yylhsNonterm (yyx->yyrule)),
yyx->yyrule - 1); yyx->yyrule - 1);
else else
YYFPRINTF (stderr, "%*s%s -> <Rule %d, tokens %lu .. %lu>\n", YYFPRINTF (stderr, "%*s%s -> <Rule %d, tokens %ld .. %ld>\n",
yyindent, "", yytokenName (yylhsNonterm (yyx->yyrule)), yyindent, "", yytokenName (yylhsNonterm (yyx->yyrule)),
yyx->yyrule - 1, (unsigned long) (yys->yyposn + 1), yyx->yyrule - 1, (long) (yys->yyposn + 1),
(unsigned long) yyx->yystate->yyposn); (long) yyx->yystate->yyposn);
for (yyi = 1; yyi <= yynrhs; yyi += 1) for (yyi = 1; yyi <= yynrhs; yyi += 1)
{ {
if (yystates[yyi]->yyresolved) if (yystates[yyi]->yyresolved)
@@ -1731,10 +1741,10 @@ yyreportTree (yySemanticOption* yyx, int yyindent)
YYFPRINTF (stderr, "%*s%s <empty>\n", yyindent+2, "", YYFPRINTF (stderr, "%*s%s <empty>\n", yyindent+2, "",
yytokenName (yystos[yystates[yyi]->yylrState])); yytokenName (yystos[yystates[yyi]->yylrState]));
else else
YYFPRINTF (stderr, "%*s%s <tokens %lu .. %lu>\n", yyindent+2, "", YYFPRINTF (stderr, "%*s%s <tokens %ld .. %ld>\n", yyindent+2, "",
yytokenName (yystos[yystates[yyi]->yylrState]), yytokenName (yystos[yystates[yyi]->yylrState]),
(unsigned long) (yystates[yyi-1]->yyposn + 1), (long) (yystates[yyi-1]->yyposn + 1),
(unsigned long) yystates[yyi]->yyposn); (long) yystates[yyi]->yyposn);
} }
else else
yyreportTree (yystates[yyi]->yysemantics.yyfirstVal, yyindent+2); yyreportTree (yystates[yyi]->yysemantics.yyfirstVal, yyindent+2);
@@ -1929,9 +1939,9 @@ yycompressStack (yyGLRStack* yystackp)
yyr = yyp, yyp = yyq, yyq = yyp->yypred) yyr = yyp, yyp = yyq, yyq = yyp->yypred)
yyp->yypred = yyr; yyp->yypred = yyr;
yystackp->yyspaceLeft += (size_t) (yystackp->yynextFree - yystackp->yyitems); yystackp->yyspaceLeft += yystackp->yynextFree - yystackp->yyitems;
yystackp->yynextFree = ((yyGLRStackItem*) yystackp->yysplitPoint) + 1; yystackp->yynextFree = ((yyGLRStackItem*) yystackp->yysplitPoint) + 1;
yystackp->yyspaceLeft -= (size_t) (yystackp->yynextFree - yystackp->yyitems); yystackp->yyspaceLeft -= yystackp->yynextFree - yystackp->yyitems;
yystackp->yysplitPoint = YY_NULLPTR; yystackp->yysplitPoint = YY_NULLPTR;
yystackp->yylastDeleted = YY_NULLPTR; yystackp->yylastDeleted = YY_NULLPTR;
@@ -1947,14 +1957,13 @@ yycompressStack (yyGLRStack* yystackp)
} }
static YYRESULTTAG static YYRESULTTAG
yyprocessOneStack (yyGLRStack* yystackp, size_t yyk, yyprocessOneStack (yyGLRStack* yystackp, ptrdiff_t yyk,
size_t yyposn]b4_pure_formals[) ptrdiff_t yyposn]b4_pure_formals[)
{ {
while (yystackp->yytops.yystates[yyk] != YY_NULLPTR) while (yystackp->yytops.yystates[yyk] != YY_NULLPTR)
{ {
yyStateNum yystate = yystackp->yytops.yystates[yyk]->yylrState; yyStateNum yystate = yystackp->yytops.yystates[yyk]->yylrState;
YYDPRINTF ((stderr, "Stack %lu Entering state %d\n", YYDPRINTF ((stderr, "Stack %ld Entering state %d\n", yyk, yystate));
(unsigned long) yyk, yystate));
YYASSERT (yystate != YYFINAL); YYASSERT (yystate != YYFINAL);
@@ -1964,8 +1973,7 @@ yyprocessOneStack (yyGLRStack* yystackp, size_t yyk,
yyRuleNum yyrule = yydefaultAction (yystate); yyRuleNum yyrule = yydefaultAction (yystate);
if (yyrule == 0) if (yyrule == 0)
{ {
YYDPRINTF ((stderr, "Stack %lu dies.\n", YYDPRINTF ((stderr, "Stack %ld dies.\n", (long) yyk));
(unsigned long) yyk));
yymarkStackDeleted (yystackp, yyk); yymarkStackDeleted (yystackp, yyk);
return yyok; return yyok;
} }
@@ -1973,9 +1981,9 @@ yyprocessOneStack (yyGLRStack* yystackp, size_t yyk,
if (yyflag == yyerr) if (yyflag == yyerr)
{ {
YYDPRINTF ((stderr, YYDPRINTF ((stderr,
"Stack %lu dies " "Stack %ld dies "
"(predicate failure or explicit user error).\n", "(predicate failure or explicit user error).\n",
(unsigned long) yyk)); (long) yyk));
yymarkStackDeleted (yystackp, yyk); yymarkStackDeleted (yystackp, yyk);
return yyok; return yyok;
} }
@@ -1984,21 +1992,17 @@ yyprocessOneStack (yyGLRStack* yystackp, size_t yyk,
} }
else else
{ {
yySymbol yytoken; yySymbol yytoken = ]b4_yygetToken_call[;
int yyaction;
const short* yyconflicts; const short* yyconflicts;
const int yyaction = yygetLRActions (yystate, yytoken, &yyconflicts);
yystackp->yytops.yylookaheadNeeds[yyk] = yytrue; yystackp->yytops.yylookaheadNeeds[yyk] = yytrue;
yytoken = ]b4_yygetToken_call[;
yyaction = yygetLRActions (yystate, yytoken, &yyconflicts);
while (*yyconflicts != 0) while (*yyconflicts != 0)
{ {
YYRESULTTAG yyflag; YYRESULTTAG yyflag;
size_t yynewStack = yysplitStack (yystackp, yyk); ptrdiff_t yynewStack = yysplitStack (yystackp, yyk);
YYDPRINTF ((stderr, "Splitting off stack %lu from %lu.\n", YYDPRINTF ((stderr, "Splitting off stack %ld from %ld.\n",
(unsigned long) yynewStack, (long) yynewStack, (long) yyk));
(unsigned long) yyk));
yyflag = yyglrReduce (yystackp, yynewStack, yyflag = yyglrReduce (yystackp, yynewStack,
*yyconflicts, *yyconflicts,
yyimmediate[*yyconflicts]]b4_user_args[); yyimmediate[*yyconflicts]]b4_user_args[);
@@ -2007,8 +2011,7 @@ yyprocessOneStack (yyGLRStack* yystackp, size_t yyk,
yyposn]b4_pure_args[)); yyposn]b4_pure_args[));
else if (yyflag == yyerr) else if (yyflag == yyerr)
{ {
YYDPRINTF ((stderr, "Stack %lu dies.\n", YYDPRINTF ((stderr, "Stack %ld dies.\n", (long) yynewStack));
(unsigned long) yynewStack));
yymarkStackDeleted (yystackp, yynewStack); yymarkStackDeleted (yystackp, yynewStack);
} }
else else
@@ -2020,8 +2023,7 @@ yyprocessOneStack (yyGLRStack* yystackp, size_t yyk,
break; break;
else if (yyisErrorAction (yyaction)) else if (yyisErrorAction (yyaction))
{ {
YYDPRINTF ((stderr, "Stack %lu dies.\n", YYDPRINTF ((stderr, "Stack %ld dies.\n", (long) yyk));
(unsigned long) yyk));
yymarkStackDeleted (yystackp, yyk); yymarkStackDeleted (yystackp, yyk);
break; break;
} }
@@ -2032,9 +2034,9 @@ yyprocessOneStack (yyGLRStack* yystackp, size_t yyk,
if (yyflag == yyerr) if (yyflag == yyerr)
{ {
YYDPRINTF ((stderr, YYDPRINTF ((stderr,
"Stack %lu dies " "Stack %ld dies "
"(predicate failure or explicit user error).\n", "(predicate failure or explicit user error).\n",
(unsigned long) yyk)); (long) yyk));
yymarkStackDeleted (yystackp, yyk); yymarkStackDeleted (yystackp, yyk);
break; break;
} }
@@ -2056,8 +2058,8 @@ yyreportSyntaxError (yyGLRStack* yystackp]b4_user_formals[)
#else #else
{ {
yySymbol yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar); yySymbol yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
size_t yysize0 = yytnamerr (YY_NULLPTR, yytokenName (yytoken)); ptrdiff_t yysize0 = yytnamerr (YY_NULLPTR, yytokenName (yytoken));
size_t yysize = yysize0; ptrdiff_t yysize = yysize0;
yybool yysize_overflow = yyfalse; yybool yysize_overflow = yyfalse;
char* yymsg = YY_NULLPTR; char* yymsg = YY_NULLPTR;
enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
@@ -2118,10 +2120,11 @@ yyreportSyntaxError (yyGLRStack* yystackp]b4_user_formals[)
} }
yyarg[yycount++] = yytokenName (yyx); yyarg[yycount++] = yytokenName (yyx);
{ {
size_t yysz = yysize + yytnamerr (YY_NULLPTR, yytokenName (yyx)); ptrdiff_t yysz = yytnamerr (YY_NULLPTR, yytokenName (yyx));
if (yysz < yysize) if (YYSIZEMAX - yysize < yysz)
yysize_overflow = yytrue; yysize_overflow = yytrue;
yysize = yysz; else
yysize += yysz;
} }
} }
} }
@@ -2144,14 +2147,15 @@ yyreportSyntaxError (yyGLRStack* yystackp]b4_user_formals[)
} }
{ {
size_t yysz = yysize + strlen (yyformat); ptrdiff_t yysz = (ptrdiff_t) strlen (yyformat);
if (yysz < yysize) if (YYSIZEMAX - yysize < yysz)
yysize_overflow = yytrue; yysize_overflow = yytrue;
yysize = yysz; else
yysize += yysz;
} }
if (!yysize_overflow) if (!yysize_overflow)
yymsg = (char *) YYMALLOC (yysize); yymsg = (char *) YYMALLOC ((size_t) yysize);
if (yymsg) if (yymsg)
{ {
@@ -2228,7 +2232,7 @@ yyrecoverSyntaxError (yyGLRStack* yystackp]b4_user_formals[)
/* Reduce to one stack. */ /* Reduce to one stack. */
{ {
size_t yyk; ptrdiff_t yyk;
for (yyk = 0; yyk < yystackp->yytops.yysize; yyk += 1) for (yyk = 0; yyk < yystackp->yytops.yysize; yyk += 1)
if (yystackp->yytops.yystates[yyk] != YY_NULLPTR) if (yystackp->yytops.yystates[yyk] != YY_NULLPTR)
break; break;
@@ -2252,14 +2256,15 @@ yyrecoverSyntaxError (yyGLRStack* yystackp]b4_user_formals[)
if (0 <= yyj && yyj <= YYLAST && yycheck[yyj] == YYTERROR if (0 <= yyj && yyj <= YYLAST && yycheck[yyj] == YYTERROR
&& yyisShiftAction (yytable[yyj])) && yyisShiftAction (yytable[yyj]))
{ {
/* Shift the error token. */]b4_locations_if([[ /* Shift the error token. */
int yyaction = yytable[yyj];]b4_locations_if([[
/* First adjust its location.*/ /* First adjust its location.*/
YYLTYPE yyerrloc; YYLTYPE yyerrloc;
yystackp->yyerror_range[2].yystate.yyloc = yylloc; yystackp->yyerror_range[2].yystate.yyloc = yylloc;
YYLLOC_DEFAULT (yyerrloc, (yystackp->yyerror_range), 2);]])[ YYLLOC_DEFAULT (yyerrloc, (yystackp->yyerror_range), 2);]])[
YY_SYMBOL_PRINT ("Shifting", yystos[yytable[yyj]], YY_SYMBOL_PRINT ("Shifting", yystos[yyaction],
&yylval, &yyerrloc); &yylval, &yyerrloc);
yyglrShift (yystackp, 0, yytable[yyj], yyglrShift (yystackp, 0, yyaction,
yys->yyposn, &yylval]b4_locations_if([, &yyerrloc])[); yys->yyposn, &yylval]b4_locations_if([, &yyerrloc])[);
yys = yystackp->yytops.yystates[0]; yys = yystackp->yytops.yystates[0];
break; break;
@@ -2301,7 +2306,7 @@ yyrecoverSyntaxError (yyGLRStack* yystackp]b4_user_formals[)
int yyresult; int yyresult;
yyGLRStack yystack; yyGLRStack yystack;
yyGLRStack* const yystackp = &yystack; yyGLRStack* const yystackp = &yystack;
size_t yyposn; ptrdiff_t yyposn;
YYDPRINTF ((stderr, "Starting parse\n")); YYDPRINTF ((stderr, "Starting parse\n"));
@@ -2381,7 +2386,7 @@ b4_dollar_popdef])[]dnl
while (yytrue) while (yytrue)
{ {
yySymbol yytoken_to_shift; yySymbol yytoken_to_shift;
size_t yys; ptrdiff_t yys;
for (yys = 0; yys < yystack.yytops.yysize; yys += 1) for (yys = 0; yys < yystack.yytops.yysize; yys += 1)
yystackp->yytops.yylookaheadNeeds[yys] = (yybool) (yychar != YYEMPTY); yystackp->yytops.yylookaheadNeeds[yys] = (yybool) (yychar != YYEMPTY);
@@ -2435,12 +2440,12 @@ b4_dollar_popdef])[]dnl
int yyaction = yygetLRActions (yystate, yytoken_to_shift, int yyaction = yygetLRActions (yystate, yytoken_to_shift,
&yyconflicts); &yyconflicts);
/* Note that yyconflicts were handled by yyprocessOneStack. */ /* Note that yyconflicts were handled by yyprocessOneStack. */
YYDPRINTF ((stderr, "On stack %lu, ", (unsigned long) yys)); YYDPRINTF ((stderr, "On stack %ld, ", (long) yys));
YY_SYMBOL_PRINT ("shifting", yytoken_to_shift, &yylval, &yylloc); YY_SYMBOL_PRINT ("shifting", yytoken_to_shift, &yylval, &yylloc);
yyglrShift (&yystack, yys, yyaction, yyposn, yyglrShift (&yystack, yys, yyaction, yyposn,
&yylval]b4_locations_if([, &yylloc])[); &yylval]b4_locations_if([, &yylloc])[);
YYDPRINTF ((stderr, "Stack %lu now in state #%d\n", YYDPRINTF ((stderr, "Stack %ld now in state #%d\n",
(unsigned long) yys, (long) yys,
yystack.yytops.yystates[yys]->yylrState)); yystack.yytops.yystates[yys]->yylrState));
} }
@@ -2488,8 +2493,8 @@ b4_dollar_popdef])[]dnl
yyGLRState** yystates = yystack.yytops.yystates; yyGLRState** yystates = yystack.yytops.yystates;
if (yystates) if (yystates)
{ {
size_t yysize = yystack.yytops.yysize; ptrdiff_t yysize = yystack.yytops.yysize;
size_t yyk; ptrdiff_t yyk;
for (yyk = 0; yyk < yysize; yyk += 1) for (yyk = 0; yyk < yysize; yyk += 1)
if (yystates[yyk]) if (yystates[yyk])
{ {
@@ -2522,8 +2527,7 @@ yy_yypstack (yyGLRState* yys)
yy_yypstack (yys->yypred); yy_yypstack (yys->yypred);
YYFPRINTF (stderr, " -> "); YYFPRINTF (stderr, " -> ");
} }
YYFPRINTF (stderr, "%d@@%lu", yys->yylrState, YYFPRINTF (stderr, "%d@@%ld", yys->yylrState, (long) yys->yyposn);
(unsigned long) yys->yyposn);
} }
static void static void
@@ -2537,7 +2541,7 @@ yypstates (yyGLRState* yyst)
} }
static void static void
yypstack (yyGLRStack* yystackp, size_t yyk) yypstack (yyGLRStack* yystackp, ptrdiff_t yyk)
{ {
yypstates (yystackp->yytops.yystates[yyk]); yypstates (yystackp->yytops.yystates[yyk]);
} }
@@ -2550,18 +2554,18 @@ static void
yypdumpstack (yyGLRStack* yystackp) yypdumpstack (yyGLRStack* yystackp)
{ {
yyGLRStackItem* yyp; yyGLRStackItem* yyp;
size_t yyi; ptrdiff_t yyi;
for (yyp = yystackp->yyitems; yyp < yystackp->yynextFree; yyp += 1) for (yyp = yystackp->yyitems; yyp < yystackp->yynextFree; yyp += 1)
{ {
YYFPRINTF (stderr, "%3lu. ", YYFPRINTF (stderr, "%3ld. ",
(unsigned long) (yyp - yystackp->yyitems)); (long) (yyp - yystackp->yyitems));
if (*(yybool *) yyp) if (*(yybool *) yyp)
{ {
YYASSERT (yyp->yystate.yyisState); YYASSERT (yyp->yystate.yyisState);
YYASSERT (yyp->yyoption.yyisState); YYASSERT (yyp->yyoption.yyisState);
YYFPRINTF (stderr, "Res: %d, LR State: %d, posn: %lu, pred: %ld", YYFPRINTF (stderr, "Res: %d, LR State: %d, posn: %ld, pred: %ld",
yyp->yystate.yyresolved, yyp->yystate.yylrState, yyp->yystate.yyresolved, yyp->yystate.yylrState,
(unsigned long) yyp->yystate.yyposn, (long) yyp->yystate.yyposn,
(long) YYINDEX (yyp->yystate.yypred)); (long) YYINDEX (yyp->yystate.yypred));
if (! yyp->yystate.yyresolved) if (! yyp->yystate.yyresolved)
YYFPRINTF (stderr, ", firstVal: %ld", YYFPRINTF (stderr, ", firstVal: %ld",
@@ -2581,7 +2585,7 @@ yypdumpstack (yyGLRStack* yystackp)
} }
YYFPRINTF (stderr, "Tops:"); YYFPRINTF (stderr, "Tops:");
for (yyi = 0; yyi < yystackp->yytops.yysize; yyi += 1) for (yyi = 0; yyi < yystackp->yytops.yysize; yyi += 1)
YYFPRINTF (stderr, "%lu: %ld; ", (unsigned long) yyi, YYFPRINTF (stderr, "%ld: %ld; ", (long) yyi,
(long) YYINDEX (yystackp->yytops.yystates[yyi])); (long) YYINDEX (yystackp->yytops.yystates[yyi]));
YYFPRINTF (stderr, "\n"); YYFPRINTF (stderr, "\n");
} }
+13 -2
View File
@@ -184,8 +184,19 @@ b4_percent_define_check_kind([[throws]], [code], [deprecated])
m4_define([b4_yystype], [b4_percent_define_get([[api.value.type]])]) m4_define([b4_yystype], [b4_percent_define_get([[api.value.type]])])
b4_percent_define_default([[api.value.type]], [[Object]]) b4_percent_define_default([[api.value.type]], [[Object]])
# %name-prefix # b4_api_prefix, b4_api_PREFIX
m4_define_default([b4_prefix], [[YY]]) # ----------------------------
# Corresponds to %define api.prefix
b4_percent_define_default([[api.prefix]], [[YY]])
m4_define([b4_api_prefix],
[b4_percent_define_get([[api.prefix]])])
m4_define([b4_api_PREFIX],
[m4_toupper(b4_api_prefix)])
# b4_prefix
# ---------
# If the %name-prefix is not given, it is api.prefix.
m4_define_default([b4_prefix], [b4_api_prefix])
b4_percent_define_default([[api.parser.class]], [b4_prefix[]Parser]) b4_percent_define_default([[api.parser.class]], [b4_prefix[]Parser])
m4_define([b4_parser_class], [b4_percent_define_get([[api.parser.class]])]) m4_define([b4_parser_class], [b4_percent_define_get([[api.parser.class]])])
+246 -34
View File
@@ -20,14 +20,22 @@ m4_include(b4_skeletonsdir/[c++.m4])
# api.value.type=variant is valid. # api.value.type=variant is valid.
m4_define([b4_value_type_setup_variant]) m4_define([b4_value_type_setup_variant])
# Check the value of %define parse.lac, where LAC stands for lookahead
# correction.
b4_percent_define_default([[parse.lac]], [[none]])
b4_define_flag_if([lac])
m4_define([b4_lac_flag],
[m4_if(b4_percent_define_get([[parse.lac]]),
[none], [[0]], [[1]])])
# b4_integral_parser_table_declare(TABLE-NAME, CONTENT, COMMENT) # b4_integral_parser_table_declare(TABLE-NAME, CONTENT, COMMENT)
# -------------------------------------------------------------- # --------------------------------------------------------------
# Declare "parser::yy<TABLE-NAME>_" whose contents is CONTENT. # Declare "parser::yy<TABLE-NAME>_" whose contents is CONTENT.
m4_define([b4_integral_parser_table_declare], m4_define([b4_integral_parser_table_declare],
[m4_ifval([$3], [b4_comment([$3], [ ]) [m4_ifval([$3], [b4_comment([$3], [ ])
])dnl ])dnl
static const b4_int_type_for([$2]) yy$1_[[]];dnl static const b4_int_type_for([$2]) yy$1_[[]];dnl
]) ])
# b4_integral_parser_table_define(TABLE-NAME, CONTENT, COMMENT) # b4_integral_parser_table_define(TABLE-NAME, CONTENT, COMMENT)
@@ -220,10 +228,21 @@ m4_define([b4_shared_declarations],
private: private:
/// This class is not copyable. /// This class is not copyable.
]b4_parser_class[ (const ]b4_parser_class[&); ]b4_parser_class[ (const ]b4_parser_class[&);
]b4_parser_class[& operator= (const ]b4_parser_class[&); ]b4_parser_class[& operator= (const ]b4_parser_class[&);]b4_lac_if([[
/// State numbers. /// Check the lookahead yytoken.
typedef int state_type; /// \returns true iff the token will be eventually shifted.
bool yy_lac_check_ (int yytoken) const;
/// Establish the initial context if no initial context currently exists.
/// \returns true iff the token will be eventually shifted.
bool yy_lac_establish_ (int yytoken);
/// Discard any previous initial lookahead context because of event.
/// \param event the event which caused the lookahead to be discarded.
/// Only used for debbuging output.
void yy_lac_discard_ (const char* event);]])[
/// Stored state numbers (used for stacks).
typedef ]b4_int_type(0, m4_eval(b4_states_number - 1))[ state_type;
/// Generate an error message. /// Generate an error message.
/// \param yystate the state where the error occurred. /// \param yystate the state where the error occurred.
@@ -234,7 +253,7 @@ m4_define([b4_shared_declarations],
/// Compute post-reduction state. /// Compute post-reduction state.
/// \param yystate the current state /// \param yystate the current state
/// \param yysym the nonterminal to push on the stack /// \param yysym the nonterminal to push on the stack
state_type yy_lr_goto_state_ (state_type yystate, int yysym); static state_type yy_lr_goto_state_ (state_type yystate, int yysym);
/// Whether the given \c yypact_ value indicates a defaulted state. /// Whether the given \c yypact_ value indicates a defaulted state.
/// \param yyvalue the value to check /// \param yyvalue the value to check
@@ -335,6 +354,10 @@ m4_define([b4_shared_declarations],
/// Assignment, needed by push_back by some old implementations. /// Assignment, needed by push_back by some old implementations.
/// Moves the contents of that. /// Moves the contents of that.
stack_symbol_type& operator= (stack_symbol_type& that); stack_symbol_type& operator= (stack_symbol_type& that);
/// Assignment, needed by push_back by other implementations.
/// Needed by some other old implementations.
stack_symbol_type& operator= (const stack_symbol_type& that);
#endif #endif
}; };
@@ -344,7 +367,16 @@ m4_define([b4_shared_declarations],
typedef stack<stack_symbol_type> stack_type; typedef stack<stack_symbol_type> stack_type;
/// The stack. /// The stack.
stack_type yystack_; stack_type yystack_;]b4_lac_if([[
/// The stack for LAC.
/// Logically, the yy_lac_stack's lifetime is confined to the function
/// yy_lac_check_. We just store it as a member of this class to hold
/// on to the memory and to avoid frequent reallocations.
/// Since yy_lac_check_ is const, this member must be mutable.
mutable std::vector<state_type> yylac_stack_;
/// Whether an initial LAC context was established.
bool yy_lac_established_;
]])[
/// Push a new state on the stack. /// Push a new state on the stack.
/// \param m a debug message to display /// \param m a debug message to display
@@ -548,12 +580,14 @@ m4_if(b4_prefix, [yy], [],
]])[ ]])[
/// Build a parser object. /// Build a parser object.
]b4_parser_class::b4_parser_class[ (]b4_parse_param_decl[)]m4_ifset([b4_parse_param], [ ]b4_parser_class::b4_parser_class[ (]b4_parse_param_decl[)
:])[
#if ]b4_api_PREFIX[DEBUG #if ]b4_api_PREFIX[DEBUG
]m4_ifset([b4_parse_param], [ ], [ :])[yydebug_ (false), : yydebug_ (false),
yycdebug_ (&std::cerr)]m4_ifset([b4_parse_param], [,])[ yycdebug_ (&std::cerr)]b4_lac_if([,], [m4_ifset([b4_parse_param], [,])])[
#endif]b4_parse_param_cons[ #else
]b4_lac_if([ :], [m4_ifset([b4_parse_param], [ :])])[
#endif]b4_lac_if([[
yy_lac_established_ (false)]m4_ifset([b4_parse_param], [,])])[]b4_parse_param_cons[
{} {}
]b4_parser_class::~b4_parser_class[ () ]b4_parser_class::~b4_parser_class[ ()
@@ -627,6 +661,17 @@ m4_if(b4_prefix, [yy], [],
} }
#if YY_CPLUSPLUS < 201103L #if YY_CPLUSPLUS < 201103L
]b4_parser_class[::stack_symbol_type&
]b4_parser_class[::stack_symbol_type::operator= (const stack_symbol_type& that)
{
state = that.state;
]b4_variant_if([b4_symbol_variant([that.type_get ()],
[value], [copy], [that.value])],
[[value = that.value;]])[]b4_locations_if([
location = that.location;])[
return *this;
}
]b4_parser_class[::stack_symbol_type& ]b4_parser_class[::stack_symbol_type&
]b4_parser_class[::stack_symbol_type::operator= (stack_symbol_type& that) ]b4_parser_class[::stack_symbol_type::operator= (stack_symbol_type& that)
{ {
@@ -758,7 +803,6 @@ m4_if(b4_prefix, [yy], [],
int int
]b4_parser_class[::parse () ]b4_parser_class[::parse ()
{ {
// State.
int yyn; int yyn;
/// Length of the RHS of the rule being reduced. /// Length of the RHS of the rule being reduced.
int yylen = 0; int yylen = 0;
@@ -774,7 +818,11 @@ m4_if(b4_prefix, [yy], [],
stack_symbol_type yyerror_range[3];]])[ stack_symbol_type yyerror_range[3];]])[
/// The return value of parse (). /// The return value of parse ().
int yyresult; int yyresult;]b4_lac_if([[
/// Discard the LAC context in case there still is one left from a
/// previous invocation.
yy_lac_discard_ ("init");]])[
#if YY_EXCEPTIONS #if YY_EXCEPTIONS
try try
@@ -798,7 +846,7 @@ b4_dollar_popdef])[]dnl
| yynewstate -- push a new symbol on the stack. | | yynewstate -- push a new symbol on the stack. |
`-----------------------------------------------*/ `-----------------------------------------------*/
yynewstate: yynewstate:
YYCDEBUG << "Entering state " << yystack_[0].state << '\n'; YYCDEBUG << "Entering state " << int (yystack_[0].state) << '\n';
// Accept? // Accept?
if (yystack_[0].state == yyfinal_) if (yystack_[0].state == yyfinal_)
@@ -843,14 +891,21 @@ b4_dollar_popdef])[]dnl
to detect an error, take that action. */ to detect an error, take that action. */
yyn += yyla.type_get (); yyn += yyla.type_get ();
if (yyn < 0 || yylast_ < yyn || yycheck_[yyn] != yyla.type_get ()) if (yyn < 0 || yylast_ < yyn || yycheck_[yyn] != yyla.type_get ())
goto yydefault; {]b4_lac_if([[
if (!yy_lac_establish_ (yyla.type_get ()))
goto yyerrlab;]])[
goto yydefault;
}
// Reduce or error. // Reduce or error.
yyn = yytable_[yyn]; yyn = yytable_[yyn];
if (yyn <= 0) if (yyn <= 0)
{ {
if (yy_table_value_is_error_ (yyn)) if (yy_table_value_is_error_ (yyn))
goto yyerrlab; goto yyerrlab;]b4_lac_if([[
if (!yy_lac_establish_ (yyla.type_get ()))
goto yyerrlab;
]])[
yyn = -yyn; yyn = -yyn;
goto yyreduce; goto yyreduce;
} }
@@ -860,7 +915,8 @@ b4_dollar_popdef])[]dnl
--yyerrstatus_; --yyerrstatus_;
// Shift the lookahead token. // Shift the lookahead token.
yypush_ ("Shifting", yyn, YY_MOVE (yyla)); yypush_ ("Shifting", static_cast<state_type> (yyn), YY_MOVE (yyla));]b4_lac_if([[
yy_lac_discard_ ("shift");]])[
goto yynewstate; goto yynewstate;
@@ -1020,8 +1076,9 @@ b4_dollar_popdef])[]dnl
yyerror_range[2].location = yyla.location; yyerror_range[2].location = yyla.location;
YYLLOC_DEFAULT (error_token.location, yyerror_range, 2);]])[ YYLLOC_DEFAULT (error_token.location, yyerror_range, 2);]])[
// Shift the error token. // Shift the error token.]b4_lac_if([[
error_token.state = yyn; yy_lac_discard_ ("error recovery");]])[
error_token.state = static_cast<state_type> (yyn);
yypush_ ("Shifting", YY_MOVE (error_token)); yypush_ ("Shifting", YY_MOVE (error_token));
} }
goto yynewstate; goto yynewstate;
@@ -1085,8 +1142,147 @@ b4_dollar_popdef])[]dnl
{ {
error (]b4_join(b4_locations_if([yyexc.location]), error (]b4_join(b4_locations_if([yyexc.location]),
[[yyexc.what ()]])[); [[yyexc.what ()]])[);
}]b4_lac_if([[
bool
]b4_parser_class[::yy_lac_check_ (int yytoken) const
{
// Logically, the yylac_stack's lifetime is confined to this function.
// Clear it, to get rid of potential left-overs from previous call.
yylac_stack_.clear ();
// Reduce until we encounter a shift and thereby accept the token.
#if ]b4_api_PREFIX[DEBUG
YYCDEBUG << "LAC: checking lookahead " << yytname_[yytoken] << ':';
#endif
std::ptrdiff_t lac_top = 0;
while (true)
{
state_type top_state = (yylac_stack_.empty ()
? yystack_[lac_top].state
: yylac_stack_.back ());
int yyrule = yypact_[top_state];
if (yy_pact_value_is_default_ (yyrule)
|| (yyrule += yytoken) < 0 || yylast_ < yyrule
|| yycheck_[yyrule] != yytoken)
{
// Use the default action.
yyrule = yydefact_[top_state];
if (yyrule == 0)
{
YYCDEBUG << " Err\n";
return false;
}
}
else
{
// Use the action from yytable.
yyrule = yytable_[yyrule];
if (yy_table_value_is_error_ (yyrule))
{
YYCDEBUG << " Err\n";
return false;
}
if (0 < yyrule)
{
YYCDEBUG << " S" << yyrule << '\n';
return true;
}
yyrule = -yyrule;
}
// By now we know we have to simulate a reduce.
YYCDEBUG << " R" << yyrule - 1;
// Pop the corresponding number of values from the stack.
{
std::ptrdiff_t yylen = yyr2_[yyrule];
// First pop from the LAC stack as many tokens as possible.
std::ptrdiff_t lac_size = (std::ptrdiff_t) yylac_stack_.size ();
if (yylen < lac_size)
{
yylac_stack_.resize ((std::size_t) (lac_size - yylen));
yylen = 0;
}
else if (lac_size)
{
yylac_stack_.clear ();
yylen -= lac_size;
}
// Only afterwards look at the main stack.
// We simulate popping elements by incrementing lac_top.
lac_top += yylen;
}
// Keep top_state in sync with the updated stack.
top_state = (yylac_stack_.empty ()
? yystack_[lac_top].state
: yylac_stack_.back ());
// Push the resulting state of the reduction.
state_type state = yy_lr_goto_state_ (top_state, yyr1_[yyrule]);
YYCDEBUG << " G" << state;
yylac_stack_.push_back (state);
}
} }
// Establish the initial context if no initial context currently exists.
bool
]b4_parser_class[::yy_lac_establish_ (int yytoken)
{
/* Establish the initial context for the current lookahead if no initial
context is currently established.
We define a context as a snapshot of the parser stacks. We define
the initial context for a lookahead as the context in which the
parser initially examines that lookahead in order to select a
syntactic action. Thus, if the lookahead eventually proves
syntactically unacceptable (possibly in a later context reached via a
series of reductions), the initial context can be used to determine
the exact set of tokens that would be syntactically acceptable in the
lookahead's place. Moreover, it is the context after which any
further semantic actions would be erroneous because they would be
determined by a syntactically unacceptable token.
yy_lac_establish_ should be invoked when a reduction is about to be
performed in an inconsistent state (which, for the purposes of LAC,
includes consistent states that don't know they're consistent because
their default reductions have been disabled).
For parse.lac=full, the implementation of yy_lac_establish_ is as
follows. If no initial context is currently established for the
current lookahead, then check if that lookahead can eventually be
shifted if syntactic actions continue from the current context. */
if (!yy_lac_established_)
{
#if ]b4_api_PREFIX[DEBUG
YYCDEBUG << "LAC: initial context established for "
<< yytname_[yytoken] << '\n';
#endif
yy_lac_established_ = true;
return yy_lac_check_ (yytoken);
}
return true;
}
// Discard any previous initial lookahead context.
void
]b4_parser_class[::yy_lac_discard_ (const char* evt)
{
/* Discard any previous initial lookahead context because of Event,
which may be a lookahead change or an invalidation of the currently
established initial context for the current lookahead.
The most common example of a lookahead change is a shift. An example
of both cases is syntax error recovery. That is, a syntax error
occurs when the lookahead is syntactically erroneous for the
currently established initial context, so error recovery manipulates
the parser stacks to try to find a new initial context in which the
current lookahead is syntactically acceptable. If it fails to find
such a context, it discards the lookahead. */
if (yy_lac_established_)
{
YYCDEBUG << "LAC: initial context discarded due to "
<< evt << '\n';
yy_lac_established_ = false;
}
}]])[
// Generate an error message. // Generate an error message.
std::string std::string
]b4_parser_class[::yysyntax_error_ (]dnl ]b4_parser_class[::yysyntax_error_ (]dnl
@@ -1095,7 +1291,7 @@ b4_error_verbose_if([state_type yystate, const symbol_type& yyla],
{]b4_error_verbose_if([[ {]b4_error_verbose_if([[
// Number of reported tokens (one for the "unexpected", one per // Number of reported tokens (one for the "unexpected", one per
// "expected"). // "expected").
size_t yycount = 0; std::ptrdiff_t yycount = 0;
// Its maximum. // Its maximum.
enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
// Arguments of yyformat. // Arguments of yyformat.
@@ -1115,24 +1311,40 @@ b4_error_verbose_if([state_type yystate, const symbol_type& yyla],
a consistent state with a default action. There might have a consistent state with a default action. There might have
been a previous inconsistent state, consistent state with a been a previous inconsistent state, consistent state with a
non-default action, or user semantic action that manipulated non-default action, or user semantic action that manipulated
yyla. (However, yyla is currently not documented for users.) yyla. (However, yyla is currently not documented for users.)]b4_lac_if([[
In the first two cases, it might appear that the current syntax
error should have been detected in the previous state when
yy_lac_check was invoked. However, at that time, there might
have been a different syntax error that discarded a different
initial context during error recovery, leaving behind the
current lookahead.]], [[
- Of course, the expected token list depends on states to have - Of course, the expected token list depends on states to have
correct lookahead information, and it depends on the parser not correct lookahead information, and it depends on the parser not
to perform extra reductions after fetching a lookahead from the to perform extra reductions after fetching a lookahead from the
scanner and before detecting a syntax error. Thus, state scanner and before detecting a syntax error. Thus, state merging
merging (from LALR or IELR) and default reductions corrupt the (from LALR or IELR) and default reductions corrupt the expected
expected token list. However, the list is correct for token list. However, the list is correct for canonical LR with
canonical LR with one exception: it will still contain any one exception: it will still contain any token that will not be
token that will not be accepted due to an error action in a accepted due to an error action in a later state.]])[
later state.
*/ */
if (!yyla.empty ()) if (!yyla.empty ())
{ {
int yytoken = yyla.type_get (); int yytoken = yyla.type_get ();
yyarg[yycount++] = yytname_[yytoken]; yyarg[yycount++] = yytname_[yytoken];]b4_lac_if([[
#if ]b4_api_PREFIX[DEBUG
// Execute LAC once. We don't care if it is succesful, we
// only do it for the sake of debugging output.
if (!yy_lac_established_)
yy_lac_check_ (yytoken);
#endif]])[
int yyn = yypact_[yystate]; int yyn = yypact_[yystate];
if (!yy_pact_value_is_default_ (yyn)) if (!yy_pact_value_is_default_ (yyn))
{ {]b4_lac_if([[
for (int yyx = 0; yyx < yyntokens_; ++yyx)
if (yyx != yyterror_ && yy_lac_check_(yyx))
{]], [[
/* Start YYX at -YYN if negative to avoid negative indexes in /* Start YYX at -YYN if negative to avoid negative indexes in
YYCHECK. In other words, skip the first -YYN actions for YYCHECK. In other words, skip the first -YYN actions for
this state because they are default actions. */ this state because they are default actions. */
@@ -1143,7 +1355,7 @@ b4_error_verbose_if([state_type yystate, const symbol_type& yyla],
for (int yyx = yyxbegin; yyx < yyxend; ++yyx) for (int yyx = yyxbegin; yyx < yyxend; ++yyx)
if (yycheck_[yyx + yyn] == yyx && yyx != yyterror_ if (yycheck_[yyx + yyn] == yyx && yyx != yyterror_
&& !yy_table_value_is_error_ (yytable_[yyx + yyn])) && !yy_table_value_is_error_ (yytable_[yyx + yyn]))
{ {]])[
if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
{ {
yycount = 1; yycount = 1;
@@ -1174,7 +1386,7 @@ b4_error_verbose_if([state_type yystate, const symbol_type& yyla],
std::string yyres; std::string yyres;
// Argument number. // Argument number.
size_t yyi = 0; std::ptrdiff_t yyi = 0;
for (char const* yyp = yyformat; *yyp; ++yyp) for (char const* yyp = yyformat; *yyp; ++yyp)
if (yyp[0] == '%' && yyp[1] == 's' && yyi < yycount) if (yyp[0] == '%' && yyp[1] == 's' && yyi < yycount)
{ {
@@ -1215,7 +1427,7 @@ b4_error_verbose_if([state_type yystate, const symbol_type& yyla],
i = yystack_.begin (), i = yystack_.begin (),
i_end = yystack_.end (); i_end = yystack_.end ();
i != i_end; ++i) i != i_end; ++i)
*yycdebug_ << ' ' << i->state; *yycdebug_ << ' ' << int (i->state);
*yycdebug_ << '\n'; *yycdebug_ << '\n';
} }
@@ -1223,7 +1435,7 @@ b4_error_verbose_if([state_type yystate, const symbol_type& yyla],
void void
]b4_parser_class[::yy_reduce_print_ (int yyrule) ]b4_parser_class[::yy_reduce_print_ (int yyrule)
{ {
unsigned yylno = yyrline_[yyrule]; int yylno = yyrline_[yyrule];
int yynrhs = yyr2_[yyrule]; int yynrhs = yyr2_[yyrule];
// Print the symbols being reduced, and their result. // Print the symbols being reduced, and their result.
*yycdebug_ << "Reducing stack by rule " << yyrule - 1 *yycdebug_ << "Reducing stack by rule " << yyrule - 1
+146 -135
View File
@@ -1,6 +1,6 @@
# Java skeleton for Bison -*- autoconf -*- # D skeleton for Bison -*- autoconf -*-
# Copyright (C) 2007-2011, 2019 Free Software Foundation, Inc. # Copyright (C) 2007-2012, 2019 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
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@@ -18,12 +18,11 @@
m4_include(b4_skeletonsdir/[d.m4]) m4_include(b4_skeletonsdir/[d.m4])
m4_divert_push(0)dnl b4_output_begin([b4_parser_file_name])
@output(b4_parser_file_name@)@
b4_copyright([Skeleton implementation for Bison LALR(1) parsers in D], b4_copyright([Skeleton implementation for Bison LALR(1) parsers in D],
[2007-2012, 2019]) [2007-2012, 2019])[
b4_percent_define_ifdef([package], [module b4_percent_define_get([package]); ]b4_percent_define_ifdef([package], [module b4_percent_define_get([package]);
])[ ])[
version(D_Version2) { version(D_Version2) {
} else { } else {
@@ -81,68 +80,14 @@ public interface Lexer
void yyerror (]b4_locations_if([b4_location_type[ loc, ]])[string s); void yyerror (]b4_locations_if([b4_location_type[ loc, ]])[string s);
} }
private final struct YYStackElement{ ]b4_locations_if([b4_position_type_if([[
int state;
]b4_yystype[ value;]b4_locations_if(
b4_location_type[[] location;])[
}
private final struct YYStack {
private YYStackElement[] stack = [];
public final @@property ulong height()
{
return stack.length;
}
public final void push (int state, ]b4_yystype[ value]dnl
b4_locations_if([, ref ]b4_location_type[ loc])[)
{
stack ~= YYStackElement(state, value]b4_locations_if([, loc])[);
}
public final void pop ()
{
pop (1);
}
public final void pop (int num)
{
stack.length -= num;
}
public final int stateAt (int i)
{
return stack[$-i-1].state;
}
]b4_locations_if([[public final ref ]b4_location_type[ locationAt (int i)
{
return stack[$-i-1].location;
}
]])[public final ref ]b4_yystype[ valueAt (int i)
{
return stack[$-i-1].value;
}
// Print the state stack on the debug stream.
public final void print (File stream)
{
stream.write ("Stack now");
for (int i = 0; i < stack.length; i++)
stream.write (" %d", stack[i].state);
stream.writeln ();
}
}
]b4_locations_if(b4_position_type_if([[[
static assert(__traits(compiles, static assert(__traits(compiles,
(new ]b4_position_type[[1])[0]=(new ]b4_position_type[[1])[0]), (new ]b4_position_type[[1])[0]=(new ]b4_position_type[[1])[0]),
"struct/class ]b4_position_type[ must be default-constructible " "struct/class ]b4_position_type[ must be default-constructible "
"and assignable"); "and assignable");
static assert(__traits(compiles, (new string[1])[0]=(new ]b4_position_type[).toString()), static assert(__traits(compiles, (new string[1])[0]=(new ]b4_position_type[).toString()),
"error: struct/class ]b4_position_type[ must have toString method"); "error: struct/class ]b4_position_type[ must have toString method");
]]], [[ ]], [[
/** /**
* A struct denoting a point in the input.*/ * A struct denoting a point in the input.*/
public struct ]b4_position_type[ { public struct ]b4_position_type[ {
@@ -152,15 +97,18 @@ public struct ]b4_position_type[ {
/** The line number within an input file. */ /** The line number within an input file. */
public int line = 1; public int line = 1;
/** The name of the input file. */ /** The name of the input file. */
public string filename = "(unspecified file)"; public string filename = null;
/** /**
* Return a string representation of the position. */ * A string representation of the position. */
public string toString() const { public string toString() const {
return format("%s:%d.%d", filename, line, column); if (filename)
return format("%s:%d.%d", filename, line, column);
else
return format("%d.%d", line, column);
} }
} }
]])b4_location_type_if([[[ ]])b4_location_type_if([[
static assert(__traits(compiles, (new ]b4_location_type[((new ]b4_position_type[[1])[0]))) && static assert(__traits(compiles, (new ]b4_location_type[((new ]b4_position_type[[1])[0]))) &&
__traits(compiles, (new ]b4_location_type[((new ]b4_position_type[[1])[0], (new ]b4_position_type[[1])[0]))), __traits(compiles, (new ]b4_location_type[((new ]b4_position_type[[1])[0], (new ]b4_position_type[[1])[0]))),
"error: struct/class ]b4_location_type[ must have " "error: struct/class ]b4_location_type[ must have "
@@ -174,7 +122,7 @@ static assert(__traits(compiles, (new ]b4_location_type[[1])[0].begin=(new ]b4_l
static assert(__traits(compiles, (new string[1])[0]=(new ]b4_location_type[[1])[0].toString()), static assert(__traits(compiles, (new string[1])[0]=(new ]b4_location_type[[1])[0].toString()),
"error: struct/class ]b4_location_type[ must have toString method."); "error: struct/class ]b4_location_type[ must have toString method.");
private immutable bool yy_location_is_class = !__traits(compiles, *(new ]b4_location_type[((new ]b4_position_type[[1])[0])));]]], [[ private immutable bool yy_location_is_class = !__traits(compiles, *(new ]b4_location_type[((new ]b4_position_type[[1])[0])));]], [[
/** /**
* 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.
@@ -196,6 +144,9 @@ public class ]b4_location_type[
this.begin = this.end = loc; this.begin = this.end = loc;
} }
public this () {
}
/** /**
* 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.
@@ -207,20 +158,25 @@ public class ]b4_location_type[
} }
/** /**
* Return a representation of the location. For this to be correct, * A representation of the location. For this to be correct,
* <code>]b4_position_type[</code> should override the <code>toString</code> * <code>]b4_position_type[</code> should override the <code>toString</code>
* method. */ * method. */
public const string toString () const { public override string toString () const {
if (begin==end) auto end_col = 0 < end.column ? end.column - 1 : 0;
return begin.toString (); auto res = begin.toString ();
else if (end.filename && begin.filename != end.filename)
return begin.toString () ~ "-" ~ end.toString (); res ~= "-" ~ format("%s:%d.%d", end.filename, end.line, end_col);
else if (begin.line < end.line)
res ~= "-" ~ format("%d.%d", end.line, end_col);
else if (begin.column < end_col)
res ~= "-" ~ format("%d", end_col);
return res;
} }
} }
private immutable bool yy_location_is_class = true; private immutable bool yy_location_is_class = true;
]]))m4_ifdef([b4_user_union_members], [private union YYSemanticType ]])])m4_ifdef([b4_user_union_members], [private union YYSemanticType
{ {
b4_user_union_members b4_user_union_members
};], };],
@@ -261,29 +217,27 @@ b4_user_union_members
]b4_lexer_if([[ ]b4_lexer_if([[
/** /**
* Instantiates the Bison-generated parser. * Instantiate the Bison-generated parser.
*/ */
public this] (b4_parse_param_decl([b4_lex_param_decl])[) { public this] (b4_parse_param_decl([b4_lex_param_decl])[) {
this.yylexer = new YYLexer(]b4_lex_param_call[); this (new YYLexer(]b4_lex_param_call[));
this.yyDebugStream = stderr;
]b4_parse_param_cons[
} }
]])[ ]])[
/** /**
* Instantiates the Bison-generated parser. * Instantiate the Bison-generated parser.
* @@param yylexer The scanner that will supply tokens to the parser. * @@param yylexer The scanner that will supply tokens to the parser.
*/ */
]b4_lexer_if([[protected]], [[public]]) [this (]b4_parse_param_decl([[Lexer yylexer]])[) { ]b4_lexer_if([[protected]], [[public]]) [this (]b4_parse_param_decl([[Lexer yylexer]])[) {
this.yylexer = yylexer; this.yylexer = yylexer;]b4_parse_trace_if([[
this.yyDebugStream = stderr; this.yyDebugStream = stderr;]])[
]b4_parse_param_cons[ ]b4_parse_param_cons[
} }
]b4_parse_trace_if([[
private File yyDebugStream; private File yyDebugStream;
/** /**
* Return the <tt>File</tt> on which the debugging output is * The <tt>File</tt> on which the debugging output is
* printed. * printed.
*/ */
public File getDebugStream () { return yyDebugStream; } public File getDebugStream () { return yyDebugStream; }
@@ -309,16 +263,17 @@ b4_user_union_members
*/ */
public final void setDebugLevel(int level) { yydebug = level; } public final void setDebugLevel(int level) { yydebug = level; }
protected final void yycdebug (string s) {
if (0 < yydebug)
yyDebugStream.writeln (s);
}
]])[
private final int yylex () { private final int yylex () {
return yylexer.yylex (); return yylexer.yylex ();
} }
protected final void yyerror (]b4_locations_if(ref [b4_location_type[ loc, ]])[string s) { protected final void yyerror (]b4_locations_if(ref [b4_location_type[ loc, ]])[string s) {
yylexer.yyerror (]b4_locations_if([loc, ])[s); yylexer.yyerror (]b4_locations_if([loc, ])[s);
}]
[protected final void yycdebug (string s) {
if (yydebug > 0)
yyDebugStream.writeln (s);
} }
/** /**
@@ -345,11 +300,11 @@ b4_user_union_members
private static immutable int YYERRLAB1 = 7; private static immutable int YYERRLAB1 = 7;
private static immutable int YYRETURN = 8; private static immutable int YYRETURN = 8;
]b4_locations_if([ ]b4_locations_if([
private static immutable YYSemanticType yy_semantic_null = cast(YYSemanticType)null;])[ private static immutable YYSemanticType yy_semantic_null;])[
private int yyerrstatus_ = 0; private int yyerrstatus_ = 0;
/** /**
* Return whether error recovery is being done. In this state, the parser * 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 bool recovering () public final bool recovering ()
@@ -373,7 +328,8 @@ b4_user_union_members
else else
yyval = yystack.valueAt (0); yyval = yystack.valueAt (0);
yy_reduce_print (yyn, yystack); ]b4_parse_trace_if([[
yy_reduce_print (yyn, yystack);]])[
switch (yyn) switch (yyn)
{ {
@@ -381,7 +337,8 @@ b4_user_union_members
default: break; default: break;
} }
yy_symbol_print ("-> $$ =", yyr1_[yyn], yyval]b4_locations_if([, yyloc])[); ]b4_parse_trace_if([[
yy_symbol_print ("-> $$ =", yyr1_[yyn], yyval]b4_locations_if([, yyloc])[);]])[
yystack.pop (yylen); yystack.pop (yylen);
yylen = 0; yylen = 0;
@@ -429,12 +386,12 @@ b4_user_union_members
return yyr; return yyr;
} }
} }
else if (yystr=="$end") else if (yystr == "$end")
return "end of input"; return "end of input";
return yystr; return yystr;
} }
]b4_parse_trace_if([[
/*--------------------------------. /*--------------------------------.
| Print this symbol on YYOUTPUT. | | Print this symbol on YYOUTPUT. |
`--------------------------------*/ `--------------------------------*/
@@ -443,11 +400,11 @@ b4_user_union_members
ref ]b4_yystype[ yyvaluep]dnl ref ]b4_yystype[ yyvaluep]dnl
b4_locations_if([, ref ]b4_location_type[ yylocationp])[) b4_locations_if([, ref ]b4_location_type[ yylocationp])[)
{ {
if (yydebug > 0) { if (0 < yydebug) {
string message = s ~ (yytype < yyntokens_ ? " token " : " nterm ") string message = s ~ (yytype < yyntokens_ ? " token " : " nterm ")
~ yytname_[yytype] ~ " ("]b4_locations_if([ ~ yytname_[yytype] ~ " ("]b4_locations_if([
~ yylocationp.toString() ~ ": "])[; ~ yylocationp.toString() ~ ": "])[;
static if (__traits(compiles, message~=yyvaluep.toString ())) static if (__traits(compiles, message ~= yyvaluep.toString ()))
message ~= yyvaluep.toString (); message ~= yyvaluep.toString ();
else else
message ~= format ("%s", &yyvaluep); message ~= format ("%s", &yyvaluep);
@@ -455,7 +412,7 @@ b4_locations_if([, ref ]b4_location_type[ yylocationp])[)
yycdebug (message); yycdebug (message);
} }
} }
]])[
/** /**
* 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.
@@ -490,9 +447,9 @@ b4_locations_if([, ref ]b4_location_type[ yylocationp])[)
/// Semantic value of the lookahead. /// Semantic value of the lookahead.
]b4_yystype[ yylval; ]b4_yystype[ yylval;
int yyresult; int yyresult;]b4_parse_trace_if([[
yycdebug ("Starting parse\n"); yycdebug ("Starting parse\n");]])[
yyerrstatus_ = 0; yyerrstatus_ = 0;
]m4_ifdef([b4_initial_action], [ ]m4_ifdef([b4_initial_action], [
@@ -512,10 +469,10 @@ m4_popdef([b4_at_dollar])])dnl
{ {
/* New state. Unlike in the C/C++ skeletons, the state is already /* New state. Unlike in the C/C++ skeletons, the state is already
pushed when we come here. */ pushed when we come here. */
case YYNEWSTATE: case YYNEWSTATE:]b4_parse_trace_if([[
yycdebug (format("Entering state %d\n", yystate)); yycdebug (format("Entering state %d\n", yystate));
if (yydebug > 0) if (0 < yydebug)
yystack.print (yyDebugStream); yystack.print (yyDebugStream);]])[
/* Accept? */ /* Accept? */
if (yystate == yyfinal_) if (yystate == yyfinal_)
@@ -531,8 +488,8 @@ m4_popdef([b4_at_dollar])])dnl
/* Read a lookahead token. */ /* Read a lookahead token. */
if (yychar == yyempty_) if (yychar == yyempty_)
{ {]b4_parse_trace_if([[
yycdebug ("Reading a token: "); yycdebug ("Reading a token: ");]])[
yychar = yylex ();]b4_locations_if([[ yychar = yylex ();]b4_locations_if([[
static if (yy_location_is_class) { static if (yy_location_is_class) {
yylloc = new ]b4_location_type[(yylexer.startPos, yylexer.endPos); yylloc = new ]b4_location_type[(yylexer.startPos, yylexer.endPos);
@@ -543,17 +500,9 @@ m4_popdef([b4_at_dollar])])dnl
} }
/* Convert token to internal form. */ /* Convert token to internal form. */
if (yychar <= YYTokenType.EOF) yytoken = yytranslate_ (yychar);]b4_parse_trace_if([[
{ yy_symbol_print ("Next token is",
yychar = yytoken = YYTokenType.EOF; yytoken, yylval]b4_locations_if([, yylloc])[);]])[
yycdebug ("Now at end of input.\n");
}
else
{
yytoken = yytranslate_ (yychar);
yy_symbol_print ("Next token is",
yytoken, yylval]b4_locations_if([, yylloc])[);
}
/* If the proper action on seeing token YYTOKEN is to reduce or to /* If the proper action on seeing token YYTOKEN is to reduce or to
detect an error, take that action. */ detect an error, take that action. */
@@ -574,9 +523,9 @@ m4_popdef([b4_at_dollar])])dnl
} }
else else
{ {
/* Shift the lookahead token. */ /* Shift the lookahead token. */]b4_parse_trace_if([[
yy_symbol_print ("Shifting", yytoken, yy_symbol_print ("Shifting", yytoken,
yylval]b4_locations_if([, yylloc])[); yylval]b4_locations_if([, yylloc])[);]])[
/* Discard the token being shifted. */ /* Discard the token being shifted. */
yychar = yyempty_; yychar = yyempty_;
@@ -685,9 +634,9 @@ m4_popdef([b4_at_dollar])])dnl
]b4_locations_if([ yyerrloc = yystack.locationAt (0);])[ ]b4_locations_if([ yyerrloc = yystack.locationAt (0);])[
yystack.pop (); yystack.pop ();
yystate = yystack.stateAt (0); yystate = yystack.stateAt (0);]b4_parse_trace_if([[
if (yydebug > 0) if (0 < yydebug)
yystack.print (yyDebugStream); yystack.print (yyDebugStream);]])[
} }
]b4_locations_if([ ]b4_locations_if([
@@ -697,9 +646,9 @@ m4_popdef([b4_at_dollar])])dnl
yyloc = yylloc_from_stack (yystack, 2); yyloc = yylloc_from_stack (yystack, 2);
yystack.pop (2);])[ yystack.pop (2);])[
/* Shift the error token. */ /* Shift the error token. */]b4_parse_trace_if([[
yy_symbol_print ("Shifting", yystos_[yyn], yy_symbol_print ("Shifting", yystos_[yyn],
yylval]b4_locations_if([, yyloc])[); yylval]b4_locations_if([, yyloc])[);]])[
yystate = yyn; yystate = yyn;
yystack.push (yyn, yylval]b4_locations_if([, yyloc])[); yystack.push (yyn, yylval]b4_locations_if([, yyloc])[);
@@ -837,6 +786,7 @@ m4_popdef([b4_at_dollar])])dnl
]b4_tname[ ]b4_tname[
@}; @};
]b4_parse_trace_if([[
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
private static immutable ]b4_int_type_for([b4_rline])[[] yyrline_ = private static immutable ]b4_int_type_for([b4_rline])[[] yyrline_ =
@{ @{
@@ -862,19 +812,25 @@ m4_popdef([b4_at_dollar])])dnl
]b4_rhs_value(yynrhs, yyi + 1)b4_locations_if([, ]b4_rhs_value(yynrhs, yyi + 1)b4_locations_if([,
b4_rhs_location(yynrhs, yyi + 1)])[); b4_rhs_location(yynrhs, yyi + 1)])[);
} }
]])[
/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
private static immutable ]b4_int_type_for([b4_translate])[[] yytranslate_table_ =
@{
]b4_translate[
@};
private static ]b4_int_type_for([b4_translate])[ yytranslate_ (int t) private static ]b4_int_type_for([b4_translate])[ yytranslate_ (int t)
{ {
if (t >= 0 && t <= yyuser_token_number_max_) ]b4_api_token_raw_if(
return yytranslate_table_[t]; [[ import std.conv : to;
return to!byte (t);]],
[[ /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
immutable ]b4_int_type_for([b4_translate])[[] translate_table =
@{
]b4_translate[
@};
if (t <= 0)
return YYTokenType.EOF;
else if (t <= yyuser_token_number_max_)
return translate_table[t];
else else
return yyundef_token_; return yyundef_token_;]])[
} }
private static immutable int yylast_ = ]b4_last[; private static immutable int yylast_ = ]b4_last[;
@@ -888,9 +844,64 @@ m4_popdef([b4_at_dollar])])dnl
private static immutable int yyuser_token_number_max_ = ]b4_user_token_number_max[; private static immutable int yyuser_token_number_max_ = ]b4_user_token_number_max[;
private static immutable int yyundef_token_ = ]b4_undef_token_number[; private static immutable int yyundef_token_ = ]b4_undef_token_number[;
]/* User implementation code. */ private final struct YYStackElement {
b4_percent_code_get[]dnl int state;
]b4_yystype[ value;]b4_locations_if(
b4_location_type[[] location;])[
}
private final struct YYStack {
private YYStackElement[] stack = [];
public final @@property ulong height()
{
return stack.length;
}
public final void push (int state, ]b4_yystype[ value]dnl
b4_locations_if([, ref ]b4_location_type[ loc])[)
{
stack ~= YYStackElement(state, value]b4_locations_if([, loc])[);
}
public final void pop ()
{
pop (1);
}
public final void pop (int num)
{
stack.length -= num;
}
public final int stateAt (int i)
{
return stack[$-i-1].state;
}
]b4_locations_if([[
public final ref ]b4_location_type[ locationAt (int i)
{
return stack[$-i-1].location;
}]])[
public final ref ]b4_yystype[ valueAt (int i)
{
return stack[$-i-1].value;
}
]b4_parse_trace_if([[
// Print the state stack on the debug stream.
public final void print (File stream)
{
stream.write ("Stack now");
for (int i = 0; i < stack.length; i++)
stream.write (" ", stack[i].state);
stream.writeln ();
}]])[
}
/* User implementation code. */
]b4_percent_code_get[
} }
b4_epilogue[]dnl ]b4_epilogue[]dnl
m4_divert_pop(0)dnl b4_output_end
+122 -133
View File
@@ -1,4 +1,4 @@
# Java skeleton for Bison -*- autoconf -*- # Java skeleton for Bison -*- autoconf -*-
# Copyright (C) 2007-2015, 2018-2019 Free Software Foundation, Inc. # Copyright (C) 2007-2015, 2018-2019 Free Software Foundation, Inc.
@@ -19,10 +19,6 @@ m4_include(b4_skeletonsdir/[java.m4])
b4_defines_if([b4_complain([%defines does not make sense in Java])]) b4_defines_if([b4_complain([%defines does not make sense in Java])])
# We do not depend on %debug in Java, but pacify warnings about
# non-used flags.
b4_parse_trace_if([0], [0])
m4_define([b4_symbol_no_destructor_assert], m4_define([b4_symbol_no_destructor_assert],
[b4_symbol_if([$1], [has_destructor], [b4_symbol_if([$1], [has_destructor],
[b4_complain_at(m4_unquote(b4_symbol([$1], [destructor_loc])), [b4_complain_at(m4_unquote(b4_symbol([$1], [destructor_loc])),
@@ -70,19 +66,19 @@ m4_define([b4_define_state],[[
/* Error handling. */ /* Error handling. */
int yynerrs_ = 0; int yynerrs_ = 0;
]b4_locations_if([/* The location where the error started. */ ]b4_locations_if([[/* The location where the error started. */
b4_location_type yyerrloc = null; ]b4_location_type[ yyerrloc = null;
/* Location. */ /* Location. */
b4_location_type yylloc = new b4_location_type (null, null);])[ ]b4_location_type[ yylloc = new ]b4_location_type[ (null, null);]])[
/* Semantic value of the lookahead. */ /* Semantic value of the lookahead. */
]b4_yystype[ yylval = null; ]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-2015, 2018])[ [2007-2015, 2018-2019])[
]b4_percent_define_ifdef([package], [package b4_percent_define_get([package]);[ ]b4_percent_define_ifdef([package], [package b4_percent_define_get([package]);[
]])[ ]])[
]b4_user_pre_prologue[ ]b4_user_pre_prologue[
@@ -103,7 +99,7 @@ b4_output_begin([b4_parser_file_name])[
private boolean yyErrorVerbose = true; private boolean yyErrorVerbose = true;
/** /**
* Return whether verbose error messages are enabled. * Whether verbose error messages are enabled.
*/ */
public final boolean getErrorVerbose() { return yyErrorVerbose; } public final boolean getErrorVerbose() { return yyErrorVerbose; }
@@ -165,12 +161,12 @@ b4_locations_if([[
} }
} }
]]) ]])[
b4_locations_if([[ ]b4_locations_if([[
private ]b4_location_type[ yylloc (YYStack rhs, int n) private ]b4_location_type[ yylloc (YYStack rhs, int n)
{ {
if (n > 0) if (0 < n)
return new ]b4_location_type[ (rhs.locationAt (n-1).begin, rhs.locationAt (0).end); return new ]b4_location_type[ (rhs.locationAt (n-1).begin, rhs.locationAt (0).end);
else else
return new ]b4_location_type[ (rhs.locationAt (0).end); return new ]b4_location_type[ (rhs.locationAt (0).end);
@@ -220,10 +216,11 @@ b4_locations_if([[
* 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);
} }
b4_lexer_if([[private class YYLexer implements Lexer { ]b4_lexer_if([[
private class YYLexer implements Lexer {
]b4_percent_code_get([[lexer]])[ ]b4_percent_code_get([[lexer]])[
} }
@@ -231,10 +228,10 @@ b4_locations_if([[
* 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_lexer_if([[ ]b4_parse_param_vars[
]b4_lexer_if([[
/** /**
* Instantiates the Bison-generated parser. * Instantiates the Bison-generated parser.
*/ */
@@ -244,24 +241,24 @@ b4_lexer_if([[
this.yylexer = new YYLexer(]b4_lex_param_call[); this.yylexer = new YYLexer(]b4_lex_param_call[);
]b4_parse_param_cons[ ]b4_parse_param_cons[
} }
]]) ]])[
/** /**
* Instantiates the Bison-generated parser. * Instantiates the Bison-generated parser.
* @@param yylexer The scanner that will supply tokens to the parser. * @@param yylexer The scanner that will supply tokens to the parser.
*/ */
b4_lexer_if([[protected]], [[public]]) b4_parser_class[ (]b4_parse_param_decl([[Lexer yylexer]])[) ]b4_maybe_throws([b4_init_throws])[ ]b4_lexer_if([[protected]], [[public]]) b4_parser_class[ (]b4_parse_param_decl([[Lexer yylexer]])[) ]b4_maybe_throws([b4_init_throws])[
{ {
]b4_percent_code_get([[init]])[ ]b4_percent_code_get([[init]])[
this.yylexer = yylexer; this.yylexer = yylexer;
]b4_parse_param_cons[ ]b4_parse_param_cons[
} }
]b4_parse_trace_if([[
private java.io.PrintStream yyDebugStream = System.err; private java.io.PrintStream yyDebugStream = System.err;
/** /**
* Return the <tt>PrintStream</tt> on which the debugging output is * The <tt>PrintStream</tt> on which the debugging output is printed.
* printed.
*/ */
public final java.io.PrintStream getDebugStream () { return yyDebugStream; } public final java.io.PrintStream getDebugStream () { return yyDebugStream; }
@@ -285,6 +282,7 @@ b4_lexer_if([[
* @@param level The verbosity level for debugging output. * @@param level The verbosity level for debugging output.
*/ */
public final void setDebugLevel(int level) { yydebug = level; } public final void setDebugLevel(int level) { yydebug = level; }
]])[
/** /**
* Print an error message via the lexer. * Print an error message via the lexer.
@@ -314,12 +312,12 @@ b4_lexer_if([[
public final void yyerror (]b4_position_type[ pos, String msg) public final void yyerror (]b4_position_type[ pos, String msg)
{ {
yylexer.yyerror (new ]b4_location_type[ (pos), msg); yylexer.yyerror (new ]b4_location_type[ (pos), msg);
}]]) }]])[
]b4_parse_trace_if([[
[protected final void yycdebug (String s) { protected final void yycdebug (String s) {
if (yydebug > 0) if (0 < yydebug)
yyDebugStream.println (s); yyDebugStream.println (s);
} }]])[
private final class YYStack { private final class YYStack {
private int[] stateStack = new int[16]; private int[] stateStack = new int[16];
@@ -360,7 +358,7 @@ b4_lexer_if([[
public final void pop (int num) { public final void pop (int num) {
// Avoid memory leaks... garbage collection is a white lie! // Avoid memory leaks... garbage collection is a white lie!
if (num > 0) { if (0 < num) {
java.util.Arrays.fill (valueStack, height - num + 1, height + 1, null); java.util.Arrays.fill (valueStack, height - num + 1, height + 1, null);
]b4_locations_if([[java.util.Arrays.fill (locStack, height - num + 1, height + 1, null);]])[ ]b4_locations_if([[java.util.Arrays.fill (locStack, height - num + 1, height + 1, null);]])[
} }
@@ -430,10 +428,9 @@ b4_lexer_if([[
private int yyerrstatus_ = 0; private int yyerrstatus_ = 0;
]b4_push_if([dnl ]b4_push_if([b4_define_state])[
b4_define_state])[
/** /**
* Return whether error recovery is being done. In this state, the parser * 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.
*/ */
@@ -446,7 +443,7 @@ b4_define_state])[
* @@param yystate the current state * @@param yystate the current state
* @@param yysym the nonterminal to push on the stack * @@param yysym the nonterminal to push on the stack
*/ */
private int yy_lr_goto_state_ (int yystate, int yysym) private int yyLRGotoState (int yystate, int yysym)
{ {
int yyr = yypgoto_[yysym - yyntokens_] + yystate; int yyr = yypgoto_[yysym - yyntokens_] + yystate;
if (0 <= yyr && yyr <= yylast_ && yycheck_[yyr] == yystate) if (0 <= yyr && yyr <= yylast_ && yycheck_[yyr] == yystate)
@@ -457,35 +454,30 @@ b4_define_state])[
private int yyaction (int yyn, YYStack yystack, int yylen) ]b4_maybe_throws([b4_throws])[ private int yyaction (int yyn, YYStack yystack, int yylen) ]b4_maybe_throws([b4_throws])[
{ {
]b4_yystype[ yyval;
]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
users should not rely upon it. */ users should not rely upon it. */
if (yylen > 0) ]b4_yystype[ yyval = (0 < yylen) ? yystack.valueAt (yylen - 1) : yystack.valueAt (0);
yyval = yystack.valueAt (yylen - 1); ]b4_locations_if([b4_location_type[ yyloc = yylloc (yystack, yylen);]])[]b4_parse_trace_if([[
else
yyval = yystack.valueAt (0);
yy_reduce_print (yyn, yystack); yyReducePrint (yyn, yystack);]])[
switch (yyn) switch (yyn)
{ {
]b4_user_actions[ ]b4_user_actions[
default: break; default: break;
} }]b4_parse_trace_if([[
yy_symbol_print ("-> $$ =", yyr1_[yyn], yyval]b4_locations_if([, yyloc])[); yySymbolPrint ("-> $$ =", yyr1_[yyn], yyval]b4_locations_if([, yyloc])[);]])[
yystack.pop (yylen); yystack.pop (yylen);
yylen = 0; yylen = 0;
/* Shift the result of the reduction. */ /* Shift the result of the reduction. */
int yystate = yy_lr_goto_state_ (yystack.stateAt (0), yyr1_[yyn]); int yystate = yyLRGotoState (yystack.stateAt (0), yyr1_[yyn]);
yystack.push (yystate, yyval]b4_locations_if([, yyloc])[); yystack.push (yystate, yyval]b4_locations_if([, yyloc])[);
return YYNEWSTATE; return YYNEWSTATE;
} }
@@ -526,21 +518,20 @@ b4_define_state])[
return yystr; return yystr;
} }
]])[ ]])[
]b4_parse_trace_if([[
/*--------------------------------. /*--------------------------------.
| Print this symbol on YYOUTPUT. | | Print this symbol on YYOUTPUT. |
`--------------------------------*/ `--------------------------------*/
private void yy_symbol_print (String s, int yytype, private void yySymbolPrint (String s, int yytype,
]b4_yystype[ yyvaluep]dnl ]b4_yystype[ yyvaluep]dnl
b4_locations_if([, Object yylocationp])[) b4_locations_if([, Object yylocationp])[)
{ {
if (yydebug > 0)
yycdebug (s + (yytype < yyntokens_ ? " token " : " nterm ") yycdebug (s + (yytype < yyntokens_ ? " token " : " nterm ")
+ yytname_[yytype] + " ("]b4_locations_if([ + yytname_[yytype] + " ("]b4_locations_if([
+ yylocationp + ": "])[ + yylocationp + ": "])[
+ (yyvaluep == null ? "(null)" : yyvaluep.toString ()) + ")"); + (yyvaluep == null ? "(null)" : yyvaluep.toString ()) + ")");
} }]])[
]b4_push_if([],[[ ]b4_push_if([],[[
/** /**
@@ -550,7 +541,7 @@ b4_define_state])[
* @@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([ ]b4_push_if([
/** /**
* Push Parse input from external lexer * Push Parse input from external lexer
@@ -567,8 +558,8 @@ b4_define_state])[
]b4_locations_if([/* @@$. */ ]b4_locations_if([/* @@$. */
b4_location_type yyloc;])[ b4_location_type yyloc;])[
]b4_push_if([],[[ ]b4_push_if([],[[
]b4_define_state[ ]b4_define_state[]b4_parse_trace_if([[
yycdebug ("Starting parse\n"); yycdebug ("Starting parse\n");]])[
yyerrstatus_ = 0; yyerrstatus_ = 0;
/* Initialize the stack. */ /* Initialize the stack. */
@@ -587,8 +578,8 @@ b4_dollar_popdef[]dnl
b4_dollar_pushdef([yylval], [], [], [yylloc])dnl b4_dollar_pushdef([yylval], [], [], [yylloc])dnl
b4_user_initial_action b4_user_initial_action
b4_dollar_popdef[]dnl b4_dollar_popdef[]dnl
])[ ])[]b4_parse_trace_if([[
yycdebug ("Starting parse\n"); yycdebug ("Starting parse\n");]])[
yyerrstatus_ = 0; yyerrstatus_ = 0;
} else } else
label = YYGETTOKEN; label = YYGETTOKEN;
@@ -600,10 +591,10 @@ b4_dollar_popdef[]dnl
{ {
/* New state. Unlike in the C/C++ skeletons, the state is already /* New state. Unlike in the C/C++ skeletons, the state is already
pushed when we come here. */ pushed when we come here. */
case YYNEWSTATE: case YYNEWSTATE:]b4_parse_trace_if([[
yycdebug ("Entering state " + yystate + "\n"); yycdebug ("Entering state " + yystate + "\n");
if (yydebug > 0) if (0 < yydebug)
yystack.print (yyDebugStream); yystack.print (yyDebugStream);]])[
/* Accept? */ /* Accept? */
if (yystate == yyfinal_) if (yystate == yyfinal_)
@@ -612,7 +603,7 @@ b4_dollar_popdef[]dnl
/* Take a decision. First try without lookahead. */ /* Take a decision. First try without lookahead. */
yyn = yypact_[yystate]; yyn = yypact_[yystate];
if (yy_pact_value_is_default_ (yyn)) if (yyPactValueIsDefault (yyn))
{ {
label = YYDEFAULT; label = YYDEFAULT;
break; break;
@@ -625,14 +616,13 @@ b4_dollar_popdef[]dnl
{ {
]b4_push_if([[ ]b4_push_if([[
if (!push_token_consumed) if (!push_token_consumed)
return YYPUSH_MORE; return YYPUSH_MORE;]b4_parse_trace_if([[
yycdebug ("Reading a token: "); yycdebug ("Reading a token: ");]])[
yychar = yylextoken; yychar = yylextoken;
yylval = yylexval;]b4_locations_if([ yylval = yylexval;]b4_locations_if([
yylloc = yylexloc;])[ yylloc = yylexloc;])[
push_token_consumed = false;]])[ push_token_consumed = false;]], [b4_parse_trace_if([[
]b4_push_if([],[[ yycdebug ("Reading a token: ");]])[
yycdebug ("Reading a token: ");
yychar = yylexer.yylex (); yychar = yylexer.yylex ();
yylval = yylexer.getLVal ();]b4_locations_if([ yylval = yylexer.getLVal ();]b4_locations_if([
yylloc = new b4_location_type (yylexer.getStartPos (), yylloc = new b4_location_type (yylexer.getStartPos (),
@@ -641,17 +631,9 @@ b4_dollar_popdef[]dnl
} }
/* Convert token to internal form. */ /* Convert token to internal form. */
if (yychar <= Lexer.EOF) yytoken = yytranslate_ (yychar);]b4_parse_trace_if([[
{ yySymbolPrint ("Next token is", yytoken,
yychar = yytoken = Lexer.EOF; yylval]b4_locations_if([, yylloc])[);]])[
yycdebug ("Now at end of input.\n");
}
else
{
yytoken = yytranslate_ (yychar);
yy_symbol_print ("Next token is", yytoken,
yylval]b4_locations_if([, yylloc])[);
}
/* If the proper action on seeing token YYTOKEN is to reduce or to /* If the proper action on seeing token YYTOKEN is to reduce or to
detect an error, take that action. */ detect an error, take that action. */
@@ -662,7 +644,7 @@ b4_dollar_popdef[]dnl
/* <= 0 means reduce or error. */ /* <= 0 means reduce or error. */
else if ((yyn = yytable_[yyn]) <= 0) else if ((yyn = yytable_[yyn]) <= 0)
{ {
if (yy_table_value_is_error_ (yyn)) if (yyTableValueIsError (yyn))
label = YYERRLAB; label = YYERRLAB;
else else
{ {
@@ -673,10 +655,10 @@ b4_dollar_popdef[]dnl
else else
{ {
/* Shift the lookahead token. */ /* Shift the lookahead token. */]b4_parse_trace_if([[
yy_symbol_print ("Shifting", yytoken, yySymbolPrint ("Shifting", yytoken,
yylval]b4_locations_if([, yylloc])[); yylval]b4_locations_if([, yylloc])[);
]])[
/* Discard the token being shifted. */ /* Discard the token being shifted. */
yychar = yyempty_; yychar = yyempty_;
@@ -727,17 +709,17 @@ b4_dollar_popdef[]dnl
]b4_locations_if([yyerrloc = yylloc;])[ ]b4_locations_if([yyerrloc = yylloc;])[
if (yyerrstatus_ == 3) if (yyerrstatus_ == 3)
{ {
/* If just tried and failed to reuse lookahead token after an /* If just tried and failed to reuse lookahead token after an
error, discard it. */ error, discard it. */
if (yychar <= Lexer.EOF) if (yychar <= Lexer.EOF)
{ {
/* Return failure if at end of input. */ /* Return failure if at end of input. */
if (yychar == Lexer.EOF) if (yychar == Lexer.EOF)
]b4_push_if([{label = YYABORT; break;}],[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
@@ -749,7 +731,6 @@ b4_dollar_popdef[]dnl
| 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);])[
/* Do not reclaim the symbols of the rule which action triggered /* Do not reclaim the symbols of the rule which action triggered
this YYERROR. */ this YYERROR. */
@@ -768,7 +749,7 @@ b4_dollar_popdef[]dnl
for (;;) for (;;)
{ {
yyn = yypact_[yystate]; yyn = yypact_[yystate];
if (!yy_pact_value_is_default_ (yyn)) if (!yyPactValueIsDefault (yyn))
{ {
yyn += yyterror_; yyn += yyterror_;
if (0 <= yyn && yyn <= yylast_ && yycheck_[yyn] == yyterror_) if (0 <= yyn && yyn <= yylast_ && yycheck_[yyn] == yyterror_)
@@ -786,9 +767,9 @@ b4_dollar_popdef[]dnl
]b4_locations_if([yyerrloc = yystack.locationAt (0);])[ ]b4_locations_if([yyerrloc = yystack.locationAt (0);])[
yystack.pop (); yystack.pop ();
yystate = yystack.stateAt (0); yystate = yystack.stateAt (0);]b4_parse_trace_if([[
if (yydebug > 0) if (0 < yydebug)
yystack.print (yyDebugStream); yystack.print (yyDebugStream);]])[
} }
if (label == YYABORT) if (label == YYABORT)
@@ -802,9 +783,9 @@ b4_dollar_popdef[]dnl
yyloc = yylloc (yystack, 2); yyloc = yylloc (yystack, 2);
yystack.pop (2);])[ yystack.pop (2);])[
/* Shift the error token. */ /* Shift the error token. */]b4_parse_trace_if([[
yy_symbol_print ("Shifting", yystos_[yyn], yySymbolPrint ("Shifting", yystos_[yyn],
yylval]b4_locations_if([, yyloc])[); yylval]b4_locations_if([, yyloc])[);]])[
yystate = yyn; yystate = yyn;
yystack.push (yyn, yylval]b4_locations_if([, yyloc])[); yystack.push (yyn, yylval]b4_locations_if([, yyloc])[);
@@ -870,9 +851,9 @@ b4_dollar_popdef[]dnl
{ {
return push_parse (yylextoken, yylexval, new b4_location_type (yylexpos)); return push_parse (yylextoken, yylexval, new b4_location_type (yylexpos));
} }
])[]]) ])[]])[
b4_both_if([[ ]b4_both_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.
@@ -881,21 +862,21 @@ b4_both_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])])[
{ {
if (yylexer == null) if (yylexer == null)
throw new NullPointerException("Null Lexer"); throw new NullPointerException("Null Lexer");
int status; int status;
do { do {
int token = yylexer.yylex(); int token = yylexer.yylex();
]b4_yystype[ lval = yylexer.getLVal(); ]b4_yystype[ lval = yylexer.getLVal();
]b4_locations_if([dnl ]b4_locations_if([dnl
b4_location_type yyloc = new b4_location_type (yylexer.getStartPos (), b4_location_type yyloc = new b4_location_type (yylexer.getStartPos (),
yylexer.getEndPos ());])[ yylexer.getEndPos ());])[
]b4_locations_if([status = push_parse(token,lval,yyloc);],[ ]b4_locations_if([status = push_parse(token,lval,yyloc);],[
status = push_parse(token,lval);])[ status = push_parse(token,lval);])[
} while (status == YYPUSH_MORE); } while (status == YYPUSH_MORE);
return (status == YYACCEPT); return (status == YYACCEPT);
} }
]])[ ]])[
@@ -938,7 +919,7 @@ b4_both_if([[
new StringBuffer ("syntax error, unexpected "); new StringBuffer ("syntax error, unexpected ");
res.append (yytnamerr_ (yytname_[tok])); res.append (yytnamerr_ (yytname_[tok]));
int yyn = yypact_[yystate]; int yyn = yypact_[yystate];
if (!yy_pact_value_is_default_ (yyn)) if (!yyPactValueIsDefault (yyn))
{ {
/* Start YYX at -YYN if negative to avoid negative /* Start YYX at -YYN if negative to avoid negative
indexes in YYCHECK. In other words, skip the first indexes in YYCHECK. In other words, skip the first
@@ -951,14 +932,14 @@ b4_both_if([[
int count = 0; int count = 0;
for (int x = yyxbegin; x < yyxend; ++x) for (int x = yyxbegin; x < yyxend; ++x)
if (yycheck_[x + yyn] == x && x != yyterror_ if (yycheck_[x + yyn] == x && x != yyterror_
&& !yy_table_value_is_error_ (yytable_[x + yyn])) && !yyTableValueIsError (yytable_[x + yyn]))
++count; ++count;
if (count < 5) if (count < 5)
{ {
count = 0; count = 0;
for (int x = yyxbegin; x < yyxend; ++x) for (int x = yyxbegin; x < yyxend; ++x)
if (yycheck_[x + yyn] == x && x != yyterror_ if (yycheck_[x + yyn] == x && x != yyterror_
&& !yy_table_value_is_error_ (yytable_[x + yyn])) && !yyTableValueIsError (yytable_[x + yyn]))
{ {
res.append (count++ == 0 ? ", expecting " : " or "); res.append (count++ == 0 ? ", expecting " : " or ");
res.append (yytnamerr_ (yytname_[x])); res.append (yytnamerr_ (yytname_[x]));
@@ -976,7 +957,7 @@ b4_both_if([[
* Whether the given <code>yypact_</code> value indicates a defaulted state. * Whether the given <code>yypact_</code> value indicates a defaulted state.
* @@param yyvalue the value to check * @@param yyvalue the value to check
*/ */
private static boolean yy_pact_value_is_default_ (int yyvalue) private static boolean yyPactValueIsDefault (int yyvalue)
{ {
return yyvalue == yypact_ninf_; return yyvalue == yypact_ninf_;
} }
@@ -986,7 +967,7 @@ b4_both_if([[
* value indicates a syntax error. * value indicates a syntax error.
* @@param yyvalue the value to check * @@param yyvalue the value to check
*/ */
private static boolean yy_table_value_is_error_ (int yyvalue) private static boolean yyTableValueIsError (int yyvalue)
{ {
return yyvalue == yytable_ninf_; return yyvalue == yytable_ninf_;
} }
@@ -1003,12 +984,13 @@ b4_both_if([[
First, the terminals, then, starting at \a yyntokens_, nonterminals. */ First, the terminals, then, starting at \a yyntokens_, nonterminals. */
]b4_typed_parser_table_define([String], [tname], [b4_tname])[ ]b4_typed_parser_table_define([String], [tname], [b4_tname])[
]b4_parse_trace_if([[
]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 yyReducePrint (int yyrule, YYStack yystack)
{ {
if (yydebug == 0) if (yydebug == 0)
return; return;
@@ -1021,23 +1003,30 @@ b4_both_if([[
/* The symbols being reduced. */ /* The symbols being reduced. */
for (int yyi = 0; yyi < yynrhs; yyi++) for (int yyi = 0; yyi < yynrhs; yyi++)
yy_symbol_print (" $" + (yyi + 1) + " =", yySymbolPrint (" $" + (yyi + 1) + " =",
yystos_[yystack.stateAt(yynrhs - (yyi + 1))], yystos_[yystack.stateAt(yynrhs - (yyi + 1))],
]b4_rhs_data(yynrhs, yyi + 1)b4_locations_if([, ]b4_rhs_data(yynrhs, yyi + 1)b4_locations_if([,
b4_rhs_location(yynrhs, yyi + 1)])[); b4_rhs_location(yynrhs, yyi + 1)])[);
} }]])[
/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM /* YYTRANSLATE_(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM
as returned by yylex, with out-of-bounds checking. */ as returned by yylex, with out-of-bounds checking. */
]b4_integral_parser_table_define([translate_table], [b4_translate])[
private static final ]b4_int_type_for([b4_translate])[ yytranslate_ (int t) private static final ]b4_int_type_for([b4_translate])[ yytranslate_ (int t)
{ ]b4_api_token_raw_if(dnl
if (t >= 0 && t <= yyuser_token_number_max_) [[ {
return t;
}
]],
[[ {
if (t <= 0)
return Lexer.EOF;
else if (t <= yyuser_token_number_max_)
return yytranslate_table_[t]; return yytranslate_table_[t];
else else
return yyundef_token_; return yyundef_token_;
} }
]b4_integral_parser_table_define([translate_table], [b4_translate])[
]])[
private static final int yylast_ = ]b4_last[; private static final int yylast_ = ]b4_last[;
private static final int yynnts_ = ]b4_nterms_number[; private static final int yynnts_ = ]b4_nterms_number[;
@@ -1050,8 +1039,8 @@ b4_both_if([[
private static final int yyuser_token_number_max_ = ]b4_user_token_number_max[; private static final int yyuser_token_number_max_ = ]b4_user_token_number_max[;
private static final int yyundef_token_ = ]b4_undef_token_number[; private static final int yyundef_token_ = ]b4_undef_token_number[;
]/* User implementation code. */ /* User implementation code. */
b4_percent_code_get[]dnl ]b4_percent_code_get[]dnl
} }
+15 -17
View File
@@ -65,8 +65,8 @@ m4_define([b4_location_define],
public:]m4_ifdef([b4_location_constructors], [[ public:]m4_ifdef([b4_location_constructors], [[
/// Construct a position. /// Construct a position.
explicit position (]b4_percent_define_get([[filename_type]])[* f = YY_NULLPTR, explicit position (]b4_percent_define_get([[filename_type]])[* f = YY_NULLPTR,
unsigned l = ]b4_location_initial_line[u, int l = ]b4_location_initial_line[,
unsigned c = ]b4_location_initial_column[u) int c = ]b4_location_initial_column[)
: filename (f) : filename (f)
, line (l) , line (l)
, column (c) , column (c)
@@ -75,8 +75,8 @@ m4_define([b4_location_define],
]])[ ]])[
/// Initialization. /// Initialization.
void initialize (]b4_percent_define_get([[filename_type]])[* fn = YY_NULLPTR, void initialize (]b4_percent_define_get([[filename_type]])[* fn = YY_NULLPTR,
unsigned l = ]b4_location_initial_line[u, int l = ]b4_location_initial_line[,
unsigned c = ]b4_location_initial_column[u) int c = ]b4_location_initial_column[)
{ {
filename = fn; filename = fn;
line = l; line = l;
@@ -90,7 +90,7 @@ m4_define([b4_location_define],
{ {
if (count) if (count)
{ {
column = ]b4_location_initial_column[u; column = ]b4_location_initial_column[;
line = add_ (line, count, ]b4_location_initial_line[); line = add_ (line, count, ]b4_location_initial_line[);
} }
} }
@@ -105,16 +105,15 @@ m4_define([b4_location_define],
/// File name to which this position refers. /// File name to which this position refers.
]b4_percent_define_get([[filename_type]])[* filename; ]b4_percent_define_get([[filename_type]])[* filename;
/// Current line number. /// Current line number.
unsigned line; int line;
/// Current column number. /// Current column number.
unsigned column; int column;
private: private:
/// Compute max (min, lhs+rhs). /// Compute max (min, lhs+rhs).
static unsigned add_ (unsigned lhs, int rhs, int min) static int add_ (int lhs, int rhs, int min)
{ {
return static_cast<unsigned> (std::max (min, return lhs + rhs < min ? min : lhs + rhs;
static_cast<int> (lhs) + rhs));
} }
}; };
@@ -197,8 +196,8 @@ m4_define([b4_location_define],
/// Construct a 0-width location in \a f, \a l, \a c. /// Construct a 0-width location in \a f, \a l, \a c.
explicit location (]b4_percent_define_get([[filename_type]])[* f, explicit location (]b4_percent_define_get([[filename_type]])[* f,
unsigned l = ]b4_location_initial_line[u, int l = ]b4_location_initial_line[,
unsigned c = ]b4_location_initial_column[u) int c = ]b4_location_initial_column[)
: begin (f, l, c) : begin (f, l, c)
, end (f, l, c) , end (f, l, c)
{} {}
@@ -206,8 +205,8 @@ m4_define([b4_location_define],
])[ ])[
/// Initialization. /// Initialization.
void initialize (]b4_percent_define_get([[filename_type]])[* f = YY_NULLPTR, void initialize (]b4_percent_define_get([[filename_type]])[* f = YY_NULLPTR,
unsigned l = ]b4_location_initial_line[u, int l = ]b4_location_initial_line[,
unsigned c = ]b4_location_initial_column[u) int c = ]b4_location_initial_column[)
{ {
begin.initialize (f, l, c); begin.initialize (f, l, c);
end = begin; end = begin;
@@ -305,7 +304,7 @@ m4_define([b4_location_define],
std::basic_ostream<YYChar>& std::basic_ostream<YYChar>&
operator<< (std::basic_ostream<YYChar>& ostr, const location& loc) operator<< (std::basic_ostream<YYChar>& ostr, const location& loc)
{ {
unsigned end_col = 0 < loc.end.column ? loc.end.column - 1 : 0; int end_col = 0 < loc.end.column ? loc.end.column - 1 : 0;
ostr << loc.begin; ostr << loc.begin;
if (loc.end.filename if (loc.end.filename
&& (!loc.begin.filename && (!loc.begin.filename
@@ -327,7 +326,7 @@ m4_ifdef([b4_position_file], [[
// used to define is now defined in "]b4_location_file[". // used to define is now defined in "]b4_location_file[".
// //
// To get rid of this file: // To get rid of this file:
// 1. add 'require "3.2"' (or newer) to your grammar file // 1. add '%require "3.2"' (or newer) to your grammar file
// 2. remove references to this file from your build system // 2. remove references to this file from your build system
// 3. if you used to include it, include "]b4_location_file[" instead. // 3. if you used to include it, include "]b4_location_file[" instead.
@@ -346,7 +345,6 @@ m4_ifdef([b4_location_file], [[
]b4_cpp_guard_open([b4_location_path])[ ]b4_cpp_guard_open([b4_location_path])[
# include <algorithm> // std::max
# include <iostream> # include <iostream>
# include <string> # include <string>
+18 -30
View File
@@ -35,6 +35,7 @@ m4_define([b4_stack_define],
typedef typename S::reverse_iterator iterator; typedef typename S::reverse_iterator iterator;
typedef typename S::const_reverse_iterator const_iterator; typedef typename S::const_reverse_iterator const_iterator;
typedef typename S::size_type size_type; typedef typename S::size_type size_type;
typedef typename std::ptrdiff_t index_type;
stack (size_type n = 200) stack (size_type n = 200)
: seq_ (n) : seq_ (n)
@@ -43,37 +44,19 @@ m4_define([b4_stack_define],
/// Random access. /// Random access.
/// ///
/// Index 0 returns the topmost element. /// Index 0 returns the topmost element.
T& const T&
operator[] (size_type i) operator[] (index_type i) const
{ {
return seq_[size () - 1 - i]; return seq_[size_type (size () - 1 - i)];
} }
/// Random access. /// Random access.
/// ///
/// Index 0 returns the topmost element. /// Index 0 returns the topmost element.
T& T&
operator[] (int i) operator[] (index_type i)
{ {
return operator[] (size_type (i)); return seq_[size_type (size () - 1 - i)];
}
/// Random access.
///
/// Index 0 returns the topmost element.
const T&
operator[] (size_type i) const
{
return seq_[size () - 1 - i];
}
/// Random access.
///
/// Index 0 returns the topmost element.
const T&
operator[] (int i) const
{
return operator[] (size_type (i));
} }
/// Steal the contents of \a t. /// Steal the contents of \a t.
@@ -88,7 +71,7 @@ m4_define([b4_stack_define],
/// Pop elements from the stack. /// Pop elements from the stack.
void void
pop (int n = 1) YY_NOEXCEPT pop (std::ptrdiff_t n = 1) YY_NOEXCEPT
{ {
for (; 0 < n; --n) for (; 0 < n; --n)
seq_.pop_back (); seq_.pop_back ();
@@ -102,10 +85,15 @@ m4_define([b4_stack_define],
} }
/// Number of elements on the stack. /// Number of elements on the stack.
size_type index_type
size () const YY_NOEXCEPT size () const YY_NOEXCEPT
{ {
return seq_.size (); return index_type (seq_.size ());
}
std::ptrdiff_t
ssize () const YY_NOEXCEPT
{
return (std::ptrdiff_t) size ();
} }
/// Iterator on top of the stack (going downwards). /// Iterator on top of the stack (going downwards).
@@ -126,20 +114,20 @@ m4_define([b4_stack_define],
class slice class slice
{ {
public: public:
slice (const stack& stack, int range) slice (const stack& stack, index_type range)
: stack_ (stack) : stack_ (stack)
, range_ (range) , range_ (range)
{} {}
const T& const T&
operator[] (int i) const operator[] (index_type i) const
{ {
return stack_[range_ - i]; return stack_[range_ - i];
} }
private: private:
const stack& stack_; const stack& stack_;
int range_; index_type range_;
}; };
private: private:
@@ -157,7 +145,7 @@ m4_ifdef([b4_stack_file],
// used to define is now defined with the parser itself. // used to define is now defined with the parser itself.
// //
// To get rid of this file: // To get rid of this file:
// 1. add 'require "3.2"' (or newer) to your grammar file // 1. add '%require "3.2"' (or newer) to your grammar file
// 2. remove references to this file from your build system. // 2. remove references to this file from your build system.
]b4_output_end[ ]b4_output_end[
]]) ]])
+182 -190
View File
@@ -1,4 +1,4 @@
-*- C -*- # -*- C -*-
# Yacc compatible skeleton for Bison # Yacc compatible skeleton for Bison
# Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software # Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software
@@ -20,51 +20,11 @@ m4_pushdef([b4_copyright_years],
# 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/>.
# Check the value of %define api.push-pull.
b4_percent_define_default([[api.push-pull]], [[pull]])
b4_percent_define_check_values([[[[api.push-pull]],
[[pull]], [[push]], [[both]]]])
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]])])
# 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]])])])
# Check the value of %define parse.lac and friends, where LAC stands for
# lookahead correction.
b4_percent_define_default([[parse.lac]], [[none]])
b4_percent_define_default([[parse.lac.es-capacity-initial]], [[20]])
b4_percent_define_default([[parse.lac.memory-trace]], [[failures]])
b4_percent_define_check_values([[[[parse.lac]], [[full]], [[none]]]],
[[[[parse.lac.memory-trace]],
[[failures]], [[full]]]])
b4_define_flag_if([lac])
m4_define([b4_lac_flag],
[m4_if(b4_percent_define_get([[parse.lac]]),
[none], [[0]], [[1]])])
m4_include(b4_skeletonsdir/[c.m4]) m4_include(b4_skeletonsdir/[c.m4])
## ---------------- ## ## ---------- ##
## Default values. ## ## api.pure. ##
## ---------------- ## ## ---------- ##
# Stack parameters.
m4_define_default([b4_stack_depth_max], [10000])
m4_define_default([b4_stack_depth_init], [200])
## ------------------------ ##
## Pure/impure interfaces. ##
## ------------------------ ##
b4_percent_define_default([[api.pure]], [[false]]) b4_percent_define_default([[api.pure]], [[false]])
b4_percent_define_check_values([[[[api.pure]], b4_percent_define_check_values([[[[api.pure]],
@@ -84,6 +44,51 @@ m4_define([b4_pure_if],
[2], [$1])]) [2], [$1])])
[m4_fatal([invalid api.pure value: ]$1)])]) [m4_fatal([invalid api.pure value: ]$1)])])
## --------------- ##
## api.push-pull. ##
## --------------- ##
b4_percent_define_default([[api.push-pull]], [[pull]])
b4_percent_define_check_values([[[[api.push-pull]],
[[pull]], [[push]], [[both]]]])
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]])])
# 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]])])])
## ----------- ##
## parse.lac. ##
## ----------- ##
b4_percent_define_default([[parse.lac]], [[none]])
b4_percent_define_default([[parse.lac.es-capacity-initial]], [[20]])
b4_percent_define_default([[parse.lac.memory-trace]], [[failures]])
b4_percent_define_check_values([[[[parse.lac]], [[full]], [[none]]]],
[[[[parse.lac.memory-trace]],
[[failures]], [[full]]]])
b4_define_flag_if([lac])
m4_define([b4_lac_flag],
[m4_if(b4_percent_define_get([[parse.lac]]),
[none], [[0]], [[1]])])
## ---------------- ##
## Default values. ##
## ---------------- ##
# Stack parameters.
m4_define_default([b4_stack_depth_max], [10000])
m4_define_default([b4_stack_depth_init], [200])
# b4_yyerror_arg_loc_if(ARG) # b4_yyerror_arg_loc_if(ARG)
# -------------------------- # --------------------------
# Expand ARG iff yyerror is to be given a location as argument. # Expand ARG iff yyerror is to be given a location as argument.
@@ -101,28 +106,6 @@ m4_ifset([b4_parse_param], [b4_args(b4_parse_param), ])])
## ------------ ##
## Data Types. ##
## ------------ ##
# b4_int_type(MIN, MAX)
# ---------------------
# Return the smallest int type able to handle numbers ranging from
# MIN to MAX (included). Overwrite the version from c.m4, which
# uses only C89 types, so that the user can override the shorter
# types, and so that pre-C89 compilers are handled correctly.
m4_define([b4_int_type],
[m4_if(b4_ints_in($@, [0], [255]), [1], [yytype_uint8],
b4_ints_in($@, [-128], [127]), [1], [yytype_int8],
b4_ints_in($@, [0], [65535]), [1], [yytype_uint16],
b4_ints_in($@, [-32768], [32767]), [1], [yytype_int16],
m4_eval([0 <= $1]), [1], [unsigned],
[int])])
## ----------------- ## ## ----------------- ##
## Semantic Values. ## ## Semantic Values. ##
## ----------------- ## ## ----------------- ##
@@ -199,7 +182,7 @@ m4_define([b4_declare_parser_state_variables], [b4_pure_if([[
/* Number of syntax errors so far. */ /* Number of syntax errors so far. */
int yynerrs; int yynerrs;
]])[ ]])[
int yystate; yy_state_fast_t yystate;
/* Number of tokens to shift before error messages enabled. */ /* Number of tokens to shift before error messages enabled. */
int yyerrstatus; int yyerrstatus;
@@ -212,9 +195,9 @@ m4_define([b4_declare_parser_state_variables], [b4_pure_if([[
to reallocate them elsewhere. */ to reallocate them elsewhere. */
/* The state stack. */ /* The state stack. */
yytype_int16 yyssa[YYINITDEPTH]; yy_state_t yyssa[YYINITDEPTH];
yytype_int16 *yyss; yy_state_t *yyss;
yytype_int16 *yyssp; yy_state_t *yyssp;
/* The semantic value stack. */ /* The semantic value stack. */
YYSTYPE yyvsa[YYINITDEPTH]; YYSTYPE yyvsa[YYINITDEPTH];
@@ -229,11 +212,11 @@ m4_define([b4_declare_parser_state_variables], [b4_pure_if([[
/* The locations where the error started and ended. */ /* The locations where the error started and ended. */
YYLTYPE yyerror_range[3];]])[ YYLTYPE yyerror_range[3];]])[
YYSIZE_T yystacksize;]b4_lac_if([[ YYPTRDIFF_T yystacksize;]b4_lac_if([[
yytype_int16 yyesa@{]b4_percent_define_get([[parse.lac.es-capacity-initial]])[@}; yy_state_t yyesa@{]b4_percent_define_get([[parse.lac.es-capacity-initial]])[@};
yytype_int16 *yyes; yy_state_t *yyes;
YYSIZE_T yyes_capacity;]])]) YYPTRDIFF_T yyes_capacity;]])])
# _b4_declare_yyparse_push # _b4_declare_yyparse_push
@@ -386,28 +369,22 @@ m4_if(b4_api_prefix, [yy], [],
# undef short # undef short
#endif #endif
#ifdef YYTYPE_UINT8 ]b4_c99_int_type_define[
typedef YYTYPE_UINT8 yytype_uint8;
#else
typedef unsigned char yytype_uint8;
#endif
#ifdef YYTYPE_INT8 #ifndef YYPTRDIFF_T
typedef YYTYPE_INT8 yytype_int8; # if defined __PTRDIFF_TYPE__ && defined __PTRDIFF_MAX__
#else # define YYPTRDIFF_T __PTRDIFF_TYPE__
typedef signed char yytype_int8; # define YYPTRDIFF_MAXIMUM __PTRDIFF_MAX__
#endif # elif defined PTRDIFF_MAX
# ifndef ptrdiff_t
#ifdef YYTYPE_UINT16 # include <stddef.h> /* INFRINGES ON USER NAME SPACE */
typedef YYTYPE_UINT16 yytype_uint16; # endif
#else # define YYPTRDIFF_T ptrdiff_t
typedef unsigned short yytype_uint16; # define YYPTRDIFF_MAXIMUM PTRDIFF_MAX
#endif # else
# define YYPTRDIFF_T long
#ifdef YYTYPE_INT16 # define YYPTRDIFF_MAXIMUM LONG_MAX
typedef YYTYPE_INT16 yytype_int16; # endif
#else
typedef short yytype_int16;
#endif #endif
#ifndef YYSIZE_T #ifndef YYSIZE_T
@@ -415,7 +392,7 @@ typedef short yytype_int16;
# define YYSIZE_T __SIZE_TYPE__ # define YYSIZE_T __SIZE_TYPE__
# elif defined size_t # elif defined size_t
# define YYSIZE_T size_t # define YYSIZE_T size_t
# elif ! defined YYSIZE_T # elif defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__
# include <stddef.h> /* INFRINGES ON USER NAME SPACE */ # include <stddef.h> /* INFRINGES ON USER NAME SPACE */
# define YYSIZE_T size_t # define YYSIZE_T size_t
# else # else
@@ -423,7 +400,16 @@ typedef short yytype_int16;
# endif # endif
#endif #endif
#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) #define YYSIZE_MAXIMUM ((YYPTRDIFF_T) (YYPTRDIFF_MAXIMUM < (YYSIZE_T) -1 \
? YYPTRDIFF_MAXIMUM : (YYSIZE_T) -1))
#define YYSIZEOF(X) ((YYPTRDIFF_T) sizeof (X))
/* Stored state numbers (used for stacks). */
typedef ]b4_int_type(0, m4_eval(b4_states_number - 1))[ yy_state_t;
/* State numbers in computations. */
typedef int yy_state_fast_t;
#ifndef YY_ #ifndef YY_
# if defined YYENABLE_NLS && YYENABLE_NLS # if defined YYENABLE_NLS && YYENABLE_NLS
@@ -526,22 +512,23 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */
/* A type that is properly aligned for any stack member. */ /* A type that is properly aligned for any stack member. */
union yyalloc union yyalloc
{ {
yytype_int16 yyss_alloc; yy_state_t yyss_alloc;
YYSTYPE yyvs_alloc;]b4_locations_if([ YYSTYPE yyvs_alloc;]b4_locations_if([
YYLTYPE yyls_alloc;])[ YYLTYPE yyls_alloc;])[
}; };
/* The size of the maximum gap between one aligned stack and the next. */ /* The size of the maximum gap between one aligned stack and the next. */
# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) # define YYSTACK_GAP_MAXIMUM (YYSIZEOF (union yyalloc) - 1)
/* The size of an array large to enough to hold all stacks, each with /* The size of an array large to enough to hold all stacks, each with
N elements. */ N elements. */
]b4_locations_if( ]b4_locations_if(
[# define YYSTACK_BYTES(N) \ [# define YYSTACK_BYTES(N) \
((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \ ((N) * (YYSIZEOF (yy_state_t) + YYSIZEOF (YYSTYPE) \
+ YYSIZEOF (YYLTYPE)) \
+ 2 * YYSTACK_GAP_MAXIMUM)], + 2 * YYSTACK_GAP_MAXIMUM)],
[# define YYSTACK_BYTES(N) \ [# define YYSTACK_BYTES(N) \
((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ ((N) * (YYSIZEOF (yy_state_t) + YYSIZEOF (YYSTYPE)) \
+ YYSTACK_GAP_MAXIMUM)])[ + YYSTACK_GAP_MAXIMUM)])[
# define YYCOPY_NEEDED 1 # define YYCOPY_NEEDED 1
@@ -554,11 +541,11 @@ union yyalloc
# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ # define YYSTACK_RELOCATE(Stack_alloc, Stack) \
do \ do \
{ \ { \
YYSIZE_T yynewbytes; \ YYPTRDIFF_T yynewbytes; \
YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
Stack = &yyptr->Stack_alloc; \ Stack = &yyptr->Stack_alloc; \
yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ yynewbytes = yystacksize * YYSIZEOF (*Stack) + YYSTACK_GAP_MAXIMUM; \
yyptr += yynewbytes / sizeof (*yyptr); \ yyptr += yynewbytes / YYSIZEOF (*yyptr); \
} \ } \
while (0) while (0)
@@ -570,12 +557,12 @@ union yyalloc
# ifndef YYCOPY # ifndef YYCOPY
# if defined __GNUC__ && 1 < __GNUC__ # if defined __GNUC__ && 1 < __GNUC__
# define YYCOPY(Dst, Src, Count) \ # define YYCOPY(Dst, Src, Count) \
__builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src))) __builtin_memcpy (Dst, Src, (YYSIZE_T) (Count) * sizeof (*(Src)))
# else # else
# define YYCOPY(Dst, Src, Count) \ # define YYCOPY(Dst, Src, Count) \
do \ do \
{ \ { \
YYSIZE_T yyi; \ YYPTRDIFF_T yyi; \
for (yyi = 0; yyi < (Count); yyi++) \ for (yyi = 0; yyi < (Count); yyi++) \
(Dst)[yyi] = (Src)[yyi]; \ (Dst)[yyi] = (Src)[yyi]; \
} \ } \
@@ -601,17 +588,20 @@ union yyalloc
#define YYUNDEFTOK ]b4_undef_token_number[ #define YYUNDEFTOK ]b4_undef_token_number[
#define YYMAXUTOK ]b4_user_token_number_max[ #define YYMAXUTOK ]b4_user_token_number_max[
/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM /* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM
as returned by yylex, with out-of-bounds checking. */ as returned by yylex, with out-of-bounds checking. */
#define YYTRANSLATE(YYX) \ ]b4_api_token_raw_if(dnl
((unsigned) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) [[#define YYTRANSLATE(YYX) (YYX)]],
[[#define YYTRANSLATE(YYX) \
(0 <= (YYX) && (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM /* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
as returned by yylex. */ as returned by yylex. */
static const ]b4_int_type_for([b4_translate])[ yytranslate[] = static const ]b4_int_type_for([b4_translate])[ yytranslate[] =
{ {
]b4_translate[ ]b4_translate[
}; };]])[
#if ]b4_api_PREFIX[DEBUG #if ]b4_api_PREFIX[DEBUG
]b4_integral_parser_table_define([rline], [b4_rline], ]b4_integral_parser_table_define([rline], [b4_rline],
@@ -636,15 +626,15 @@ static const ]b4_int_type_for([b4_toknum])[ yytoknum[] =
}; };
# endif # endif
#define YYPACT_NINF ]b4_pact_ninf[ #define YYPACT_NINF (]b4_pact_ninf[)
#define yypact_value_is_default(Yystate) \ #define yypact_value_is_default(Yyn) \
]b4_table_value_equals([[pact]], [[Yystate]], [b4_pact_ninf])[ ]b4_table_value_equals([[pact]], [[Yyn]], [b4_pact_ninf], [YYPACT_NINF])[
#define YYTABLE_NINF ]b4_table_ninf[ #define YYTABLE_NINF (]b4_table_ninf[)
#define yytable_value_is_error(Yytable_value) \ #define yytable_value_is_error(Yyn) \
]b4_table_value_equals([[table]], [[Yytable_value]], [b4_table_ninf])[ ]b4_table_value_equals([[table]], [[Yyn]], [b4_table_ninf], [YYTABLE_NINF])[
]b4_parser_tables_define[ ]b4_parser_tables_define[
@@ -722,8 +712,8 @@ do { \
`------------------------------------------------------------------*/ `------------------------------------------------------------------*/
]b4_function_define([yy_stack_print], [static void], ]b4_function_define([yy_stack_print], [static void],
[[yytype_int16 *yybottom], [yybottom]], [[yy_state_t *yybottom], [yybottom]],
[[yytype_int16 *yytop], [yytop]])[ [[yy_state_t *yytop], [yytop]])[
{ {
YYFPRINTF (stderr, "Stack now"); YYFPRINTF (stderr, "Stack now");
for (; yybottom <= yytop; yybottom++) for (; yybottom <= yytop; yybottom++)
@@ -746,16 +736,16 @@ do { \
`------------------------------------------------*/ `------------------------------------------------*/
]b4_function_define([yy_reduce_print], [static void], ]b4_function_define([yy_reduce_print], [static void],
[[yytype_int16 *yyssp], [yyssp]], [[yy_state_t *yyssp], [yyssp]],
[[YYSTYPE *yyvsp], [yyvsp]], [[YYSTYPE *yyvsp], [yyvsp]],
b4_locations_if([[[YYLTYPE *yylsp], [yylsp]], b4_locations_if([[[YYLTYPE *yylsp], [yylsp]],
])[[int yyrule], [yyrule]]m4_ifset([b4_parse_param], [, ])[[int yyrule], [yyrule]]m4_ifset([b4_parse_param], [,
b4_parse_param]))[ b4_parse_param]))[
{ {
unsigned long yylno = yyrline[yyrule]; int yylno = yyrline[yyrule];
int yynrhs = yyr2[yyrule]; int yynrhs = yyr2[yyrule];
int yyi; int yyi;
YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", YYFPRINTF (stderr, "Reducing stack by rule %d (line %d):\n",
yyrule - 1, yylno); yyrule - 1, yylno);
/* The symbols being reduced. */ /* The symbols being reduced. */
for (yyi = 0; yyi < yynrhs; yyi++) for (yyi = 0; yyi < yynrhs; yyi++)
@@ -814,22 +804,22 @@ int yydebug;
using YYSTACK_FREE. Return 0 if successful or if no reallocation is using YYSTACK_FREE. Return 0 if successful or if no reallocation is
required. Return 1 if memory is exhausted. */ required. Return 1 if memory is exhausted. */
static int static int
yy_lac_stack_realloc (YYSIZE_T *yycapacity, YYSIZE_T yyadd, yy_lac_stack_realloc (YYPTRDIFF_T *yycapacity, YYPTRDIFF_T yyadd,
#if ]b4_api_PREFIX[DEBUG #if ]b4_api_PREFIX[DEBUG
char const *yydebug_prefix, char const *yydebug_prefix,
char const *yydebug_suffix, char const *yydebug_suffix,
#endif #endif
yytype_int16 **yybottom, yy_state_t **yybottom,
yytype_int16 *yybottom_no_free, yy_state_t *yybottom_no_free,
yytype_int16 **yytop, yytype_int16 *yytop_empty) yy_state_t **yytop, yy_state_t *yytop_empty)
{ {
YYSIZE_T yysize_old = YYPTRDIFF_T yysize_old =
(YYSIZE_T) (*yytop == yytop_empty ? 0 : *yytop - *yybottom + 1); *yytop == yytop_empty ? 0 : *yytop - *yybottom + 1;
YYSIZE_T yysize_new = yysize_old + yyadd; YYPTRDIFF_T yysize_new = yysize_old + yyadd;
if (*yycapacity < yysize_new) if (*yycapacity < yysize_new)
{ {
YYSIZE_T yyalloc = 2 * yysize_new; YYPTRDIFF_T yyalloc = 2 * yysize_new;
yytype_int16 *yybottom_new; yy_state_t *yybottom_new;
/* Use YYMAXDEPTH for maximum stack size given that the stack /* Use YYMAXDEPTH for maximum stack size given that the stack
should never need to grow larger than the main state stack should never need to grow larger than the main state stack
needs to grow without LAC. */ needs to grow without LAC. */
@@ -842,7 +832,8 @@ yy_lac_stack_realloc (YYSIZE_T *yycapacity, YYSIZE_T yyadd,
if (YYMAXDEPTH < yyalloc) if (YYMAXDEPTH < yyalloc)
yyalloc = YYMAXDEPTH; yyalloc = YYMAXDEPTH;
yybottom_new = yybottom_new =
(yytype_int16*) YYSTACK_ALLOC (yyalloc * sizeof *yybottom_new); (yy_state_t *) YYSTACK_ALLOC ((YYSIZE_T)
(yyalloc * YYSIZEOF (*yybottom_new)));
if (!yybottom_new) if (!yybottom_new)
{ {
YYDPRINTF ((stderr, "%srealloc failed%s", yydebug_prefix, YYDPRINTF ((stderr, "%srealloc failed%s", yydebug_prefix,
@@ -859,8 +850,8 @@ yy_lac_stack_realloc (YYSIZE_T *yycapacity, YYSIZE_T yyadd,
*yybottom = yybottom_new; *yybottom = yybottom_new;
*yycapacity = yyalloc;]m4_if(b4_percent_define_get([[parse.lac.memory-trace]]), *yycapacity = yyalloc;]m4_if(b4_percent_define_get([[parse.lac.memory-trace]]),
[full], [[ [full], [[
YYDPRINTF ((stderr, "%srealloc to %lu%s", yydebug_prefix, YYDPRINTF ((stderr, "%srealloc to %ld%s", yydebug_prefix,
(unsigned long) yyalloc, yydebug_suffix));]])[ (long) yyalloc, yydebug_suffix));]])[
} }
return 0; return 0;
} }
@@ -945,11 +936,11 @@ do { \
contents of either array, alter *YYES and *YYES_CAPACITY, and free contents of either array, alter *YYES and *YYES_CAPACITY, and free
any old *YYES other than YYESA. */ any old *YYES other than YYESA. */
static int static int
yy_lac (yytype_int16 *yyesa, yytype_int16 **yyes, yy_lac (yy_state_t *yyesa, yy_state_t **yyes,
YYSIZE_T *yyes_capacity, yytype_int16 *yyssp, int yytoken) YYPTRDIFF_T *yyes_capacity, yy_state_t *yyssp, int yytoken)
{ {
yytype_int16 *yyes_prev = yyssp; yy_state_t *yyes_prev = yyssp;
yytype_int16 *yyesp = yyes_prev; yy_state_t *yyesp = yyes_prev;
YYDPRINTF ((stderr, "LAC: checking lookahead %s:", yytname[yytoken])); YYDPRINTF ((stderr, "LAC: checking lookahead %s:", yytname[yytoken]));
if (yytoken == YYUNDEFTOK) if (yytoken == YYUNDEFTOK)
{ {
@@ -986,11 +977,11 @@ yy_lac (yytype_int16 *yyesa, yytype_int16 **yyes,
yyrule = -yyrule; yyrule = -yyrule;
} }
{ {
YYSIZE_T yylen = yyr2[yyrule]; YYPTRDIFF_T yylen = yyr2[yyrule];
YYDPRINTF ((stderr, " R%d", yyrule - 1)); YYDPRINTF ((stderr, " R%d", yyrule - 1));
if (yyesp != yyes_prev) if (yyesp != yyes_prev)
{ {
YYSIZE_T yysize = (YYSIZE_T) (yyesp - *yyes + 1); YYPTRDIFF_T yysize = yyesp - *yyes + 1;
if (yylen < yysize) if (yylen < yysize)
{ {
yyesp -= yylen; yyesp -= yylen;
@@ -1006,19 +997,18 @@ yy_lac (yytype_int16 *yyesa, yytype_int16 **yyes,
yyesp = yyes_prev -= yylen; yyesp = yyes_prev -= yylen;
} }
{ {
yytype_int16 yystate; yy_state_fast_t yystate;
{ {
const int yylhs = yyr1[yyrule] - YYNTOKENS; const int yylhs = yyr1[yyrule] - YYNTOKENS;
const int yyi = yypgoto[yylhs] + *yyesp; const int yyi = yypgoto[yylhs] + *yyesp;
yystate = ((yytype_int16) yystate = (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yyesp
(0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yyesp ? yytable[yyi]
? yytable[yyi] : yydefgoto[yylhs]);
: yydefgoto[yylhs]));
} }
if (yyesp == yyes_prev) if (yyesp == yyes_prev)
{ {
yyesp = *yyes; yyesp = *yyes;
*yyesp = yystate; *yyesp = (yy_state_t) yystate;
} }
else else
{ {
@@ -1031,9 +1021,9 @@ yy_lac (yytype_int16 *yyesa, yytype_int16 **yyes,
YYDPRINTF ((stderr, "\n")); YYDPRINTF ((stderr, "\n"));
return 2; return 2;
} }
*++yyesp = yystate; *++yyesp = (yy_state_t) yystate;
} }
YYDPRINTF ((stderr, " G%d", (int) yystate)); YYDPRINTF ((stderr, " G%d", yystate));
} }
} }
}]])[ }]])[
@@ -1043,13 +1033,13 @@ yy_lac (yytype_int16 *yyesa, yytype_int16 **yyes,
# ifndef yystrlen # ifndef yystrlen
# if defined __GLIBC__ && defined _STRING_H # if defined __GLIBC__ && defined _STRING_H
# define yystrlen strlen # define yystrlen(S) ((YYPTRDIFF_T) strlen (S))
# else # else
/* Return the length of YYSTR. */ /* Return the length of YYSTR. */
]b4_function_define([yystrlen], [static YYSIZE_T], ]b4_function_define([yystrlen], [static YYPTRDIFF_T],
[[const char *yystr], [yystr]])[ [[const char *yystr], [yystr]])[
{ {
YYSIZE_T yylen; YYPTRDIFF_T yylen;
for (yylen = 0; yystr[yylen]; yylen++) for (yylen = 0; yystr[yylen]; yylen++)
continue; continue;
return yylen; return yylen;
@@ -1085,12 +1075,12 @@ yy_lac (yytype_int16 *yyesa, yytype_int16 **yyes,
backslash-backslash). YYSTR is taken from yytname. If YYRES is backslash-backslash). YYSTR is taken from yytname. If YYRES is
null, do not copy; instead, return the length of what the result null, do not copy; instead, return the length of what the result
would have been. */ would have been. */
static YYSIZE_T static YYPTRDIFF_T
yytnamerr (char *yyres, const char *yystr) yytnamerr (char *yyres, const char *yystr)
{ {
if (*yystr == '"') if (*yystr == '"')
{ {
YYSIZE_T yyn = 0; YYPTRDIFF_T yyn = 0;
char const *yyp = yystr; char const *yyp = yystr;
for (;;) for (;;)
@@ -1121,10 +1111,10 @@ yytnamerr (char *yyres, const char *yystr)
do_not_strip_quotes: ; do_not_strip_quotes: ;
} }
if (! yyres) if (yyres)
return yystpcpy (yyres, yystr) - yyres;
else
return yystrlen (yystr); return yystrlen (yystr);
return (YYSIZE_T) (yystpcpy (yyres, yystr) - yyres);
} }
# endif # endif
@@ -1139,12 +1129,12 @@ yytnamerr (char *yyres, const char *yystr)
required number of bytes is too large to store]b4_lac_if([[ or if required number of bytes is too large to store]b4_lac_if([[ or if
yy_lac returned 2]])[. */ yy_lac returned 2]])[. */
static int static int
yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, yysyntax_error (YYPTRDIFF_T *yymsg_alloc, char **yymsg,
]b4_lac_if([[yytype_int16 *yyesa, yytype_int16 **yyes, ]b4_lac_if([[yy_state_t *yyesa, yy_state_t **yyes,
YYSIZE_T *yyes_capacity, ]])[yytype_int16 *yyssp, int yytoken) YYPTRDIFF_T *yyes_capacity, ]])[yy_state_t *yyssp, int yytoken)
{ {
YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]); YYPTRDIFF_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]);
YYSIZE_T yysize = yysize0; YYPTRDIFF_T yysize = yysize0;
enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
/* Internationalized format string. */ /* Internationalized format string. */
const char *yyformat = YY_NULLPTR; const char *yyformat = YY_NULLPTR;
@@ -1188,15 +1178,8 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
YYDPRINTF ((stderr, "Constructing syntax error message\n"));]])[ YYDPRINTF ((stderr, "Constructing syntax error message\n"));]])[
yyarg[yycount++] = yytname[yytoken]; yyarg[yycount++] = yytname[yytoken];
if (!yypact_value_is_default (yyn)) if (!yypact_value_is_default (yyn))
{]b4_lac_if([], [[ {]b4_lac_if([[
/* Start YYX at -YYN if negative to avoid negative indexes in int yyx;
YYCHECK. In other words, skip the first -YYN actions for
this state because they are default actions. */
int yyxbegin = yyn < 0 ? -yyn : 0;
/* Stay within bounds of both yycheck and yytname. */
int yychecklim = YYLAST - yyn + 1;
int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;]])[
int yyx;]b4_lac_if([[
for (yyx = 0; yyx < YYNTOKENS; ++yyx) for (yyx = 0; yyx < YYNTOKENS; ++yyx)
if (yyx != YYTERROR && yyx != YYUNDEFTOK) if (yyx != YYTERROR && yyx != YYUNDEFTOK)
@@ -1209,6 +1192,14 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
if (yy_lac_status == 1) if (yy_lac_status == 1)
continue; continue;
}]], [[ }]], [[
/* Start YYX at -YYN if negative to avoid negative indexes in
YYCHECK. In other words, skip the first -YYN actions for
this state because they are default actions. */
int yyxbegin = yyn < 0 ? -yyn : 0;
/* Stay within bounds of both yycheck and yytname. */
int yychecklim = YYLAST - yyn + 1;
int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
int yyx;
for (yyx = yyxbegin; yyx < yyxend; ++yyx) for (yyx = yyxbegin; yyx < yyxend; ++yyx)
if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
@@ -1222,7 +1213,8 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
} }
yyarg[yycount++] = yytname[yyx]; yyarg[yycount++] = yytname[yyx];
{ {
YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]); YYPTRDIFF_T yysize1 = yysize + yytnamerr (YY_NULLPTR,
yytname[yyx]);
if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM) if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)
yysize = yysize1; yysize = yysize1;
else else
@@ -1253,7 +1245,7 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
} }
{ {
YYSIZE_T yysize1 = yysize + yystrlen (yyformat); YYPTRDIFF_T yysize1 = yysize + yystrlen (yyformat);
if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM) if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)
yysize = yysize1; yysize = yysize1;
else else
@@ -1434,7 +1426,7 @@ b4_function_define([[yyparse]], [[int]], b4_parse_param)[
/* Buffer for error messages, and its allocated size. */ /* Buffer for error messages, and its allocated size. */
char yymsgbuf[128]; char yymsgbuf[128];
char *yymsg = yymsgbuf; char *yymsg = yymsgbuf;
YYSIZE_T yymsg_alloc = sizeof yymsgbuf; YYPTRDIFF_T yymsg_alloc = sizeof yymsgbuf;
#endif #endif
#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)]b4_locations_if([, yylsp -= (N)])[) #define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)]b4_locations_if([, yylsp -= (N)])[)
@@ -1455,7 +1447,7 @@ b4_function_define([[yyparse]], [[int]], b4_parse_param)[
yystacksize = YYINITDEPTH;]b4_lac_if([[ yystacksize = YYINITDEPTH;]b4_lac_if([[
yyes = yyesa; yyes = yyesa;
yyes_capacity = sizeof yyesa / sizeof *yyes; yyes_capacity = ]b4_percent_define_get([[parse.lac.es-capacity-initial]])[;
if (YYMAXDEPTH < yyes_capacity) if (YYMAXDEPTH < yyes_capacity)
yyes_capacity = YYMAXDEPTH;]])[ yyes_capacity = YYMAXDEPTH;]])[
@@ -1487,12 +1479,12 @@ yynewstate:
/*--------------------------------------------------------------------. /*--------------------------------------------------------------------.
| yynewstate -- set current state (the top of the stack) to yystate. | | yysetstate -- set current state (the top of the stack) to yystate. |
`--------------------------------------------------------------------*/ `--------------------------------------------------------------------*/
yysetstate: yysetstate:
YYDPRINTF ((stderr, "Entering state %d\n", yystate)); YYDPRINTF ((stderr, "Entering state %d\n", yystate));
YY_ASSERT (0 <= yystate && yystate < YYNSTATES); YY_ASSERT (0 <= yystate && yystate < YYNSTATES);
*yyssp = (yytype_int16) yystate; *yyssp = (yy_state_t) yystate;
if (yyss + yystacksize - 1 <= yyssp) if (yyss + yystacksize - 1 <= yyssp)
#if !defined yyoverflow && !defined YYSTACK_RELOCATE #if !defined yyoverflow && !defined YYSTACK_RELOCATE
@@ -1500,15 +1492,15 @@ yysetstate:
#else #else
{ {
/* Get the current used size of the three stacks, in elements. */ /* Get the current used size of the three stacks, in elements. */
YYSIZE_T yysize = (YYSIZE_T) (yyssp - yyss + 1); YYPTRDIFF_T yysize = yyssp - yyss + 1;
# if defined yyoverflow # if defined yyoverflow
{ {
/* Give user a chance to reallocate the stack. Use copies of /* Give user a chance to reallocate the stack. Use copies of
these so that the &'s don't force the real ones into these so that the &'s don't force the real ones into
memory. */ memory. */
YYSTYPE *yyvs1 = yyvs; yy_state_t *yyss1 = yyss;
yytype_int16 *yyss1 = yyss;]b4_locations_if([ YYSTYPE *yyvs1 = yyvs;]b4_locations_if([
YYLTYPE *yyls1 = yyls;])[ YYLTYPE *yyls1 = yyls;])[
/* Each stack pointer address is followed by the size of the /* Each stack pointer address is followed by the size of the
@@ -1516,9 +1508,9 @@ yysetstate:
conditional around just the two extra args, but that might conditional around just the two extra args, but that might
be undefined if yyoverflow is a macro. */ be undefined if yyoverflow is a macro. */
yyoverflow (YY_("memory exhausted"), yyoverflow (YY_("memory exhausted"),
&yyss1, yysize * sizeof (*yyssp), &yyss1, yysize * YYSIZEOF (*yyssp),
&yyvs1, yysize * sizeof (*yyvsp),]b4_locations_if([ &yyvs1, yysize * YYSIZEOF (*yyvsp),]b4_locations_if([
&yyls1, yysize * sizeof (*yylsp),])[ &yyls1, yysize * YYSIZEOF (*yylsp),])[
&yystacksize); &yystacksize);
yyss = yyss1; yyss = yyss1;
yyvs = yyvs1;]b4_locations_if([ yyvs = yyvs1;]b4_locations_if([
@@ -1533,9 +1525,10 @@ yysetstate:
yystacksize = YYMAXDEPTH; yystacksize = YYMAXDEPTH;
{ {
yytype_int16 *yyss1 = yyss; yy_state_t *yyss1 = yyss;
union yyalloc *yyptr = union yyalloc *yyptr =
(union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); (union yyalloc *) YYSTACK_ALLOC ((YYSIZE_T)
YYSTACK_BYTES (yystacksize));
if (! yyptr) if (! yyptr)
goto yyexhaustedlab; goto yyexhaustedlab;
YYSTACK_RELOCATE (yyss_alloc, yyss); YYSTACK_RELOCATE (yyss_alloc, yyss);
@@ -1551,8 +1544,8 @@ yysetstate:
yyvsp = yyvs + yysize - 1;]b4_locations_if([ yyvsp = yyvs + yysize - 1;]b4_locations_if([
yylsp = yyls + yysize - 1;])[ yylsp = yyls + yysize - 1;])[
YYDPRINTF ((stderr, "Stack size increased to %lu\n", YYDPRINTF ((stderr, "Stack size increased to %ld\n",
(unsigned long) yystacksize)); (long) yystacksize));
if (yyss + yystacksize - 1 <= yyssp) if (yyss + yystacksize - 1 <= yyssp)
YYABORT; YYABORT;
@@ -1642,16 +1635,15 @@ yyread_pushed_token:]])[
/* Shift the lookahead token. */ /* Shift the lookahead token. */
YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
/* Discard the shifted token. */
yychar = YYEMPTY;]b4_lac_if([[
YY_LAC_DISCARD ("shift");]])[
yystate = yyn; yystate = yyn;
YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
*++yyvsp = yylval; *++yyvsp = yylval;
YY_IGNORE_MAYBE_UNINITIALIZED_END]b4_locations_if([ YY_IGNORE_MAYBE_UNINITIALIZED_END]b4_locations_if([
*++yylsp = yylloc;])[ *++yylsp = yylloc;])[
/* Discard the shifted token. */
yychar = YYEMPTY;]b4_lac_if([[
YY_LAC_DISCARD ("shift");]])[
goto yynewstate; goto yynewstate;
@@ -1766,7 +1758,7 @@ yyerrlab:
{ {
if (yymsg != yymsgbuf) if (yymsg != yymsgbuf)
YYSTACK_FREE (yymsg); YYSTACK_FREE (yymsg);
yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc); yymsg = (char *) YYSTACK_ALLOC ((YYSIZE_T) yymsg_alloc);
if (!yymsg) if (!yymsg)
{ {
yymsg = yymsgbuf; yymsg = yymsgbuf;
+2
View File
@@ -31,3 +31,5 @@
/version.texi /version.texi
/yacc.1 /yacc.1
/relocatable.texi /relocatable.texi
/figs/*.eps
/figs/*.svg
+304 -223
View File
@@ -377,6 +377,13 @@ Invoking Bison
* Option Cross Key:: Alphabetical list of long options. * Option Cross Key:: Alphabetical list of long options.
* Yacc Library:: Yacc-compatible @code{yylex} and @code{main}. * Yacc Library:: Yacc-compatible @code{yylex} and @code{main}.
Bison Options
* Operation Modes:: Options controlling the global behavior of @command{bison}
* Diagnostics:: Options controlling the diagnostics
* Tuning the Parser:: Options changing the generated parsers
* Output Files:: Options controlling the output
Parsers Written In Other Languages Parsers Written In Other Languages
* C++ Parsers:: The interface to generate C++ parser classes * C++ Parsers:: The interface to generate C++ parser classes
@@ -455,20 +462,17 @@ Copying This Manual
@unnumbered Introduction @unnumbered Introduction
@cindex introduction @cindex introduction
@dfn{Bison} is a general-purpose parser generator that converts an @dfn{Bison} is a general-purpose parser generator that converts an annotated
annotated context-free grammar into a deterministic LR or generalized context-free grammar into a deterministic LR or generalized LR (GLR) parser
LR (GLR) parser employing LALR(1) parser tables. As an experimental employing LALR(1), IELR(1) or canonical LR(1) parser tables. Once you are
feature, Bison can also generate IELR(1) or canonical LR(1) parser proficient with Bison, you can use it to develop a wide range of language
tables. Once you are proficient with Bison, you can use it to develop parsers, from those used in simple desk calculators to complex programming
a wide range of language parsers, from those used in simple desk languages.
calculators to complex programming languages.
Bison is upward compatible with Yacc: all properly-written Yacc Bison is upward compatible with Yacc: all properly-written Yacc grammars
grammars ought to work with Bison with no change. Anyone familiar ought to work with Bison with no change. Anyone familiar with Yacc should
with Yacc should be able to use Bison with little trouble. You need be able to use Bison with little trouble. You need to be fluent in C, C++
to be fluent in C or C++ programming in order to use Bison or to or Java programming in order to use Bison or to understand this manual.
understand this manual. Java is also supported as an experimental
feature.
We begin with tutorial chapters that explain the basic concepts of We begin with tutorial chapters that explain the basic concepts of
using Bison and show three explained examples, each building on the using Bison and show three explained examples, each building on the
@@ -580,10 +584,9 @@ are called LR(1) grammars. In brief, in these grammars, it must be possible
to tell how to parse any portion of an input string with just a single token to tell how to parse any portion of an input string with just a single token
of lookahead. For historical reasons, Bison by default is limited by the of lookahead. For historical reasons, Bison by default is limited by the
additional restrictions of LALR(1), which is hard to explain simply. additional restrictions of LALR(1), which is hard to explain simply.
@xref{Mysterious Conflicts}, for more information on this. As an @xref{Mysterious Conflicts}, for more information on this. You can escape
experimental feature, you can escape these additional restrictions by these additional restrictions by requesting IELR(1) or canonical LR(1)
requesting IELR(1) or canonical LR(1) parser tables. @xref{LR Table parser tables. @xref{LR Table Construction}, to learn how.
Construction}, to learn how.
@cindex GLR parsing @cindex GLR parsing
@cindex generalized LR (GLR) parsing @cindex generalized LR (GLR) parsing
@@ -1280,8 +1283,7 @@ In addition to the @code{%dprec} and @code{%merge} directives,
GLR parsers GLR parsers
allow you to reject parses on the basis of arbitrary computations executed allow you to reject parses on the basis of arbitrary computations executed
in user code, without having Bison treat this rejection as an error in user code, without having Bison treat this rejection as an error
if there are alternative parses. (This feature is experimental and may if there are alternative parses. For example,
evolve. We welcome user feedback.) For example,
@example @example
widget: widget:
@@ -1445,13 +1447,13 @@ anything other than their usual meanings.
In some cases the Bison parser implementation file includes system In some cases the Bison parser implementation file includes system
headers, and in those cases your code should respect the identifiers headers, and in those cases your code should respect the identifiers
reserved by those headers. On some non-GNU hosts, @code{<alloca.h>}, reserved by those headers. On some non-GNU hosts, @code{<limits.h>},
@code{<malloc.h>}, @code{<stddef.h>}, and @code{<stdlib.h>} are @code{<stddef.h>}, @code{<stdint.h>} (if available), and @code{<stdlib.h>}
included as needed to declare memory allocators and related types. are included to declare memory allocators and integer types and constants.
@code{<libintl.h>} is included if message translation is in use @code{<libintl.h>} is included if message translation is in use
(@pxref{Internationalization}). Other system headers may be included (@pxref{Internationalization}). Other system headers may be included
if you define @code{YYDEBUG} to a nonzero value (@pxref{Tracing, if you define @code{YYDEBUG} (@pxref{Tracing, ,Tracing Your Parser}) or
,Tracing Your Parser}). @code{YYSTACK_USE_ALLOCA} (@pxref{Table of Symbols}) to a nonzero value.
@node Stages @node Stages
@section Stages in Using Bison @section Stages in Using Bison
@@ -2660,8 +2662,14 @@ found, a pointer to that symbol is returned; otherwise zero is returned.
@comment file: mfcalc.y: 3 @comment file: mfcalc.y: 3
@example @example
#include <stdlib.h> /* malloc. */ @group
/* The mfcalc code assumes that malloc and realloc
always succeed, and that integer calculations
never overflow. Production-quality code should
not make these assumptions. */
#include <stdlib.h> /* malloc, realloc. */
#include <string.h> /* strlen. */ #include <string.h> /* strlen. */
@end group
@group @group
symrec * symrec *
@@ -2710,16 +2718,17 @@ operators in @code{yylex}.
@comment file: mfcalc.y: 3 @comment file: mfcalc.y: 3
@example @example
#include <ctype.h> #include <ctype.h>
#include <stddef.h>
@group @group
int int
yylex (void) yylex (void)
@{ @{
int c; int c = getchar ();
/* Ignore white space, get first nonwhite character. */ /* Ignore white space, get first nonwhite character. */
while ((c = getchar ()) == ' ' || c == '\t') while (c == ' ' || c == '\t')
continue; c = getchar ();
if (c == EOF) if (c == EOF)
return 0; return 0;
@@ -2746,23 +2755,18 @@ Bison generated a definition of @code{YYSTYPE} with a member named
/* Char starts an identifier => read the name. */ /* Char starts an identifier => read the name. */
if (isalpha (c)) if (isalpha (c))
@{ @{
/* Initially make the buffer long enough static ptrdiff_t bufsize = 0;
for a 40-character symbol name. */
static size_t length = 40;
static char *symbuf = 0; static char *symbuf = 0;
@end group @end group
if (!symbuf) ptrdiff_t i = 0;
symbuf = malloc (length + 1);
int i = 0;
do do
@group @group
@{ @{
/* If buffer is full, make it bigger. */ /* If buffer is full, make it bigger. */
if (i == length) if (bufsize <= i)
@{ @{
length *= 2; bufsize = 2 * bufsize + 40;
symbuf = realloc (symbuf, length + 1); symbuf = realloc (symbuf, bufsize);
@} @}
/* Add this character to the buffer. */ /* Add this character to the buffer. */
symbuf[i++] = c; symbuf[i++] = c;
@@ -4784,9 +4788,6 @@ value. In order to force Bison to recognize @samp{name.suffix} in its
entirety as the name of a semantic value, the bracketed syntax entirety as the name of a semantic value, the bracketed syntax
@samp{$[name.suffix]} must be used. @samp{$[name.suffix]} must be used.
The named references feature is experimental. More user feedback will help
to stabilize it.
@node Declarations @node Declarations
@section Bison Declarations @section Bison Declarations
@cindex declarations, Bison @cindex declarations, Bison
@@ -5247,7 +5248,6 @@ Decl, , Freeing Discarded Symbols}).
@deffn {Directive} %printer @{ @var{code} @} @var{symbols} @deffn {Directive} %printer @{ @var{code} @} @var{symbols}
@findex %printer @findex %printer
@vindex yyo @vindex yyo
@vindex yyoutput
@c This is the same text as for %destructor. @c This is the same text as for %destructor.
Invoke the braced @var{code} whenever the parser displays one of the Invoke the braced @var{code} whenever the parser displays one of the
@var{symbols}. Within @var{code}, @code{yyo} denotes the output stream (a @var{symbols}. Within @var{code}, @code{yyo} denotes the output stream (a
@@ -5859,7 +5859,7 @@ states and what is done for each type of lookahead token in that state.
@deffn {Directive} %yacc @deffn {Directive} %yacc
Pretend the option @option{--yacc} was given, i.e., imitate Yacc, including Pretend the option @option{--yacc} was given, i.e., imitate Yacc, including
its naming conventions. @xref{Bison Options}, for more. its naming conventions. @xref{Tuning the Parser}, for more.
@end deffn @end deffn
@@ -5884,7 +5884,7 @@ delimiters) denote finite choice (e.g., a variation of a feature). String
values denote remaining cases (e.g., a file name). values denote remaining cases (e.g., a file name).
It is an error if a @var{variable} is defined by @code{%define} multiple It is an error if a @var{variable} is defined by @code{%define} multiple
times, but see @ref{Bison Options,,@option{-D @var{name}[=@var{value}]}}. times, but see @ref{Tuning the Parser,,@option{-D @var{name}[=@var{value}]}}.
@end deffn @end deffn
The rest of this section summarizes variables and values that @code{%define} The rest of this section summarizes variables and values that @code{%define}
@@ -6068,7 +6068,7 @@ Introduced in Bison 3.3 to replace @code{parser_class_name}.
@item Accepted Values: String @item Accepted Values: String
@item Default Value: @code{yy} @item Default Value: @code{YY} for Java, @code{yy} otherwise.
@item History: introduced in Bison 2.6 @item History: introduced in Bison 2.6
@end itemize @end itemize
@@ -6213,6 +6213,42 @@ introduced in Bison 3.0
@c api.token.prefix @c api.token.prefix
@c ================================================== api.token.raw
@deffn Directive {%define api.token.raw}
@itemize @bullet
@item Language(s):
all
@item Purpose:
The output files normally define the tokens with Yacc-compatible token
numbers: sequential numbers starting at 257 except for single character
tokens which stand for themselves (e.g., in ASCII, @samp{'a'} is numbered
65). The parser however uses symbol numbers assigned sequentially starting
at 3. Therefore each time the scanner returns an (external) token number,
it must be mapped to the (internal) symbol number.
When @code{api.token.raw} is set, tokens are assigned their internal number,
which saves one table lookup per token to map them from the external to the
internal number, and also saves the generation of the mapping table. The
gain is typically moderate, but in extreme cases (very simple user actions),
a 10% improvement can be observed.
When @code{api.token.raw} is set, the grammar cannot use character literals
(such as @samp{'a'}).
@item Accepted Values: Boolean.
@item Default Value:
@code{false}
@item History:
introduced in Bison 3.5. Was initially introduced in Bison 1.25 as
@samp{%raw}, but never worked and was removed in Bison 1.29.
@end itemize
@end deffn
@c api.token.raw
@c ================================================== api.value.automove @c ================================================== api.value.automove
@deffn Directive {%define api.value.automove} @deffn Directive {%define api.value.automove}
@@ -6406,9 +6442,7 @@ Obsoleted by @code{api.location.type} since Bison 2.7.
@item Language(s): all @item Language(s): all
@item Purpose: Specify the kind of states that are permitted to @item Purpose: Specify the kind of states that are permitted to
contain default reductions. @xref{Default Reductions}. (The ability to contain default reductions. @xref{Default Reductions}.
specify where default reductions should be used is experimental. More user
feedback will help to stabilize it.)
@item Accepted Values: @code{most}, @code{consistent}, @code{accepting} @item Accepted Values: @code{most}, @code{consistent}, @code{accepting}
@item Default Value: @item Default Value:
@@ -6783,7 +6817,7 @@ extern int cdebug;
Prior to Bison 2.6, a feature similar to @code{api.prefix} was provided by Prior to Bison 2.6, a feature similar to @code{api.prefix} was provided by
the obsolete directive @code{%name-prefix} (@pxref{Table of Symbols, ,Bison the obsolete directive @code{%name-prefix} (@pxref{Table of Symbols, ,Bison
Symbols}) and the option @option{--name-prefix} (@pxref{Bison Options}). Symbols}) and the option @option{--name-prefix} (@pxref{Output Files}).
@node Interface @node Interface
@chapter Parser C-Language Interface @chapter Parser C-Language Interface
@@ -8370,8 +8404,7 @@ mysterious reduce/reduce conflicts. The best way to fix all these problems
is to select a different parser table construction algorithm. Either is to select a different parser table construction algorithm. Either
IELR(1) or canonical LR(1) would suffice, but the former is more efficient IELR(1) or canonical LR(1) would suffice, but the former is more efficient
and easier to debug during development. @xref{LR Table Construction}, for and easier to debug during development. @xref{LR Table Construction}, for
details. (Bison's IELR(1) and canonical LR(1) implementations are details.
experimental. More user feedback will help to stabilize them.)
If you instead wish to work around LALR(1)'s limitations, you If you instead wish to work around LALR(1)'s limitations, you
can often fix a mysterious conflict by identifying the two parser states can often fix a mysterious conflict by identifying the two parser states
@@ -8439,9 +8472,6 @@ to tune fundamental aspects of the generated LR-based parsers. Some of
these features easily eliminate shortcomings like those mentioned above. these features easily eliminate shortcomings like those mentioned above.
Others can be helpful purely for understanding your parser. Others can be helpful purely for understanding your parser.
Most of the features discussed in this section are still experimental. More
user feedback will help to stabilize them.
@menu @menu
* LR Table Construction:: Choose a different construction algorithm. * LR Table Construction:: Choose a different construction algorithm.
* Default Reductions:: Disable default reductions. * Default Reductions:: Disable default reductions.
@@ -8669,9 +8699,6 @@ The accepted values of @var{where} are:
@item @code{consistent} @item @code{consistent}
@item @code{accepting} (default for canonical LR) @item @code{accepting} (default for canonical LR)
@end itemize @end itemize
(The ability to specify where default reductions are permitted is
experimental. More user feedback will help to stabilize it.)
@end deffn @end deffn
@node LAC @node LAC
@@ -8707,9 +8734,7 @@ Enable LAC to improve syntax error handling.
@item @code{none} (default) @item @code{none} (default)
@item @code{full} @item @code{full}
@end itemize @end itemize
(This feature is experimental. More user feedback will help to stabilize This feature is currently only available for deterministic parsers in C and C++.
it. Moreover, it is currently only available for deterministic parsers in
C.)
@end deffn @end deffn
Conceptually, the LAC mechanism is straight-forward. Whenever the parser Conceptually, the LAC mechanism is straight-forward. Whenever the parser
@@ -9983,7 +10008,7 @@ compatibility with previous versions of Bison.
@findex %define parse.trace @findex %define parse.trace
Add the @samp{%define parse.trace} directive (@pxref{%define Add the @samp{%define parse.trace} directive (@pxref{%define
Summary,,parse.trace}), or pass the @option{-Dparse.trace} option Summary,,parse.trace}), or pass the @option{-Dparse.trace} option
(@pxref{Bison Options}). This is a Bison extension, which is especially (@pxref{Tuning the Parser}). This is a Bison extension, which is especially
useful for languages that don't use a preprocessor. Unless POSIX and Yacc useful for languages that don't use a preprocessor. Unless POSIX and Yacc
portability matter to you, this is the preferred solution. portability matter to you, this is the preferred solution.
@end table @end table
@@ -10305,13 +10330,22 @@ are unique. When a long option takes an argument, like
@samp{--file-prefix}, connect the option name and the argument with @samp{--file-prefix}, connect the option name and the argument with
@samp{=}. @samp{=}.
Here is a list of options that can be used with Bison, alphabetized by Here is a list of options that can be used with Bison. It is followed by a
short option. It is followed by a cross key alphabetized by long cross key alphabetized by long option.
option.
@menu
* Operation Modes:: Options controlling the global behavior of @command{bison}
* Diagnostics:: Options controlling the diagnostics
* Tuning the Parser:: Options changing the generated parsers
* Output Files:: Options controlling the output
@end menu
@node Operation Modes
@subsection Operation Modes
Options controlling the global behavior of @command{bison}.
@c Please, keep this ordered as in 'bison --help'. @c Please, keep this ordered as in 'bison --help'.
@noindent
Operations modes:
@table @option @table @option
@item -h @item -h
@itemx --help @itemx --help
@@ -10364,29 +10398,140 @@ exp:;
See the documentation of @option{--feature=fixit} below for more details. See the documentation of @option{--feature=fixit} below for more details.
@item -y @item -f [@var{feature}]
@itemx --yacc @itemx --feature[=@var{feature}]
Act more like the traditional @command{yacc} command. This can cause Activate miscellaneous @var{feature}s. @var{Feature} can be one of:
different diagnostics to be generated (it implies @option{-Wyacc}), and may @table @code
change behavior in other minor ways. Most importantly, imitate Yacc's @item caret
output file name conventions, so that the parser implementation file is @itemx diagnostics-show-caret
called @file{y.tab.c}, and the other outputs are called @file{y.output} and Show caret errors, in a manner similar to GCC's
@file{y.tab.h}. Also, if generating a deterministic parser in C, generate @option{-fdiagnostics-show-caret}, or Clang's
@code{#define} statements in addition to an @code{enum} to associate token @option{-fcaret-diagnostics}. The location provided with the message is used
numbers with token names. Thus, the following shell script can substitute to quote the corresponding line of the source file, underlining the
for Yacc, and the Bison distribution contains such a script for important part of it with carets (@samp{^}). Here is an example, using the
compatibility with POSIX: following file @file{in.y}:
@example @example
#! /bin/sh %type <ival> exp
bison -y "$@@" %%
exp: exp '+' exp @{ $exp = $1 + $2; @};
@end example @end example
The @option{-y}/@option{--yacc} option is intended for use with traditional When invoked with @option{-fcaret} (or nothing), Bison will report:
Yacc grammars. If your grammar uses Bison extensions like
@samp{%glr-parser}, Bison might not be Yacc-compatible even if this option
is specified.
@example
@group
in.y:3.20-23: @derror{error}: ambiguous reference: '$exp'
3 | exp: exp '+' exp @{ @derror{$exp} = $1 + $2; @};
| @derror{^~~~}
@end group
@group
in.y:3.1-3: refers to: $exp at $$
3 | @dnotice{exp}: exp '+' exp @{ $exp = $1 + $2; @};
| @dnotice{^~~}
@end group
@group
in.y:3.6-8: refers to: $exp at $1
3 | exp: @dnotice{exp} '+' exp @{ $exp = $1 + $2; @};
| @dnotice{^~~}
@end group
@group
in.y:3.14-16: refers to: $exp at $3
3 | exp: exp '+' @dnotice{exp} @{ $exp = $1 + $2; @};
| @dnotice{^~~}
@end group
@group
in.y:3.32-33: @derror{error}: $2 of 'exp' has no declared type
3 | exp: exp '+' exp @{ $exp = $1 + @derror{$2}; @};
| @derror{^~}
@end group
@end example
Whereas, when invoked with @option{-fno-caret}, Bison will only report:
@example
@group
in.y:3.20-23: @derror{error}: ambiguous reference: '$exp'
in.y:3.1-3: refers to: $exp at $$
in.y:3.6-8: refers to: $exp at $1
in.y:3.14-16: refers to: $exp at $3
in.y:3.32-33: @derror{error}: $2 of 'exp' has no declared type
@end group
@end example
This option is activated by default.
@item fixit
@itemx diagnostics-parseable-fixits
Show machine-readable fixes, in a manner similar to GCC's and Clang's
@option{-fdiagnostics-parseable-fixits}.
Fix-its are generated for duplicate directives:
@example
@group
$ @kbd{cat foo.y}
%define api.prefix @{foo@}
%define api.prefix @{bar@}
%%
exp:;
@end group
@group
$ @kbd{bison -ffixit foo.y}
foo.y:2.1-24: @derror{error}: %define variable 'api.prefix' redefined
2 | @derror{%define api.prefix @{bar@}}
| @derror{^~~~~~~~~~~~~~~~~~~~~~~~}
foo.y:1.1-24: previous definition
1 | @dnotice{%define api.prefix @{foo@}}
| @dnotice{^~~~~~~~~~~~~~~~~~~~~~~~}
fix-it:"foo.y":@{2:1-2:25@}:""
foo.y: @dwarning{warning}: fix-its can be applied. Rerun with option '--update'. [@dwarning{-Wother}]
@end group
@end example
They are also generated to update deprecated directives, unless
@option{-Wno-deprecated} was given:
@example
@group
$ @kbd{cat /tmp/foo.yy}
%error-verbose
%name-prefix "foo"
%%
exp:;
@end group
@group
$ @kbd{bison foo.y}
foo.y:1.1-14: @dwarning{warning}: deprecated directive, use '%define parse.error verbose' [@dwarning{-Wdeprecated}]
1 | @dwarning{%error-verbose}
| @dwarning{^~~~~~~~~~~~~~}
foo.y:2.1-18: @dwarning{warning}: deprecated directive, use '%define api.prefix @{foo@}' [@dwarning{-Wdeprecated}]
2 | @dwarning{%name-prefix "foo"}
| @dwarning{^~~~~~~~~~~~~~~~~~}
foo.y: @dwarning{warning}: fix-its can be applied. Rerun with option '--update'. [@dwarning{-Wother}]
@end group
@end example
The fix-its are applied by @command{bison} itself when given the option
@option{-u}/@option{--update}. See its documentation above.
@item syntax-only
Do not generate the output files. The name of this feature is somewhat
misleading as more than just checking the syntax is done: every stage is run
(including checking for conflicts for instance), except the generation of
the output files.
@end table
@end table
@node Diagnostics
@subsection Diagnostics
Options controlling the diagnostics.
@c Please, keep this ordered as in 'bison --help'.
@table @code
@item -W [@var{category}] @item -W [@var{category}]
@itemx --warnings[=@var{category}] @itemx --warnings[=@var{category}]
Output warnings falling in @var{category}. @var{category} can be one Output warnings falling in @var{category}. @var{category} can be one
@@ -10541,136 +10686,40 @@ they are explicitly enabled by @option{-Werror=@var{category}}.
Deactivate the error treatment for this @var{category}. However, the warning Deactivate the error treatment for this @var{category}. However, the warning
itself won't be disabled, or enabled, by this option. itself won't be disabled, or enabled, by this option.
@item -f [@var{feature}] @item --color
@itemx --feature[=@var{feature}] Equivalent to @option{--color=always}.
Activate miscellaneous @var{feature}. @var{feature} can be one of:
@item --color=@var{when}
Control whether diagnostics are colorized, depending on @var{when}:
@table @code @table @code
@item caret @item always
@itemx diagnostics-show-caret @itemx yes
Show caret errors, in a manner similar to GCC's Enable colorized diagnostics.
@option{-fdiagnostics-show-caret}, or Clang's
@option{-fcaret-diagnostics}. The location provided with the message is used
to quote the corresponding line of the source file, underlining the
important part of it with carets (@samp{^}). Here is an example, using the
following file @file{in.y}:
@example @item never
%type <ival> exp @itemx no
%% Disable colorized diagnostics.
exp: exp '+' exp @{ $exp = $1 + $2; @};
@end example
When invoked with @option{-fcaret} (or nothing), Bison will report: @item auto @r{(default)}
@itemx tty
@example Diagnostics will be colorized if the output device is a tty, i.e. when the
@group output goes directly to a text screen or terminal emulator window.
in.y:3.20-23: @derror{error}: ambiguous reference: '$exp'
3 | exp: exp '+' exp @{ @derror{$exp} = $1 + $2; @};
| @derror{^~~~}
@end group
@group
in.y:3.1-3: refers to: $exp at $$
3 | @dnotice{exp}: exp '+' exp @{ $exp = $1 + $2; @};
| @dnotice{^~~}
@end group
@group
in.y:3.6-8: refers to: $exp at $1
3 | exp: @dnotice{exp} '+' exp @{ $exp = $1 + $2; @};
| @dnotice{^~~}
@end group
@group
in.y:3.14-16: refers to: $exp at $3
3 | exp: exp '+' @dnotice{exp} @{ $exp = $1 + $2; @};
| @dnotice{^~~}
@end group
@group
in.y:3.32-33: @derror{error}: $2 of 'exp' has no declared type
3 | exp: exp '+' exp @{ $exp = $1 + @derror{$2}; @};
| @derror{^~}
@end group
@end example
Whereas, when invoked with @option{-fno-caret}, Bison will only report:
@example
@group
in.y:3.20-23: @derror{error}: ambiguous reference: $exp
in.y:3.1-3: refers to: $exp at $$
in.y:3.6-8: refers to: $exp at $1
in.y:3.14-16: refers to: $exp at $3
in.y:3.32-33: @derror{error}: $2 of exp has no declared type
@end group
@end example
This option is activated by default.
@item fixit
@itemx diagnostics-parseable-fixits
Show machine-readable fixes, in a manner similar to GCC's and Clang's
@option{-fdiagnostics-parseable-fixits}.
Fix-its are generated for duplicate directives:
@example
@group
$ @kbd{cat foo.y}
%define api.prefix @{foo@}
%define api.prefix @{bar@}
%%
exp:;
@end group
@group
$ @kbd{bison -ffixit foo.y}
foo.y:2.1-24: @derror{error}: %define variable 'api.prefix' redefined
2 | @derror{%define api.prefix @{bar@}}
| @derror{^~~~~~~~~~~~~~~~~~~~~~~~}
foo.y:1.1-24: previous definition
1 | @dnotice{%define api.prefix @{foo@}}
| @dnotice{^~~~~~~~~~~~~~~~~~~~~~~~}
fix-it:"foo.y":@{2:1-2:25@}:""
foo.y: @dwarning{warning}: fix-its can be applied. Rerun with option '--update'. [@dwarning{-Wother}]
@end group
@end example
They are also generated to update deprecated directives, unless
@option{-Wno-deprecated} was given:
@example
@group
$ @kbd{cat /tmp/foo.yy}
%error-verbose
%name-prefix "foo"
%%
exp:;
@end group
@group
$ @kbd{bison foo.y}
foo.y:1.1-14: @dwarning{warning}: deprecated directive, use '%define parse.error verbose' [@dwarning{-Wdeprecated}]
1 | @dwarning{%error-verbose}
| @dwarning{^~~~~~~~~~~~~~}
foo.y:2.1-18: @dwarning{warning}: deprecated directive, use '%define api.prefix @{foo@}' [@dwarning{-Wdeprecated}]
2 | @dwarning{%name-prefix "foo"}
| @dwarning{^~~~~~~~~~~~~~~~~~}
foo.y: @dwarning{warning}: fix-its can be applied. Rerun with option '--update'. [@dwarning{-Wother}]
@end group
@end example
The fix-its are applied by @command{bison} itself when given the option
@option{-u}/@option{--update}. See its documentation above.
@item syntax-only
Do not generate the output files. The name of this feature is somewhat
misleading as more than just checking the syntax is done: every stage is run
(including checking for conflicts for instance), except the generation of
the output files.
@end table
@end table @end table
@noindent @item --style=@var{file}
Tuning the parser: Specifies the CSS style @var{file} to use when colorizing. It has an effect
only when the @option{--color} option is effective. The
@file{bison-default.css} file provide a good example from which to define
your own style file. See the documentation of libtextstyle for more
details.
@end table
@node Tuning the Parser
@subsection Tuning the Parser
Options changing the generated parsers.
@c Please, keep this ordered as in 'bison --help'.
@table @option @table @option
@item -t @item -t
@itemx --debug @itemx --debug
@@ -10682,9 +10731,14 @@ it is not already defined, so that the debugging facilities are compiled.
@itemx --define=@var{name}[=@var{value}] @itemx --define=@var{name}[=@var{value}]
@itemx -F @var{name}[=@var{value}] @itemx -F @var{name}[=@var{value}]
@itemx --force-define=@var{name}[=@var{value}] @itemx --force-define=@var{name}[=@var{value}]
Each of these is equivalent to @samp{%define @var{name} "@var{value}"} Each of these is equivalent to @samp{%define @var{name} @var{value}}
(@pxref{%define Summary}) except that Bison processes multiple definitions (@pxref{%define Summary}). Note that the delimiters are part of
for the same @var{name} as follows: @var{value}: @option{-Dapi.value.type=union},
@option{-Dapi.value.type=@{union@}} and @option{-Dapi.value.type="union"}
correspond to @samp{%define api.value.type union}, @samp{%define
api.value.type @{union@}} and @samp{%define api.value.type "union"}.
Bison processes multiple definitions for the same @var{name} as follows:
@itemize @itemize
@item @item
@@ -10751,11 +10805,37 @@ This is similar to how most shells resolve commands.
@item -k @item -k
@itemx --token-table @itemx --token-table
Pretend that @code{%token-table} was specified. @xref{Decl Summary}. Pretend that @code{%token-table} was specified. @xref{Decl Summary}.
@item -y
@itemx --yacc
Act more like the traditional @command{yacc} command. This can cause
different diagnostics to be generated (it implies @option{-Wyacc}), and may
change behavior in other minor ways. Most importantly, imitate Yacc's
output file name conventions, so that the parser implementation file is
called @file{y.tab.c}, and the other outputs are called @file{y.output} and
@file{y.tab.h}. Also, if generating a deterministic parser in C, generate
@code{#define} statements in addition to an @code{enum} to associate token
numbers with token names. Thus, the following shell script can substitute
for Yacc, and the Bison distribution contains such a script for
compatibility with POSIX:
@example
#! /bin/sh
bison -y "$@@"
@end example
The @option{-y}/@option{--yacc} option is intended for use with traditional
Yacc grammars. If your grammar uses Bison extensions like
@samp{%glr-parser}, Bison might not be Yacc-compatible even if this option
is specified.
@end table @end table
@noindent @node Output Files
Adjust the output: @subsection Output Files
Options controlling the output.
@c Please, keep this ordered as in 'bison --help'.
@table @option @table @option
@item --defines[=@var{file}] @item --defines[=@var{file}]
Pretend that @code{%defines} was specified, i.e., write an extra output Pretend that @code{%defines} was specified, i.e., write an extra output
@@ -11397,13 +11477,13 @@ classes will not be generated, and the user defined type will be used.
@node C++ position @node C++ position
@subsubsection C++ @code{position} @subsubsection C++ @code{position}
@deftypeop {Constructor} {position} {} position (std::string* @var{file} = nullptr, unsigned @var{line} = 1, unsigned @var{col} = 1) @deftypeop {Constructor} {position} {} position (std::string* @var{file} = nullptr, int @var{line} = 1, int @var{col} = 1)
Create a @code{position} denoting a given point. Note that @code{file} is Create a @code{position} denoting a given point. Note that @code{file} is
not reclaimed when the @code{position} is destroyed: memory managed must be not reclaimed when the @code{position} is destroyed: memory managed must be
handled elsewhere. handled elsewhere.
@end deftypeop @end deftypeop
@deftypemethod {position} {void} initialize (std::string* @var{file} = nullptr, unsigned @var{line} = 1, unsigned @var{col} = 1) @deftypemethod {position} {void} initialize (std::string* @var{file} = nullptr, int @var{line} = 1, int @var{col} = 1)
Reset the position to the given values. Reset the position to the given values.
@end deftypemethod @end deftypemethod
@@ -11414,7 +11494,7 @@ change it to @samp{@var{type}*} using @samp{%define filename_type
"@var{type}"}. "@var{type}"}.
@end deftypeivar @end deftypeivar
@deftypeivar {position} {unsigned} line @deftypeivar {position} {int} line
The line, starting at 1. The line, starting at 1.
@end deftypeivar @end deftypeivar
@@ -11423,7 +11503,7 @@ If @var{height} is not null, advance by @var{height} lines, resetting the
column number. The resulting line number cannot be less than 1. column number. The resulting line number cannot be less than 1.
@end deftypemethod @end deftypemethod
@deftypeivar {position} {unsigned} column @deftypeivar {position} {int} column
The column, starting at 1. The column, starting at 1.
@end deftypeivar @end deftypeivar
@@ -11458,11 +11538,11 @@ Create a @code{Location} from the endpoints of the range.
@end deftypeop @end deftypeop
@deftypeop {Constructor} {location} {} location (const position& @var{pos} = position()) @deftypeop {Constructor} {location} {} location (const position& @var{pos} = position())
@deftypeopx {Constructor} {location} {} location (std::string* @var{file}, unsigned @var{line}, unsigned @var{col}) @deftypeopx {Constructor} {location} {} location (std::string* @var{file}, int @var{line}, int @var{col})
Create a @code{Location} denoting an empty range located at a given point. Create a @code{Location} denoting an empty range located at a given point.
@end deftypeop @end deftypeop
@deftypemethod {location} {void} initialize (std::string* @var{file} = nullptr, unsigned @var{line} = 1, unsigned @var{col} = 1) @deftypemethod {location} {void} initialize (std::string* @var{file} = nullptr, int @var{line} = 1, int @var{col} = 1)
Reset the location to an empty range at the given values. Reset the location to an empty range at the given values.
@end deftypemethod @end deftypemethod
@@ -11642,7 +11722,7 @@ location (if enabled) being @var{yylval} and @var{yylloc}. Invocations of
Note that when using variants, the interface for @code{yylex} is the same, Note that when using variants, the interface for @code{yylex} is the same,
but @code{yylval} is handled differently. but @code{yylval} is handled differently.
Regular union-based code in Lex scanner typically look like: Regular union-based code in Lex scanner typically looks like:
@example @example
[0-9]+ @{ [0-9]+ @{
@@ -14129,7 +14209,8 @@ is recovering from a syntax error, and 0 otherwise.
@deffn {Macro} YYSTACK_USE_ALLOCA @deffn {Macro} YYSTACK_USE_ALLOCA
Macro used to control the use of @code{alloca} when the Macro used to control the use of @code{alloca} when the
deterministic parser in C needs to extend its stacks. If defined to 0, deterministic parser in C needs to extend its stacks. If defined to 0,
the parser will use @code{malloc} to extend its stacks. If defined to the parser will use @code{malloc} to extend its stacks and memory exhaustion
occurs if @code{malloc} fails (@pxref{Memory Management}). If defined to
1, the parser will use @code{alloca}. Values other than 0 and 1 are 1, the parser will use @code{alloca}. Values other than 0 and 1 are
reserved for future Bison extensions. If not defined, reserved for future Bison extensions. If not defined,
@code{YYSTACK_USE_ALLOCA} defaults to 0. @code{YYSTACK_USE_ALLOCA} defaults to 0.
@@ -14462,7 +14543,7 @@ London, Department of Computer Science, TR-00-12 (December 2000).
@c LocalWords: strncmp intval tindex lvalp locp llocp typealt YYBACKUP subrange @c LocalWords: strncmp intval tindex lvalp locp llocp typealt YYBACKUP subrange
@c LocalWords: YYEMPTY YYEOF YYRECOVERING yyclearin GE def UMINUS maybeword loc @c LocalWords: YYEMPTY YYEOF YYRECOVERING yyclearin GE def UMINUS maybeword loc
@c LocalWords: Johnstone Shamsa Sadaf Hussain Tomita TR uref YYMAXDEPTH inline @c LocalWords: Johnstone Shamsa Sadaf Hussain Tomita TR uref YYMAXDEPTH inline
@c LocalWords: YYINITDEPTH stmts ref initdcl maybeasm notype Lookahead yyoutput @c LocalWords: YYINITDEPTH stmts ref initdcl maybeasm notype Lookahead
@c LocalWords: hexflag STR exdent itemset asis DYYDEBUG YYFPRINTF args Autoconf @c LocalWords: hexflag STR exdent itemset asis DYYDEBUG YYFPRINTF args Autoconf
@c LocalWords: ypp yxx itemx tex leaderfill Troubleshouting sqrt Graphviz @c LocalWords: ypp yxx itemx tex leaderfill Troubleshouting sqrt Graphviz
@c LocalWords: hbox hss hfill tt ly yyin fopen fclose ofirst gcc ll lookahead @c LocalWords: hbox hss hfill tt ly yyin fopen fclose ofirst gcc ll lookahead
@@ -14509,7 +14590,7 @@ London, Department of Computer Science, TR-00-12 (December 2000).
@c LocalWords: Beazley's goyacc ocamlyacc SIGACT SIGPLAN colorWarning @c LocalWords: Beazley's goyacc ocamlyacc SIGACT SIGPLAN colorWarning
@c LocalWords: setcolor rgbError colorError rgbNotice colorNotice derror @c LocalWords: setcolor rgbError colorError rgbNotice colorNotice derror
@c LocalWords: colorOff maincolor inlineraw darkviolet darkcyan dwarning @c LocalWords: colorOff maincolor inlineraw darkviolet darkcyan dwarning
@c LocalWords: dnotice copyable @c LocalWords: dnotice copyable stdint ptrdiff bufsize
@c Local Variables: @c Local Variables:
@c ispell-dictionary: "american" @c ispell-dictionary: "american"
+1
View File
@@ -0,0 +1 @@
/simple.yy
+1 -1
View File
@@ -117,7 +117,7 @@ namespace yy
static int count = 0; static int count = 0;
const int stage = count; const int stage = count;
++count; ++count;
auto loc = parser::location_type{nullptr, unsigned (stage + 1), unsigned (stage + 1)}; auto loc = parser::location_type{nullptr, stage + 1, stage + 1};
if (stage == 0) if (stage == 0)
return parser::make_TEXT (make_string_uptr ("I have numbers for you."), std::move (loc)); return parser::make_TEXT (make_string_uptr ("I have numbers for you."), std::move (loc));
else if (stage < max) else if (stage < max)
+1 -1
View File
@@ -117,7 +117,7 @@ namespace yy
static int count = 0; static int count = 0;
const int stage = count; const int stage = count;
++count; ++count;
parser::location_type loc (NULLPTR, unsigned (stage + 1), unsigned (stage + 1)); parser::location_type loc (NULLPTR, stage + 1, stage + 1);
switch (stage) switch (stage)
{ {
case 0: case 0:
+3 -3
View File
@@ -15,9 +15,9 @@
lexcalcdir = $(docdir)/%D% lexcalcdir = $(docdir)/%D%
## ------ ## ## --------- ##
## Calc. ## ## LexCalc. ##
## ------ ## ## --------- ##
if FLEX_WORKS if FLEX_WORKS
check_PROGRAMS += %D%/lexcalc check_PROGRAMS += %D%/lexcalc
+1
View File
@@ -4,6 +4,7 @@
%option nodefault noinput nounput noyywrap %option nodefault noinput nounput noyywrap
%{ %{
#include <errno.h> /* errno, ERANGE */
#include <limits.h> /* INT_MIN */ #include <limits.h> /* INT_MIN */
#include <stdlib.h> /* strtol */ #include <stdlib.h> /* strtol */
+2
View File
@@ -0,0 +1,2 @@
/scan.c
/scan.h
+30 -6
View File
@@ -15,9 +15,9 @@
reccalcdir = $(docdir)/%D% reccalcdir = $(docdir)/%D%
## ------ ## ## --------- ##
## Calc. ## ## RecCalc. ##
## ------ ## ## --------- ##
if FLEX_WORKS if FLEX_WORKS
check_PROGRAMS += %D%/reccalc check_PROGRAMS += %D%/reccalc
@@ -36,16 +36,40 @@ endif FLEX_WORKS
# additional dependency. # additional dependency.
DASH = - DASH = -
%D%/reccalc$(DASH)parse.o: %D%/scan.h %D%/reccalc$(DASH)parse.o: %D%/scan.h
# Tell Make scan.o depends on parse.h, except that Make sees only
# parse.c, not parse.h. We can't use BUILT_SOURCES to this end, since
# we use the built bison.
%D%/reccalc$(DASH)scan.o: %D%/parse.c
# Likewise, but for Automake before 1.16.
%D%/examples_c_reccalc_reccalc$(DASH)parse.o: %D%/scan.h
%D%/examples_c_reccalc_reccalc$(DASH)scan.o: %D%/parse.c
## See "info automake 'Multiple Outputs'" for this rule.
%D%/scan.c %D%/scan.h: %D%/scan.stamp %D%/scan.c %D%/scan.h: %D%/scan.stamp
@test -f $@ || rm -f %D%/scan.stamp ## Recover from the removal of $@
@test -f $@ || $(MAKE) $(AM_MAKEFLAGS) %D%/scan.stamp @if test -f $@; then :; else \
trap 'rm -rf %D%/scan.lock %D%/scan.stamp' 1 2 13 15; \
## mkdir is a portable test-and-set
if mkdir %D%/scan.lock 2>/dev/null; then \
## This code is being executed by the first process.
rm -f %D%/scan.stamp; \
$(MAKE) $(AM_MAKEFLAGS) %D%/scan.stamp; \
result=$$?; rm -rf %D%/scan.lock; exit $$result; \
else \
## This code is being executed by the follower processes.
## Wait until the first process is done.
while test -d %D%/scan.lock; do sleep 1; done; \
## Succeed if and only if the first process succeeded.
test -f %D%/scan.stamp; \
fi; \
fi
%D%/scan.stamp: %D%/scan.l %D%/scan.stamp: %D%/scan.l
$(AM_V_LEX)rm -f $@ $@.tmp $(AM_V_LEX)rm -f $@ $@.tmp
$(AM_V_at)$(MKDIR_P) %D% $(AM_V_at)$(MKDIR_P) %D%
$(AM_V_at)touch $@.tmp $(AM_V_at)touch $@.tmp
$(AM_V_at)$(LEX) -o%D%/scan.c --header-file=%D%/scan.h $(srcdir)/%D%/scan.l $(AM_V_at)$(LEX) $(AM_LFLAGS) $(LFLAGS) -o%D%/scan.c --header-file=%D%/scan.h $(srcdir)/%D%/scan.l
$(AM_V_at)mv $@.tmp $@ $(AM_V_at)mv $@.tmp $@
+1 -8
View File
@@ -3,11 +3,6 @@
%define api.parser.class {Calc} %define api.parser.class {Calc}
%define parse.error verbose %define parse.error verbose
%code imports {
import std.ascii;
import std.stdio;
}
%union { %union {
int ival; int ival;
} }
@@ -102,16 +97,14 @@ class CalcLexer(R) : Lexer
// Skip initial spaces // Skip initial spaces
while (!input.empty && input.front != '\n' && isWhite (input.front)) while (!input.empty && input.front != '\n' && isWhite (input.front))
{
input.popFront; input.popFront;
}
// Handle EOF. // Handle EOF.
if (input.empty) if (input.empty)
return YYTokenType.EOF; return YYTokenType.EOF;
// Numbers. // Numbers.
if (input.front == '.' || input.front.isNumber) if (input.front.isNumber)
{ {
import std.conv : parse; import std.conv : parse;
semanticVal_.ival = input.parse!int; semanticVal_.ival = input.parse!int;
+3 -3
View File
@@ -78,9 +78,9 @@ class CalcLexer implements Calc.Lexer {
st = new StreamTokenizer (new InputStreamReader (is)); st = new StreamTokenizer (new InputStreamReader (is));
st.resetSyntax (); st.resetSyntax ();
st.eolIsSignificant (true); st.eolIsSignificant (true);
st.whitespaceChars (9, 9); st.whitespaceChars ('\t', '\t');
st.whitespaceChars (32, 32); st.whitespaceChars (' ', ' ');
st.wordChars (48, 57); st.wordChars ('0', '9');
} }
+1 -1
Submodule gnulib updated: 672663aca3...56ca994d47
+2
View File
@@ -15,4 +15,6 @@
/[email protected] /[email protected]
/insert-header.sin /insert-header.sin
/quot.sed /quot.sed
/remove-potcdate.sed
/remove-potcdate.sin /remove-potcdate.sin
/stamp-po
+30 -7
View File
@@ -16,6 +16,7 @@
/argmatch.c /argmatch.c
/argmatch.h /argmatch.h
/asnprintf.c /asnprintf.c
/assure.h
/basename-lgpl.c /basename-lgpl.c
/basename.c /basename.c
/binary-io.c /binary-io.c
@@ -38,6 +39,7 @@
/canonicalize-lgpl.c /canonicalize-lgpl.c
/careadlinkat.c /careadlinkat.c
/careadlinkat.h /careadlinkat.h
/cdefs.h
/charset.alias /charset.alias
/cloexec.c /cloexec.c
/cloexec.h /cloexec.h
@@ -51,6 +53,7 @@
/config.h /config.h
/config.in.h /config.in.h
/configmake.h /configmake.h
/diffseq.h
/dirname-lgpl.c /dirname-lgpl.c
/dirname.c /dirname.c
/dirname.h /dirname.h
@@ -89,9 +92,13 @@
/fseterr.c /fseterr.c
/fseterr.h /fseterr.h
/fstat.c /fstat.c
/fstrcmp.c
/fstrcmp.h
/fsync.c
/getdtablesize.c /getdtablesize.c
/gethrxtime.c /gethrxtime.c
/gethrxtime.h /gethrxtime.h
/getopt-cdefs.h
/getopt-cdefs.in.h /getopt-cdefs.in.h
/getopt-core.h /getopt-core.h
/getopt-ext.h /getopt-ext.h
@@ -129,8 +136,10 @@
/isnanf.c /isnanf.c
/isnanl-nolibm.h /isnanl-nolibm.h
/isnanl.c /isnanl.c
/iswblank.c
/itold.c /itold.c
/ldexpl.c /ldexpl.c
/libc-config.h
/limits.h /limits.h
/limits.in.h /limits.in.h
/localcharset.c /localcharset.c
@@ -144,6 +153,10 @@
/math.c /math.c
/math.h /math.h
/math.in.h /math.in.h
/mbchar.c
/mbchar.h
/mbfile.c
/mbfile.h
/mbrtowc.c /mbrtowc.c
/mbsinit.c /mbsinit.c
/mbswidth.c /mbswidth.c
@@ -189,6 +202,9 @@
/relocatable.c /relocatable.c
/relocatable.h /relocatable.h
/relocwrapper.c /relocwrapper.c
/rename.c
/rmdir.c
/same-inode.h
/sched.h /sched.h
/sched.in.h /sched.in.h
/setenv.c /setenv.c
@@ -264,6 +280,8 @@
/sys_types.in.h /sys_types.in.h
/sys_wait.in.h /sys_wait.in.h
/sysexits.in.h /sysexits.in.h
/textstyle.h
/textstyle.in.h
/time.h /time.h
/time.in.h /time.in.h
/timespec.c /timespec.c
@@ -300,10 +318,22 @@
/wctype.h /wctype.h
/wctype.in.h /wctype.in.h
/wcwidth.c /wcwidth.c
/windows-initguard.h
/windows-mutex.c
/windows-mutex.h
/windows-once.c
/windows-once.h
/windows-recmutex.c
/windows-recmutex.h
/windows-rwlock.c
/windows-rwlock.h
/windows-tls.c
/windows-tls.h
/xalloc-die.c /xalloc-die.c
/xalloc-oversized.h /xalloc-oversized.h
/xalloc.h /xalloc.h
/xconcat-filename.c /xconcat-filename.c
/xhash.c
/xmalloc.c /xmalloc.c
/xmemdup0.c /xmemdup0.c
/xmemdup0.h /xmemdup0.h
@@ -315,10 +345,3 @@
/xstrndup.h /xstrndup.h
/xtime.c /xtime.c
/xtime.h /xtime.h
/rename.c
/rmdir.c
/same-inode.h
/assure.h
/fsync.c
/textstyle.in.h
/xhash.c
+2
View File
@@ -1,3 +1,5 @@
/lock.c /lock.c
/lock.h /lock.h
/threadlib.c /threadlib.c
/tls.c
/tls.h
+8 -18
View File
@@ -1,5 +1,6 @@
/*~ /*~
/00gnulib.m4 /00gnulib.m4
/__inline.m4
/absolute-header.m4 /absolute-header.m4
/alloca.m4 /alloca.m4
/asm-underscore.m4 /asm-underscore.m4
@@ -7,9 +8,7 @@
/calloc.m4 /calloc.m4
/canonicalize.m4 /canonicalize.m4
/clock_time.m4 /clock_time.m4
/close-stream.m4
/close.m4 /close.m4
/closeout.m4
/codeset.m4 /codeset.m4
/config-h.m4 /config-h.m4
/configmake.m4 /configmake.m4
@@ -44,23 +43,14 @@
/getopt.m4 /getopt.m4
/getprogname.m4 /getprogname.m4
/getrusage.m4 /getrusage.m4
/gettext.m4
/gettime.m4 /gettime.m4
/gettimeofday.m4 /gettimeofday.m4
/glibc2.m4
/glibc21.m4
/gnulib-cache.m4 /gnulib-cache.m4
/gnulib-common.m4 /gnulib-common.m4
/gnulib-comp.m4 /gnulib-comp.m4
/gnulib-tool.m4 /gnulib-tool.m4
/host-cpu-c-abi.m4 /host-cpu-c-abi.m4
/iconv.m4
/include_next.m4 /include_next.m4
/intdiv0.m4
/intl.m4
/intldir.m4
/intlmacosx.m4
/intmax.m4
/intmax_t.m4 /intmax_t.m4
/inttypes-pri.m4 /inttypes-pri.m4
/inttypes.m4 /inttypes.m4
@@ -69,10 +59,12 @@
/isnand.m4 /isnand.m4
/isnanf.m4 /isnanf.m4
/isnanl.m4 /isnanl.m4
/iswblank.m4
/javacomp.m4 /javacomp.m4
/javaexec.m4 /javaexec.m4
/jm-winsz1.m4
/jm-winsz2.m4
/largefile.m4 /largefile.m4
/lcmessage.m4
/ldexp.m4 /ldexp.m4
/ldexpl.m4 /ldexpl.m4
/lib-ld.m4 /lib-ld.m4
@@ -93,6 +85,8 @@
/malloc.m4 /malloc.m4
/malloca.m4 /malloca.m4
/math_h.m4 /math_h.m4
/mbchar.m4
/mbfile.m4
/mbrtowc.m4 /mbrtowc.m4
/mbsinit.m4 /mbsinit.m4
/mbstate_t.m4 /mbstate_t.m4
@@ -104,25 +98,22 @@
/msvc-inval.m4 /msvc-inval.m4
/msvc-nothrow.m4 /msvc-nothrow.m4
/multiarch.m4 /multiarch.m4
/nls.m4
/nocrash.m4 /nocrash.m4
/non-recursive-gnulib-prefix-hack.m4 /non-recursive-gnulib-prefix-hack.m4
/obstack-printf.m4 /obstack-printf.m4
/obstack.m4 /obstack.m4
/off_t.m4 /off_t.m4
/open-cloexec.m4 /open-cloexec.m4
/open-slash.m4
/open.m4 /open.m4
/pathmax.m4 /pathmax.m4
/perror.m4 /perror.m4
/pipe2.m4 /pipe2.m4
/po.m4
/posix_spawn.m4 /posix_spawn.m4
/printf-frexp.m4 /printf-frexp.m4
/printf-frexpl.m4 /printf-frexpl.m4
/printf-posix-rpl.m4 /printf-posix-rpl.m4
/printf-posix.m4
/printf.m4 /printf.m4
/progtest.m4
/pthread_rwlock_rdlock.m4 /pthread_rwlock_rdlock.m4
/quote.m4 /quote.m4
/quotearg.m4 /quotearg.m4
@@ -177,14 +168,13 @@
/threadlib.m4 /threadlib.m4
/time_h.m4 /time_h.m4
/timespec.m4 /timespec.m4
/uintmax_t.m4 /tls.m4
/unistd-safer.m4 /unistd-safer.m4
/unistd_h.m4 /unistd_h.m4
/unlink.m4 /unlink.m4
/unlocked-io.m4 /unlocked-io.m4
/vasnprintf.m4 /vasnprintf.m4
/vfprintf-posix.m4 /vfprintf-posix.m4
/visibility.m4
/vsnprintf-posix.m4 /vsnprintf-posix.m4
/vsnprintf.m4 /vsnprintf.m4
/vsprintf-posix.m4 /vsprintf-posix.m4
-22
View File
@@ -1,22 +0,0 @@
## ----------------------------------- ##
## Check if --with-dmalloc was given. ##
## From Franc,ois Pinard ##
## ----------------------------------- ##
# serial 1
AC_DEFUN([AM_WITH_DMALLOC],
[AC_MSG_CHECKING([if malloc debugging is wanted])
AC_ARG_WITH(dmalloc,
[ --with-dmalloc use dmalloc, as in
http://www.dmalloc.com/dmalloc.tar.gz],
[if test "$withval" = yes; then
AC_MSG_RESULT(yes)
AC_DEFINE([WITH_DMALLOC],1,
[Define if using the dmalloc debugging malloc package])
LIBS="$LIBS -ldmalloc"
LDFLAGS="$LDFLAGS -g"
else
AC_MSG_RESULT(no)
fi], [AC_MSG_RESULT(no)])
])
+4 -3
View File
@@ -15,7 +15,10 @@ AC_DEFUN_ONCE([AC_PROG_LEX],
[AC_CHECK_PROGS([LEX], [flex lex], [:]) [AC_CHECK_PROGS([LEX], [flex lex], [:])
if test "x$LEX" != "x:"; then if test "x$LEX" != "x:"; then
_AC_PROG_LEX_YYTEXT_DECL _AC_PROG_LEX_YYTEXT_DECL
fi]) fi
AC_SUBST([LEX_IS_FLEX],
[`test "$ac_cv_prog_lex_is_flex" = yes && echo true || echo false`])dnl
])
# _AC_PROG_LEX_YYTEXT_DECL # _AC_PROG_LEX_YYTEXT_DECL
@@ -37,8 +40,6 @@ else
ac_cv_prog_lex_is_flex=no ac_cv_prog_lex_is_flex=no
fi fi
]) ])
AC_SUBST([LEX_IS_FLEX],
[`test "$ac_cv_prog_lex_is_flex" = yes && echo true || echo false`])dnl
cat >conftest.l <<_ACEOF[ cat >conftest.l <<_ACEOF[
%% %%
+1 -1
View File
@@ -269,7 +269,7 @@ AnnotationList__computePredecessorAnnotations (
if (item_number_is_rule_number (ritem[s->items[self_item] if (item_number_is_rule_number (ritem[s->items[self_item]
- 2])) - 2]))
{ {
unsigned rulei; int rulei;
for (rulei = s->items[self_item]; for (rulei = s->items[self_item];
!item_number_is_rule_number (ritem[rulei]); !item_number_is_rule_number (ritem[rulei]);
++rulei) ++rulei)
+1 -1
View File
@@ -25,7 +25,7 @@
# include "InadequacyList.h" # include "InadequacyList.h"
# include "state.h" # include "state.h"
typedef unsigned AnnotationIndex; typedef int AnnotationIndex;
/** /**
* A node in a list of annotations on a particular LR(0) state. Each * A node in a list of annotations on a particular LR(0) state. Each
+7 -2
View File
@@ -22,6 +22,8 @@
#include "InadequacyList.h" #include "InadequacyList.h"
#include <intprops.h>
ContributionIndex const ContributionIndex__none = -1; ContributionIndex const ContributionIndex__none = -1;
ContributionIndex const ContributionIndex__error_action = -2; ContributionIndex const ContributionIndex__error_action = -2;
@@ -31,8 +33,11 @@ InadequacyList__new_conflict (state *manifesting_state, symbol *token,
InadequacyListNodeCount *node_count) InadequacyListNodeCount *node_count)
{ {
InadequacyList *result = xmalloc (sizeof *result); InadequacyList *result = xmalloc (sizeof *result);
result->id = (*node_count)++; result->id = *node_count;
aver (*node_count != 0); IGNORE_TYPE_LIMITS_BEGIN
if (INT_ADD_WRAPV (*node_count, 1, node_count))
aver (false);
IGNORE_TYPE_LIMITS_END
result->next = NULL; result->next = NULL;
result->manifestingState = manifesting_state; result->manifestingState = manifesting_state;
result->contributionCount = bitset_count (actions); result->contributionCount = bitset_count (actions);
+1 -4
View File
@@ -27,11 +27,8 @@
/** /**
* A unique ID assigned to every \c InadequacyList node. * A unique ID assigned to every \c InadequacyList node.
*
* This must remain unsigned so that the overflow check in
* \c InadequacyList__new_conflict works properly.
*/ */
typedef unsigned long long InadequacyListNodeCount; typedef long long InadequacyListNodeCount;
/** /**
* For a conflict, each rule in the grammar can have at most one contributing * For a conflict, each rule in the grammar can have at most one contributing
+1 -1
View File
@@ -170,7 +170,7 @@ set_fderives (void)
void void
closure_new (unsigned n) closure_new (int n)
{ {
itemset = xnmalloc (n, sizeof *itemset); itemset = xnmalloc (n, sizeof *itemset);
+1 -1
View File
@@ -27,7 +27,7 @@
data so that closure can be called. n is the number of elements to data so that closure can be called. n is the number of elements to
allocate for itemset. */ allocate for itemset. */
void closure_new (unsigned n); void closure_new (int n);
/* Given the kernel (aka core) of a state (a sorted vector of item numbers /* Given the kernel (aka core) of a state (a sorted vector of item numbers
+75 -55
View File
@@ -107,46 +107,59 @@ flush (FILE *out)
| --warnings's handling. | | --warnings's handling. |
`------------------------*/ `------------------------*/
static const char * const warnings_args[] = ARGMATCH_DEFINE_GROUP (warning, warnings)
static const argmatch_warning_doc argmatch_warning_docs[] =
{ {
"none", { "conflicts-sr", N_("S/R conflicts (enabled by default)") },
"midrule-values", { "conflicts-rr", N_("R/R conflicts (enabled by default)") },
"yacc", { "deprecated", N_("obsolete constructs") },
"conflicts-sr", { "empty-rule", N_("empty rules without %empty") },
"conflicts-rr", { "midrule-values", N_("unset or unused midrule values") },
"deprecated", { "precedence", N_("useless precedence and associativity") },
"empty-rule", { "yacc", N_("incompatibilities with POSIX Yacc") },
"precedence", { "other", N_("all other warnings (enabled by default)") },
"other", { "all", N_("all the warnings except 'yacc'") },
"all", { "no-CATEGORY", N_("turn off warnings in CATEGORY") },
"error", { "none", N_("turn off all the warnings") },
"everything", { "error[=CATEGORY]", N_("treat warnings as errors") },
0 { NULL, NULL }
}; };
static const warnings warnings_types[] = static const argmatch_warning_arg argmatch_warning_args[] =
{ {
Wnone, { "none", Wnone },
Wmidrule_values, { "midrule-values", Wmidrule_values },
Wyacc, { "yacc", Wyacc },
Wconflicts_sr, { "conflicts-sr", Wconflicts_sr },
Wconflicts_rr, { "conflicts-rr", Wconflicts_rr },
Wdeprecated, { "deprecated", Wdeprecated },
Wempty_rule, { "empty-rule", Wempty_rule },
Wprecedence, { "precedence", Wprecedence },
Wother, { "other", Wother },
Wall, { "all", Wall },
Werror, { "everything", Weverything },
Weverything { NULL, Wnone }
}; };
ARGMATCH_VERIFY (warnings_args, warnings_types); const argmatch_warning_group_type argmatch_warning_group =
{
argmatch_warning_args,
argmatch_warning_docs,
N_("Warning categories include:"),
NULL
};
void
warning_usage (FILE *out)
{
argmatch_warning_usage (out);
}
void void
warning_argmatch (char const *arg, size_t no, size_t err) warning_argmatch (char const *arg, size_t no, size_t err)
{ {
int value = XARGMATCH ("--warning", arg + no + err, int value = *argmatch_warning_value ("--warning", arg + no + err);
warnings_args, warnings_types);
/* -Wnone == -Wno-everything, and -Wno-none == -Weverything. */ /* -Wnone == -Wno-everything, and -Wno-none == -Weverything. */
if (!value) if (!value)
@@ -185,7 +198,14 @@ warning_argmatch (char const *arg, size_t no, size_t err)
void void
warnings_argmatch (char *args) warnings_argmatch (char *args)
{ {
if (args) if (!args)
warning_argmatch ("all", 0, 0);
else if (STREQ (args, "help"))
{
warning_usage (stdout);
exit (EXIT_SUCCESS);
}
else
for (args = strtok (args, ","); args; args = strtok (NULL, ",")) for (args = strtok (args, ","); args; args = strtok (NULL, ","))
if (STREQ (args, "error")) if (STREQ (args, "error"))
warnings_are_errors = true; warnings_are_errors = true;
@@ -201,8 +221,6 @@ warnings_argmatch (char *args)
warning_argmatch (args, no, err); warning_argmatch (args, no, err);
} }
else
warning_argmatch ("all", 0, 0);
} }
static const char* static const char*
@@ -290,6 +308,8 @@ complain_init_color (void)
void void
complain_init (void) complain_init (void)
{ {
caret_init ();
warnings warnings_default = warnings warnings_default =
Wconflicts_sr | Wconflicts_rr | Wdeprecated | Wother; Wconflicts_sr | Wconflicts_rr | Wdeprecated | Wother;
@@ -363,16 +383,17 @@ warning_is_enabled (warnings flags)
static void static void
warnings_print_categories (warnings warn_flags, FILE *out) warnings_print_categories (warnings warn_flags, FILE *out)
{ {
for (size_t i = 0; warnings_args[i]; ++i) for (int wbit = 0; wbit < warnings_size; ++wbit)
if (warn_flags & warnings_types[i]) if (warn_flags & (1 << wbit))
{ {
severity s = warning_severity (warnings_types[i]); warnings w = 1 << wbit;
severity s = warning_severity (w);
const char* style = severity_style (s); const char* style = severity_style (s);
fputs (" [", out); fputs (" [", out);
begin_use_class (style, out); begin_use_class (style, out);
fprintf (out, "-W%s%s", fprintf (out, "-W%s%s",
s == severity_error ? "error=" : "", s == severity_error ? "error=" : "",
warnings_args[i]); argmatch_warning_argument (&w));
end_use_class (style, out); end_use_class (style, out);
fputc (']', out); fputc (']', out);
/* Display only the first match, the second is "-Wall". */ /* Display only the first match, the second is "-Wall". */
@@ -396,15 +417,15 @@ warnings_print_categories (warnings warn_flags, FILE *out)
*/ */
static static
void void
error_message (const location *loc, unsigned *indent, warnings flags, error_message (const location *loc, int *indent, warnings flags,
severity sever, const char *message, va_list args) severity sever, const char *message, va_list args)
{ {
unsigned pos = 0; int pos = 0;
if (loc) if (loc)
pos += location_print (*loc, stderr); pos += location_print (*loc, stderr);
else else
pos += fprintf (stderr, "%s", current_file ? current_file : program_name); pos += fprintf (stderr, "%s", grammar_file ? grammar_file : program_name);
pos += fprintf (stderr, ": "); pos += fprintf (stderr, ": ");
if (indent) if (indent)
@@ -449,7 +470,7 @@ error_message (const location *loc, unsigned *indent, warnings flags,
/** Raise a complaint (fatal error, error or just warning). */ /** Raise a complaint (fatal error, error or just warning). */
static void static void
complains (const location *loc, unsigned *indent, warnings flags, complains (const location *loc, int *indent, warnings flags,
const char *message, va_list args) const char *message, va_list args)
{ {
severity s = warning_severity (flags); severity s = warning_severity (flags);
@@ -477,7 +498,7 @@ complain (location const *loc, warnings flags, const char *message, ...)
} }
void void
complain_indent (location const *loc, warnings flags, unsigned *indent, complain_indent (location const *loc, warnings flags, int *indent,
const char *message, ...) const char *message, ...)
{ {
va_list args; va_list args;
@@ -487,7 +508,7 @@ complain_indent (location const *loc, warnings flags, unsigned *indent,
} }
void void
complain_args (location const *loc, warnings w, unsigned *indent, complain_args (location const *loc, warnings w, int *indent,
int argc, char *argv[]) int argc, char *argv[])
{ {
switch (argc) switch (argc)
@@ -525,24 +546,23 @@ bison_directive (location const *loc, char const *directive)
void void
deprecated_directive (location const *loc, char const *old, char const *upd) deprecated_directive (location const *loc, char const *old, char const *upd)
{ {
if (feature_flag & feature_caret)
complain (loc, Wdeprecated,
_("deprecated directive, use %s"),
quote_n (1, upd));
else
complain (loc, Wdeprecated,
_("deprecated directive: %s, use %s"),
quote (old), quote_n (1, upd));
/* Register updates only if -Wdeprecated is enabled. */
if (warning_is_enabled (Wdeprecated)) if (warning_is_enabled (Wdeprecated))
fixits_register (loc, upd); {
complain (loc, Wdeprecated,
_("deprecated directive: %s, use %s"),
quote (old), quote_n (1, upd));
if (feature_flag & feature_caret)
location_caret_suggestion (*loc, upd, stderr);
/* Register updates only if -Wdeprecated is enabled. */
fixits_register (loc, upd);
}
} }
void void
duplicate_directive (char const *directive, duplicate_directive (char const *directive,
location first, location second) location first, location second)
{ {
unsigned i = 0; int i = 0;
if (feature_flag & feature_caret) if (feature_flag & feature_caret)
complain_indent (&second, Wother, &i, _("duplicate directive")); complain_indent (&second, Wother, &i, _("duplicate directive"));
else else
@@ -556,7 +576,7 @@ void
duplicate_rule_directive (char const *directive, duplicate_rule_directive (char const *directive,
location first, location second) location first, location second)
{ {
unsigned i = 0; int i = 0;
complain_indent (&second, complaint, &i, complain_indent (&second, complaint, &i,
_("only one %s allowed per rule"), directive); _("only one %s allowed per rule"), directive);
i += SUB_INDENT; i += SUB_INDENT;
+15 -15
View File
@@ -45,14 +45,14 @@ void flush (FILE *out);
/** The bits assigned to each warning type. */ /** The bits assigned to each warning type. */
typedef enum typedef enum
{ {
warning_midrule_values, /**< Unset or unused midrule values. */ warning_conflicts_rr,
warning_conflicts_sr,
warning_deprecated,
warning_empty_rule,
warning_midrule_values,
warning_other,
warning_precedence,
warning_yacc, /**< POSIXME. */ warning_yacc, /**< POSIXME. */
warning_conflicts_sr, /**< S/R conflicts. */
warning_conflicts_rr, /**< R/R conflicts. */
warning_empty_rule, /**< Implicitly empty rules. */
warning_deprecated, /**< Obsolete constructs. */
warning_precedence, /**< Useless precedence and associativity. */
warning_other, /**< All other warnings. */
warnings_size /**< The number of warnings. Must be last. */ warnings_size /**< The number of warnings. Must be last. */
} warning_bit; } warning_bit;
@@ -60,6 +60,8 @@ typedef enum
/** Whether -Werror was set. */ /** Whether -Werror was set. */
extern bool warnings_are_errors; extern bool warnings_are_errors;
void warning_usage (FILE *out);
/** Decode a single argument from -W. /** Decode a single argument from -W.
* *
* \param arg the subarguments to decode. * \param arg the subarguments to decode.
@@ -100,16 +102,14 @@ typedef enum
{ {
Wnone = 0, /**< Issue no warnings. */ Wnone = 0, /**< Issue no warnings. */
Wmidrule_values = 1 << warning_midrule_values,
Wyacc = 1 << warning_yacc,
Wconflicts_sr = 1 << warning_conflicts_sr,
Wconflicts_rr = 1 << warning_conflicts_rr, Wconflicts_rr = 1 << warning_conflicts_rr,
Wconflicts_sr = 1 << warning_conflicts_sr,
Wdeprecated = 1 << warning_deprecated, Wdeprecated = 1 << warning_deprecated,
Wempty_rule = 1 << warning_empty_rule, Wempty_rule = 1 << warning_empty_rule,
Wprecedence = 1 << warning_precedence, Wmidrule_values = 1 << warning_midrule_values,
Wother = 1 << warning_other, Wother = 1 << warning_other,
Wprecedence = 1 << warning_precedence,
Werror = 1 << 10, /** This bit is no longer used. */ Wyacc = 1 << warning_yacc,
complaint = 1 << 11, /**< All complaints. */ complaint = 1 << 11, /**< All complaints. */
fatal = 1 << 12, /**< All fatal errors. */ fatal = 1 << 12, /**< All fatal errors. */
@@ -133,11 +133,11 @@ void complain (location const *loc, warnings flags, char const *message, ...)
__attribute__ ((__format__ (__printf__, 3, 4))); __attribute__ ((__format__ (__printf__, 3, 4)));
/** Likewise, but with an \a argc/argv interface. */ /** Likewise, but with an \a argc/argv interface. */
void complain_args (location const *loc, warnings w, unsigned *indent, void complain_args (location const *loc, warnings w, int *indent,
int argc, char *arg[]); int argc, char *arg[]);
/** 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, int *indent,
char const *message, ...) char const *message, ...)
__attribute__ ((__format__ (__printf__, 4, 5))); __attribute__ ((__format__ (__printf__, 4, 5)));
+29 -25
View File
@@ -38,7 +38,10 @@
/* -1 stands for not specified. */ /* -1 stands for not specified. */
int expected_sr_conflicts = -1; int expected_sr_conflicts = -1;
int expected_rr_conflicts = -1; int expected_rr_conflicts = -1;
static char *conflicts;
/* CONFLICTS[STATE-NUM] -- Whether that state has unresolved conflicts. */
static bool *conflicts;
static struct obstack solved_conflicts_obstack; static struct obstack solved_conflicts_obstack;
static struct obstack solved_conflicts_xml_obstack; static struct obstack solved_conflicts_xml_obstack;
@@ -73,8 +76,9 @@ log_resolution (rule *r, symbol_number token,
{ {
case shift_resolution: case shift_resolution:
case right_resolution: case right_resolution:
obstack_sgrow (&solved_conflicts_obstack, " ");
obstack_printf (&solved_conflicts_obstack, obstack_printf (&solved_conflicts_obstack,
_(" Conflict between rule %d and token %s" _("Conflict between rule %d and token %s"
" resolved as shift"), " resolved as shift"),
r->number, r->number,
symbols[token]->tag); symbols[token]->tag);
@@ -82,16 +86,18 @@ log_resolution (rule *r, symbol_number token,
case reduce_resolution: case reduce_resolution:
case left_resolution: case left_resolution:
obstack_sgrow (&solved_conflicts_obstack, " ");
obstack_printf (&solved_conflicts_obstack, obstack_printf (&solved_conflicts_obstack,
_(" Conflict between rule %d and token %s" _("Conflict between rule %d and token %s"
" resolved as reduce"), " resolved as reduce"),
r->number, r->number,
symbols[token]->tag); symbols[token]->tag);
break; break;
case nonassoc_resolution: case nonassoc_resolution:
obstack_sgrow (&solved_conflicts_obstack, " ");
obstack_printf (&solved_conflicts_obstack, obstack_printf (&solved_conflicts_obstack,
_(" Conflict between rule %d and token %s" _("Conflict between rule %d and token %s"
" resolved as an error"), " resolved as an error"),
r->number, r->number,
symbols[token]->tag); symbols[token]->tag);
@@ -376,7 +382,7 @@ set_conflicts (state *s, symbol **errors)
for (int i = 0; i < reds->num; ++i) for (int i = 0; i < reds->num; ++i)
{ {
if (!bitset_disjoint_p (reds->lookahead_tokens[i], lookahead_set)) if (!bitset_disjoint_p (reds->lookahead_tokens[i], lookahead_set))
conflicts[s->number] = 1; conflicts[s->number] = true;
bitset_or (lookahead_set, lookahead_set, reds->lookahead_tokens[i]); bitset_or (lookahead_set, lookahead_set, reds->lookahead_tokens[i]);
} }
} }
@@ -428,7 +434,7 @@ conflicts_update_state_numbers (state_number old_to_new[],
`---------------------------------------------*/ `---------------------------------------------*/
static size_t static size_t
count_state_sr_conflicts (state *s) count_state_sr_conflicts (const state *s)
{ {
transitions *trans = s->transitions; transitions *trans = s->transitions;
reductions *reds = s->reductions; reductions *reds = s->reductions;
@@ -476,7 +482,7 @@ count_sr_conflicts (void)
`-----------------------------------------------------------------*/ `-----------------------------------------------------------------*/
static size_t static size_t
count_state_rr_conflicts (state *s) count_state_rr_conflicts (const state *s)
{ {
reductions *reds = s->reductions; reductions *reds = s->reductions;
size_t res = 0; size_t res = 0;
@@ -588,24 +594,22 @@ conflicts_output (FILE *out)
{ {
bool printed_sth = false; bool printed_sth = false;
for (state_number i = 0; i < nstates; ++i) for (state_number i = 0; i < nstates; ++i)
{ if (conflicts[i])
state *s = states[i]; {
if (conflicts[i]) const state *s = states[i];
{ int src = count_state_sr_conflicts (s);
int src = count_state_sr_conflicts (s); int rrc = count_state_rr_conflicts (s);
int rrc = count_state_rr_conflicts (s); fprintf (out, _("State %d "), i);
fprintf (out, _("State %d "), i); if (src && rrc)
if (src && rrc) fprintf (out,
fprintf (out, _("conflicts: %d shift/reduce, %d reduce/reduce\n"),
_("conflicts: %d shift/reduce, %d reduce/reduce\n"), src, rrc);
src, rrc); else if (src)
else if (src) fprintf (out, _("conflicts: %d shift/reduce\n"), src);
fprintf (out, _("conflicts: %d shift/reduce\n"), src); else if (rrc)
else if (rrc) fprintf (out, _("conflicts: %d reduce/reduce\n"), rrc);
fprintf (out, _("conflicts: %d reduce/reduce\n"), rrc); printed_sth = true;
printed_sth = true; }
}
}
if (printed_sth) if (printed_sth)
fputs ("\n\n", out); fputs ("\n\n", out);
} }
+7 -6
View File
@@ -40,11 +40,9 @@ rule ***derives;
static void static void
print_derives (void) print_derives (void)
{ {
int i;
fputs ("DERIVES\n", stderr); fputs ("DERIVES\n", stderr);
for (i = ntokens; i < nsyms; i++) for (symbol_number i = ntokens; i < nsyms; ++i)
{ {
fprintf (stderr, " %s derives\n", symbols[i]->tag); fprintf (stderr, " %s derives\n", symbols[i]->tag);
for (rule **rp = derives[i - ntokens]; *rp; ++rp) for (rule **rp = derives[i - ntokens]; *rp; ++rp)
@@ -88,7 +86,7 @@ derives_compute (void)
/* Q is the storage for DERIVES[...] (DERIVES[0] = q). */ /* Q is the storage for DERIVES[...] (DERIVES[0] = q). */
rule **q = xnmalloc (nvars + nrules, sizeof *q); rule **q = xnmalloc (nvars + nrules, sizeof *q);
for (symbol_number i = ntokens; i < nsyms; i++) for (symbol_number i = ntokens; i < nsyms; ++i)
{ {
rule_list *p = dset[i - ntokens]; rule_list *p = dset[i - ntokens];
derives[i - ntokens] = q; derives[i - ntokens] = q;
@@ -111,6 +109,9 @@ derives_compute (void)
void void
derives_free (void) derives_free (void)
{ {
free (derives[0]); if (derives)
free (derives); {
free (derives[0]);
free (derives);
}
} }
-1
View File
@@ -68,7 +68,6 @@ static generated_file *generated_files = NULL;
static int generated_files_size = 0; static int generated_files_size = 0;
uniqstr grammar_file = NULL; uniqstr grammar_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'.
-3
View File
@@ -58,9 +58,6 @@ extern char *dir_prefix;
and therefore GCC warns about a name clash. */ and therefore GCC warns about a name clash. */
extern uniqstr grammar_file; extern uniqstr grammar_file;
/* The current file name. Might change with #line. */
extern uniqstr current_file;
/* The computed base for output file names. */ /* The computed base for output file names. */
extern char *all_but_ext; extern char *all_but_ext;
+1 -1
View File
@@ -91,7 +91,7 @@ fixits_register (location const *loc, char const* fix)
true); true);
fixit *f = fixit_new (loc, fix); fixit *f = fixit_new (loc, fix);
gl_sortedlist_add (fixits, (gl_listelement_compar_fn) fixit_cmp, f); gl_sortedlist_add (fixits, (gl_listelement_compar_fn) fixit_cmp, f);
if (feature_flag & feature_fixit_parsable) if (feature_flag & feature_fixit)
fixit_print (f, stderr); fixit_print (f, stderr);
} }
+263 -211
View File
@@ -68,28 +68,28 @@ 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];
typedef int* (xargmatch_fn) (const char *context, const char *arg);
/** Decode an option's key. /** Decode an option's key.
* *
* \param opt option being decoded. * \param opt option being decoded.
* \param keys array of valid subarguments. * \param xargmatch matching function.
* \param values array of corresponding (int) values. * \param all the value of the argument 'all'.
* \param all the all value. * \param flags the flags to update
* \param flags the flags to update * \param arg the subarguments to decode.
* \param arg the subarguments to decode. * 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.
* *
* 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
* flags from \c all. Thus no-none = all and no-all = none. * flags from \c all. Thus no-none = all and no-all = none.
*/ */
static void static void
flag_argmatch (const char *opt, flag_argmatch (const char *opt, xargmatch_fn xargmatch,
const char *const keys[], const int values[],
int all, int *flags, char *arg, size_t no) int all, int *flags, char *arg, size_t no)
{ {
int value = XARGMATCH (opt, arg + no, keys, values); int value = *xargmatch (opt, arg + no);
/* -rnone == -rno-all, and -rno-none == -rall. */ /* -rnone == -rno-all, and -rno-none == -rall. */
if (!value) if (!value)
@@ -104,30 +104,38 @@ flag_argmatch (const char *opt,
*flags |= value; *flags |= value;
} }
typedef void (usage_fn) (FILE *out);
/** Decode an option's set of keys. /** Decode an option's set of keys.
* *
* \param opt option being decoded (e.g., --report). * \param opt option being decoded (e.g., --report).
* \param keys array of valid subarguments. * \param xargmatch matching function.
* \param values array of corresponding (int) values. * \param usage function that implement --help for this option.
* \param all the all value. * \param all the value of the argument 'all'.
* \param flags the flags to update * \param flags the flags to update
* \param args comma separated list of effective subarguments to decode. * \param args comma separated list of effective subarguments to decode.
* If 0, then activate all the flags. * If 0, then activate all the flags.
*/ */
static void static void
flags_argmatch (const char *opt, flags_argmatch (const char *opt,
const char * const keys[], const int values[], xargmatch_fn xargmatch,
usage_fn usage,
int all, int *flags, char *args) int all, int *flags, char *args)
{ {
if (args) if (!args)
*flags |= all;
else if (STREQ (args, "help"))
{
usage (stdout);
exit (EXIT_SUCCESS);
}
else
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;
flag_argmatch (opt, keys, flag_argmatch (opt, xargmatch,
values, all, flags, args, no); all, flags, args, no);
} }
else
*flags |= all;
} }
@@ -142,116 +150,188 @@ flags_argmatch (const char *opt,
* \arg FlagName_flag the flag to update. * \arg FlagName_flag the flag to update.
*/ */
#define FLAGS_ARGMATCH(FlagName, Args, All) \ #define FLAGS_ARGMATCH(FlagName, Args, All) \
flags_argmatch ("--" #FlagName, FlagName ## _args, FlagName ## _types, \ flags_argmatch ("--" #FlagName, \
(xargmatch_fn*) argmatch_## FlagName ## _value, \
argmatch_## FlagName ## _usage, \
All, &FlagName ## _flag, Args) All, &FlagName ## _flag, Args)
/*---------------------.
| --color's handling. |
`---------------------*/
enum color
{
color_always,
color_never,
color_auto
};
ARGMATCH_DEFINE_GROUP (color, enum color)
static const argmatch_color_doc argmatch_color_docs[] =
{
{ "always", N_("colorize the output") },
{ "never", N_("don't colorize the output") },
{ "auto", N_("colorize if the output device is a tty") },
{ NULL, NULL },
};
static const argmatch_color_arg argmatch_color_args[] =
{
{ "always", color_always },
{ "yes", color_always },
{ "never", color_never },
{ "no", color_never },
{ "auto", color_auto },
{ "tty", color_auto },
{ NULL, color_always },
};
const argmatch_color_group_type argmatch_color_group =
{
argmatch_color_args,
argmatch_color_docs,
/* TRANSLATORS: Use the same translation for WHEN as in the
--color=WHEN help message. */
N_("WHEN can be one of the following:"),
NULL
};
/*----------------------. /*----------------------.
| --report's handling. | | --report's handling. |
`----------------------*/ `----------------------*/
static const char * const report_args[] = ARGMATCH_DEFINE_GROUP (report, enum report)
static const argmatch_report_doc argmatch_report_docs[] =
{ {
/* In a series of synonyms, present the most meaningful first, so { "states", N_("describe the states") },
that argmatch_valid be more readable. */ { "itemsets", N_("complete the core item sets with their closure") },
"none", { "lookaheads", N_("explicitly associate lookahead tokens to items") },
"state", "states", { "solved", N_("describe shift/reduce conflicts solving") },
"itemset", "itemsets", { "all", N_("include all the above information") },
"lookahead", "lookaheads", "look-ahead", { "none", N_("disable the report") },
"solved", { NULL, NULL },
"all",
0
}; };
static const int report_types[] = static const argmatch_report_arg argmatch_report_args[] =
{ {
report_none, { "none", report_none },
report_states, report_states, { "states", report_states },
report_states | report_itemsets, report_states | report_itemsets, { "itemsets", report_states | report_itemsets },
report_states | report_lookahead_tokens, { "lookaheads", report_states | report_lookahead_tokens },
report_states | report_lookahead_tokens, { "solved", report_states | report_solved_conflicts },
report_states | report_lookahead_tokens, { "all", report_all },
report_states | report_solved_conflicts, { NULL, report_none },
report_all
}; };
ARGMATCH_VERIFY (report_args, report_types); const argmatch_report_group_type argmatch_report_group =
{
argmatch_report_args,
argmatch_report_docs,
/* TRANSLATORS: Use the same translation for THINGS as in the
--report=THINGS help message. */
N_("THINGS is a list of comma separated words that can include:"),
NULL
};
/*---------------------. /*---------------------.
| --trace's handling. | | --trace's handling. |
`---------------------*/ `---------------------*/
static const char * const trace_args[] = ARGMATCH_DEFINE_GROUP (trace, enum trace)
static const argmatch_trace_doc argmatch_trace_docs[] =
{ {
"none - no traces", /* Meant for developers only, don't translate them. */
"locations - full display of the locations", { "none", "no traces" },
"scan - grammar scanner traces", { "locations", "full display of the locations" },
"parse - grammar parser traces", { "scan", "grammar scanner traces" },
"automaton - construction of the automaton", { "parse", "grammar parser traces" },
"bitsets - use of bitsets", { "automaton", "construction of the automaton" },
"closure - input/output of closure", { "bitsets", "use of bitsets" },
"grammar - reading, reducing the grammar", { "closure", "input/output of closure" },
"resource - memory consumption (where available)", { "grammar", "reading, reducing the grammar" },
"sets - grammar sets: firsts, nullable etc.", { "resource", "memory consumption (where available)" },
"muscles - m4 definitions passed to the skeleton", { "sets", "grammar sets: firsts, nullable etc." },
"tools - m4 invocation", { "muscles", "m4 definitions passed to the skeleton" },
"m4 - m4 traces", { "tools", "m4 invocation" },
"skeleton - skeleton postprocessing", { "m4", "m4 traces" },
"time - time consumption", { "skeleton", "skeleton postprocessing" },
"ielr - IELR conversion", { "time", "time consumption" },
"all - all of the above", { "ielr", "IELR conversion" },
0 { "all", "all of the above" },
{ NULL, NULL},
}; };
static const int trace_types[] = static const argmatch_trace_arg argmatch_trace_args[] =
{ {
trace_none, { "none", trace_none },
trace_locations, { "locations", trace_locations },
trace_scan, { "scan", trace_scan },
trace_parse, { "parse", trace_parse },
trace_automaton, { "automaton", trace_automaton },
trace_bitsets, { "bitsets", trace_bitsets },
trace_closure, { "closure", trace_closure },
trace_grammar, { "grammar", trace_grammar },
trace_resource, { "resource", trace_resource },
trace_sets, { "sets", trace_sets },
trace_muscles, { "muscles", trace_muscles },
trace_tools, { "tools", trace_tools },
trace_m4, { "m4", trace_m4 },
trace_skeleton, { "skeleton", trace_skeleton },
trace_time, { "time", trace_time },
trace_ielr, { "ielr", trace_ielr },
trace_all { "all", trace_all },
{ NULL, trace_none},
}; };
ARGMATCH_VERIFY (trace_args, trace_types); const argmatch_trace_group_type argmatch_trace_group =
{
argmatch_trace_args,
argmatch_trace_docs,
N_("TRACES is a list of comma separated words that can include:"),
NULL
};
/*-----------------------. /*-----------------------.
| --feature's handling. | | --feature's handling. |
`-----------------------*/ `-----------------------*/
static const char * const feature_args[] = ARGMATCH_DEFINE_GROUP (feature, enum feature)
static const argmatch_feature_doc argmatch_feature_docs[] =
{ {
"none", { "caret", N_("show errors with carets") },
"caret", "diagnostics-show-caret", { "fixit", N_("show machine-readable fixes") },
"fixit", "diagnostics-parseable-fixits", { "syntax-only", N_("do not generate any file") },
"syntax-only", { "all", N_("all of the above") },
"all", { "none", N_("disable all of the above") },
0 { NULL, NULL }
}; };
static const int feature_types[] = static const argmatch_feature_arg argmatch_feature_args[] =
{ {
feature_none, { "none", feature_none },
feature_caret, feature_caret, { "caret", feature_caret },
feature_fixit_parsable, feature_fixit_parsable, { "diagnostics-show-caret", feature_caret },
feature_syntax_only, { "fixit", feature_fixit },
feature_all { "diagnostics-parseable-fixits", feature_fixit },
{ "syntax-only", feature_syntax_only },
{ "all", feature_all },
{ NULL, feature_none}
}; };
ARGMATCH_VERIFY (feature_args, feature_types); const argmatch_feature_group_type argmatch_feature_group =
{
argmatch_feature_args,
argmatch_feature_docs,
/* TRANSLATORS: Use the same translation for FEATURES as in the
--feature=FEATURES help message. */
N_("FEATURES is a list of comma separated words that can include:"),
NULL
};
/*-------------------------------------------. /*-------------------------------------------.
| Display the help message and exit STATUS. | | Display the help message and exit STATUS. |
@@ -275,8 +355,7 @@ usage (int status)
printf (_("Usage: %s [OPTION]... FILE\n"), program_name); printf (_("Usage: %s [OPTION]... FILE\n"), program_name);
fputs (_("\ fputs (_("\
Generate a deterministic LR or generalized LR (GLR) parser employing\n\ Generate a deterministic LR or generalized LR (GLR) parser employing\n\
LALR(1), IELR(1), or canonical LR(1) parser tables. IELR(1) and\n\ LALR(1), IELR(1), or canonical LR(1) parser tables.\n\
canonical LR(1) support is experimental.\n\
\n\ \n\
"), stdout); "), stdout);
@@ -286,10 +365,10 @@ Mandatory arguments to long options are mandatory for short options too.\n\
fputs (_("\ fputs (_("\
The same is true for optional arguments.\n\ The same is true for optional arguments.\n\
"), stdout); "), stdout);
putc ('\n', stdout);
fputs (_("\ fputs (_("\
\n\ Operation Modes:\n\
Operation modes:\n\
-h, --help display this help and exit\n\ -h, --help display this help and exit\n\
-V, --version output version information and exit\n\ -V, --version output version information and exit\n\
--print-localedir output directory containing locale-dependent data\n\ --print-localedir output directory containing locale-dependent data\n\
@@ -297,32 +376,48 @@ Operation modes:\n\
--print-datadir output directory containing skeletons and XSLT\n\ --print-datadir output directory containing skeletons and XSLT\n\
and exit\n\ and exit\n\
-u, --update apply fixes to the source grammar file and exit\n\ -u, --update apply fixes to the source grammar file and exit\n\
-y, --yacc emulate POSIX Yacc\n\
-W, --warnings[=CATEGORY] report the warnings falling in CATEGORY\n\
-f, --feature[=FEATURES] activate miscellaneous features\n\ -f, --feature[=FEATURES] activate miscellaneous features\n\
\n\ \n\
"), stdout); "), stdout);
argmatch_feature_usage (stdout);
putc ('\n', stdout);
fputs (_("\ fputs (_("\
Parser:\n\ Diagnostics:\n\
-W, --warnings[=CATEGORY] report the warnings falling in CATEGORY\n\
--color[=WHEN] whether to colorize the diagnostics\n\
--style=FILE specify the CSS FILE for colorizer diagnostics\n\
\n\
"), stdout);
warning_usage (stdout);
putc ('\n', stdout);
argmatch_color_usage (stdout);
putc ('\n', stdout);
fputs (_("\
Tuning the 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\
-p, --name-prefix=PREFIX prepend PREFIX to the external symbols\n\ -p, --name-prefix=PREFIX prepend PREFIX to the external symbols\n\
deprecated by '-Dapi.prefix=PREFIX'\n\ deprecated by '-Dapi.prefix={PREFIX}'\n\
-l, --no-lines don't generate '#line' directives\n\ -l, --no-lines don't generate '#line' directives\n\
-k, --token-table include a table of token names\n\ -k, --token-table include a table of token names\n\
-y, --yacc emulate POSIX Yacc\n\
"), stdout); "), stdout);
putc ('\n', stdout); putc ('\n', stdout);
/* Keep -d and --defines separate so that ../build-aux/cross-options.pl /* Keep -d and --defines separate so that ../build-aux/cross-options.pl
* won't assume that -d also takes an argument. */ * won't assume that -d also takes an argument. */
fputs (_("\ fputs (_("\
Output:\n\ Output Files:\n\
--defines[=FILE] also produce a header file\n\ --defines[=FILE] also produce a header file\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\
@@ -332,53 +427,12 @@ Output:\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\
-x, --xml[=FILE] also output an XML report of the automaton\n\ -x, --xml[=FILE] also output an XML report of the automaton\n\
(the XML schema is experimental)\n\
"), stdout); "), stdout);
putc ('\n', stdout); putc ('\n', stdout);
fputs (_("\ argmatch_report_usage (stdout);
Warning categories include:\n\
'conflicts-sr' S/R conflicts (enabled by default)\n\
'conflicts-rr' R/R conflicts (enabled by default)\n\
'deprecated' obsolete constructs\n\
'empty-rule' empty rules without %empty\n\
'midrule-values' unset or unused midrule values\n\
'precedence' useless precedence and associativity\n\
'yacc' incompatibilities with POSIX Yacc\n\
'other' all other warnings (enabled by default)\n\
'all' all the warnings except 'yacc'\n\
'no-CATEGORY' turn off warnings in CATEGORY\n\
'none' turn off all the warnings\n\
'error[=CATEGORY]' treat warnings as errors\n\
"), stdout);
putc ('\n', stdout); putc ('\n', stdout);
fputs (_("\
THINGS is a list of comma separated words that can include:\n\
'state' describe the states\n\
'itemset' complete the core item sets with their closure\n\
'lookahead' explicitly associate lookahead tokens to items\n\
'solved' describe shift/reduce conflicts solving\n\
'all' include all the above information\n\
'none' disable the report\n\
"), stdout);
putc ('\n', stdout);
fputs (_("\
FEATURES is a list of comma separated words that can include:\n\
'caret', 'diagnostics-show-caret'\n\
show errors with carets\n\
'fixit', 'diagnostics-parseable-fixits'\n\
show machine-readable fixes\n\
'syntax-only'\n\
do not generate any file\n\
'all'\n\
all of the above\n\
'none'\n\
disable all of the above\n\
"), stdout);
putc ('\n', stdout);
printf (_("Report bugs to <%s>.\n"), PACKAGE_BUGREPORT); printf (_("Report bugs to <%s>.\n"), PACKAGE_BUGREPORT);
printf (_("%s home page: <%s>.\n"), PACKAGE_NAME, PACKAGE_URL); printf (_("%s home page: <%s>.\n"), PACKAGE_NAME, PACKAGE_URL);
fputs (_("General help using GNU software: " fputs (_("General help using GNU software: "
@@ -452,7 +506,7 @@ skeleton_arg (char const *arg, int prio, location loc)
void void
language_argmatch (char const *arg, int prio, location loc) language_argmatch (char const *arg, int prio, location loc)
{ {
char const *msg; char const *msg = NULL;
if (prio < language_prio) if (prio < language_prio)
{ {
@@ -467,10 +521,9 @@ language_argmatch (char const *arg, int prio, location loc)
} }
else if (language_prio == prio) else if (language_prio == prio)
msg = _("multiple language declarations are invalid"); msg = _("multiple language declarations are invalid");
else
return;
complain (&loc, complaint, msg, quotearg_colon (arg)); if (msg)
complain (&loc, complaint, msg, quotearg_colon (arg));
} }
/*----------------------. /*----------------------.
@@ -508,6 +561,7 @@ static char const short_options[] =
enum enum
{ {
COLOR_OPTION = CHAR_MAX + 1, COLOR_OPTION = CHAR_MAX + 1,
FIXED_OUTPUT_FILES_OPTION,
LOCATIONS_OPTION, LOCATIONS_OPTION,
PRINT_DATADIR_OPTION, PRINT_DATADIR_OPTION,
PRINT_LOCALEDIR_OPTION, PRINT_LOCALEDIR_OPTION,
@@ -515,6 +569,7 @@ enum
STYLE_OPTION STYLE_OPTION
}; };
/* In the same order as in usage(), and in the documentation. */
static struct option const long_options[] = static struct option const long_options[] =
{ {
/* Operation modes. */ /* Operation modes. */
@@ -523,55 +578,43 @@ static struct option const long_options[] =
{ "print-localedir", no_argument, 0, PRINT_LOCALEDIR_OPTION }, { "print-localedir", no_argument, 0, PRINT_LOCALEDIR_OPTION },
{ "print-datadir", no_argument, 0, PRINT_DATADIR_OPTION }, { "print-datadir", no_argument, 0, PRINT_DATADIR_OPTION },
{ "update", no_argument, 0, 'u' }, { "update", no_argument, 0, 'u' },
{ "warnings", optional_argument, 0, 'W' }, { "feature", optional_argument, 0, 'f' },
/* Parser. */ /* Diagnostics. */
{ "name-prefix", required_argument, 0, 'p' }, { "warnings", optional_argument, 0, 'W' },
{ "color", optional_argument, 0, COLOR_OPTION },
{ "style", optional_argument, 0, STYLE_OPTION },
/* Output. */ /* Tuning the Parser. */
{ "file-prefix", required_argument, 0, 'b' }, { "language", required_argument, 0, 'L' },
{ "output", required_argument, 0, 'o' }, { "skeleton", required_argument, 0, 'S' },
{ "output-file", required_argument, 0, 'o' }, { "debug", no_argument, 0, 't' },
{ "graph", optional_argument, 0, 'g' }, { "locations", no_argument, 0, LOCATIONS_OPTION },
{ "xml", optional_argument, 0, 'x' }, { "define", required_argument, 0, 'D' },
{ "force-define", required_argument, 0, 'F' },
{ "name-prefix", required_argument, 0, 'p' },
{ "no-lines", no_argument, 0, 'l' },
{ "token-table", no_argument, 0, 'k' },
{ "yacc", no_argument, 0, 'y' },
/* Output Files. */
{ "defines", optional_argument, 0, 'd' },
{ "report", required_argument, 0, 'r' }, { "report", required_argument, 0, 'r' },
{ "report-file", required_argument, 0, REPORT_FILE_OPTION }, { "report-file", required_argument, 0, REPORT_FILE_OPTION },
{ "verbose", no_argument, 0, 'v' }, { "verbose", no_argument, 0, 'v' },
{ "file-prefix", required_argument, 0, 'b' },
{ "output", required_argument, 0, 'o' },
{ "graph", optional_argument, 0, 'g' },
{ "xml", optional_argument, 0, 'x' },
/* Hidden. */ /* Hidden. */
{ "trace", optional_argument, 0, 'T' }, { "fixed-output-files", no_argument, 0, FIXED_OUTPUT_FILES_OPTION },
{ "color", optional_argument, 0, COLOR_OPTION }, { "output-file", required_argument, 0, 'o' },
{ "style", optional_argument, 0, STYLE_OPTION }, { "trace", optional_argument, 0, 'T' },
/* Output. */
{ "defines", optional_argument, 0, 'd' },
{ "feature", optional_argument, 0, 'f' },
/* Operation modes. */
{ "fixed-output-files", no_argument, 0, 'y' },
{ "yacc", no_argument, 0, 'y' },
/* Parser. */
{ "debug", no_argument, 0, 't' },
{ "define", required_argument, 0, 'D' },
{ "force-define", required_argument, 0, 'F' },
{ "locations", no_argument, 0, LOCATIONS_OPTION },
{ "no-lines", no_argument, 0, 'l' },
{ "skeleton", required_argument, 0, 'S' },
{ "language", required_argument, 0, 'L' },
{ "token-table", no_argument, 0, 'k' },
{0, 0, 0, 0} {0, 0, 0, 0}
}; };
/* Under DOS, there is no difference on the case. This can be
troublesome when looking for '.tab' etc. */
#ifdef MSDOS
# define AS_FILE_NAME(File) (strlwr (File), (File))
#else
# define AS_FILE_NAME(File) (File)
#endif
/* Build a location for the current command line argument. */ /* Build a location for the current command line argument. */
static static
location location
@@ -603,6 +646,8 @@ getargs_colors (int argc, char *argv[])
else else
handle_color_option (color); handle_color_option (color);
} }
else if (STREQ ("--color", arg))
handle_color_option (NULL);
else if (STRPREFIX_LIT ("--style=", arg)) else if (STRPREFIX_LIT ("--style=", arg))
{ {
const char *style = arg + strlen ("--style="); const char *style = arg + strlen ("--style=");
@@ -621,6 +666,8 @@ getargs (int argc, char *argv[])
int c; int c;
while ((c = getopt_long (argc, argv, short_options, long_options, NULL)) while ((c = getopt_long (argc, argv, short_options, long_options, NULL))
!= -1) != -1)
{
location loc = command_line_location ();
switch (c) switch (c)
{ {
/* ASCII Sorting for short options (i.e., upper case then /* ASCII Sorting for short options (i.e., upper case then
@@ -653,7 +700,7 @@ getargs (int argc, char *argv[])
*end = 0; *end = 0;
} }
} }
muscle_percent_define_insert (name, command_line_location (), muscle_percent_define_insert (name, loc,
kind, 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);
@@ -661,13 +708,11 @@ getargs (int argc, char *argv[])
break; break;
case 'L': case 'L':
language_argmatch (optarg, command_line_prio, language_argmatch (optarg, command_line_prio, loc);
command_line_location ());
break; break;
case 'S': case 'S':
skeleton_arg (AS_FILE_NAME (optarg), command_line_prio, skeleton_arg (optarg, command_line_prio, loc);
command_line_location ());
break; break;
case 'T': case 'T':
@@ -687,7 +732,7 @@ getargs (int argc, char *argv[])
break; break;
case 'b': case 'b':
spec_file_prefix = AS_FILE_NAME (optarg); spec_file_prefix = optarg;
break; break;
case 'd': case 'd':
@@ -696,7 +741,7 @@ getargs (int argc, char *argv[])
if (optarg) if (optarg)
{ {
free (spec_header_file); free (spec_header_file);
spec_header_file = xstrdup (AS_FILE_NAME (optarg)); spec_header_file = xstrdup (optarg);
} }
break; break;
@@ -705,7 +750,7 @@ getargs (int argc, char *argv[])
if (optarg) if (optarg)
{ {
free (spec_graph_file); free (spec_graph_file);
spec_graph_file = xstrdup (AS_FILE_NAME (optarg)); spec_graph_file = xstrdup (optarg);
} }
break; break;
@@ -721,7 +766,7 @@ getargs (int argc, char *argv[])
break; break;
case 'o': case 'o':
spec_outfile = AS_FILE_NAME (optarg); spec_outfile = optarg;
break; break;
case 'p': case 'p':
@@ -734,7 +779,7 @@ getargs (int argc, char *argv[])
case 't': case 't':
muscle_percent_define_insert ("parse.trace", muscle_percent_define_insert ("parse.trace",
command_line_location (), loc,
muscle_keyword, "", muscle_keyword, "",
MUSCLE_PERCENT_DEFINE_D); MUSCLE_PERCENT_DEFINE_D);
break; break;
@@ -753,22 +798,28 @@ getargs (int argc, char *argv[])
if (optarg) if (optarg)
{ {
free (spec_xml_file); free (spec_xml_file);
spec_xml_file = xstrdup (AS_FILE_NAME (optarg)); spec_xml_file = xstrdup (optarg);
} }
break; break;
case 'y': case 'y':
warning_argmatch ("yacc", 0, 0); warning_argmatch ("yacc", 0, 0);
yacc_loc = command_line_location (); yacc_loc = loc;
break; break;
case COLOR_OPTION: case COLOR_OPTION:
/* Handled in getargs_colors. */ /* Handled in getargs_colors. */
break; break;
case FIXED_OUTPUT_FILES_OPTION:
complain (&loc, Wdeprecated,
_("deprecated option: %s, use %s"),
quote ("--fixed-output-files"), quote_n (1, "-o y.tab.c"));
spec_outfile = "y.tab.c";
break;
case LOCATIONS_OPTION: case LOCATIONS_OPTION:
muscle_percent_define_ensure ("locations", muscle_percent_define_ensure ("locations", loc, true);
command_line_location (), true);
break; break;
case PRINT_LOCALEDIR_OPTION: case PRINT_LOCALEDIR_OPTION:
@@ -781,7 +832,7 @@ getargs (int argc, char *argv[])
case REPORT_FILE_OPTION: case REPORT_FILE_OPTION:
free (spec_verbose_file); free (spec_verbose_file);
spec_verbose_file = xstrdup (AS_FILE_NAME (optarg)); spec_verbose_file = xstrdup (optarg);
break; break;
case STYLE_OPTION: case STYLE_OPTION:
@@ -791,6 +842,7 @@ getargs (int argc, char *argv[])
default: default:
usage (EXIT_FAILURE); usage (EXIT_FAILURE);
} }
}
if (argc - optind != 1) if (argc - optind != 1)
{ {
@@ -801,7 +853,7 @@ getargs (int argc, char *argv[])
usage (EXIT_FAILURE); usage (EXIT_FAILURE);
} }
current_file = grammar_file = uniqstr_new (argv[optind]); grammar_file = uniqstr_new (argv[optind]);
MUSCLE_INSERT_C_STRING ("file_name", grammar_file); MUSCLE_INSERT_C_STRING ("file_name", grammar_file);
} }
+1 -1
View File
@@ -118,7 +118,7 @@ enum feature
{ {
feature_none = 0, /**< No additional feature. */ feature_none = 0, /**< No additional feature. */
feature_caret = 1 << 0, /**< Output errors with carets. */ feature_caret = 1 << 0, /**< Output errors with carets. */
feature_fixit_parsable = 1 << 1, /**< Issue instructions to fix the sources. */ feature_fixit = 1 << 1, /**< Issue instructions to fix the sources. */
feature_syntax_only = 1 << 2, /**< Don't generate output. */ feature_syntax_only = 1 << 2, /**< Don't generate output. */
feature_all = ~0 /**< All above features. */ feature_all = ~0 /**< All above features. */
}; };
+4 -4
View File
@@ -32,7 +32,7 @@
/* Comments for these variables are in gram.h. */ /* Comments for these variables are in gram.h. */
item_number *ritem = NULL; item_number *ritem = NULL;
unsigned nritems = 0; int nritems = 0;
rule *rules = NULL; rule *rules = NULL;
rule_number nrules = 0; rule_number nrules = 0;
@@ -165,7 +165,7 @@ void
ritem_print (FILE *out) ritem_print (FILE *out)
{ {
fputs ("RITEM\n", out); fputs ("RITEM\n", out);
for (unsigned i = 0; i < nritems; ++i) for (int i = 0; i < nritems; ++i)
if (ritem[i] >= 0) if (ritem[i] >= 0)
fprintf (out, " %s", symbols[ritem[i]]->tag); fprintf (out, " %s", symbols[ritem[i]]->tag);
else else
@@ -280,8 +280,8 @@ grammar_dump (FILE *out, const char *title)
for (rule_number i = 0; i < nrules + nuseless_productions; ++i) for (rule_number i = 0; i < nrules + nuseless_productions; ++i)
{ {
rule const *rule_i = &rules[i]; rule const *rule_i = &rules[i];
unsigned const rhs_itemno = rule_i->rhs - ritem; int const rhs_itemno = rule_i->rhs - ritem;
unsigned length = rule_rhs_length (rule_i); int length = rule_rhs_length (rule_i);
aver (item_number_as_rule_number (rule_i->rhs[length] == i)); aver (item_number_as_rule_number (rule_i->rhs[length] == i));
fprintf (out, "%3d (%2d, %2d, %2s, %2s) %2d -> (%2u-%2u)", fprintf (out, "%3d (%2d, %2d, %2s, %2s) %2d -> (%2u-%2u)",
i, i,
+1 -1
View File
@@ -115,7 +115,7 @@ extern int nvars;
typedef int item_number; typedef int item_number;
# define ITEM_NUMBER_MAX INT_MAX # define ITEM_NUMBER_MAX INT_MAX
extern item_number *ritem; extern item_number *ritem;
extern unsigned nritems; extern int nritems;
/* There is weird relationship between OT1H item_number and OTOH /* There is weird relationship between OT1H item_number and OTOH
symbol_number and rule_number: we store the latter in symbol_number and rule_number: we store the latter in
+4 -4
View File
@@ -78,7 +78,7 @@ static bitset
ielr_compute_ritem_sees_lookahead_set (void) ielr_compute_ritem_sees_lookahead_set (void)
{ {
bitset result = bitset_create (nritems, BITSET_FIXED); bitset result = bitset_create (nritems, BITSET_FIXED);
unsigned i = nritems-1; int i = nritems-1;
while (0 < i) while (0 < i)
{ {
--i; --i;
@@ -418,7 +418,7 @@ ielr_item_has_lookahead (state *s, symbol_number lhs, size_t item,
top-level invocation), go get it. */ top-level invocation), go get it. */
if (!lhs) if (!lhs)
{ {
unsigned i; int i;
for (i = s->items[item]; for (i = s->items[item];
!item_number_is_rule_number (ritem[i]); !item_number_is_rule_number (ritem[i]);
++i) ++i)
@@ -496,7 +496,7 @@ ielr_compute_annotation_lists (bitsetv follow_kernel_items,
AnnotationIndex *annotation_counts = AnnotationIndex *annotation_counts =
xnmalloc (nstates, sizeof *annotation_counts); xnmalloc (nstates, sizeof *annotation_counts);
ContributionIndex max_contributions = 0; ContributionIndex max_contributions = 0;
unsigned total_annotations = 0; int total_annotations = 0;
*inadequacy_listsp = xnmalloc (nstates, sizeof **inadequacy_listsp); *inadequacy_listsp = xnmalloc (nstates, sizeof **inadequacy_listsp);
*annotation_listsp = xnmalloc (nstates, sizeof **annotation_listsp); *annotation_listsp = xnmalloc (nstates, sizeof **annotation_listsp);
@@ -633,7 +633,7 @@ ielr_compute_lookaheads (bitsetv follow_kernel_items, bitsetv always_follows,
{ {
if (item_number_is_rule_number (ritem[t->items[t_item] - 2])) if (item_number_is_rule_number (ritem[t->items[t_item] - 2]))
{ {
unsigned rule_item; int rule_item;
for (rule_item = t->items[t_item]; for (rule_item = t->items[t_item];
!item_number_is_rule_number (ritem[rule_item]); !item_number_is_rule_number (ritem[rule_item]);
++rule_item) ++rule_item)
+15
View File
@@ -550,6 +550,14 @@ lookahead_tokens_print (FILE *out)
void void
lalr (void) lalr (void)
{ {
if (trace_flag & trace_automaton)
{
fputc ('\n', stderr);
begin_use_class ("trace0", stderr);
fprintf (stderr, "lalr: begin");
end_use_class ("trace0", stderr);
fputc ('\n', stderr);
}
initialize_LA (); initialize_LA ();
set_goto_map (); set_goto_map ();
initialize_goto_follows (); initialize_goto_follows ();
@@ -560,6 +568,13 @@ lalr (void)
if (trace_flag & trace_sets) if (trace_flag & trace_sets)
lookahead_tokens_print (stderr); lookahead_tokens_print (stderr);
if (trace_flag & trace_automaton)
{
begin_use_class ("trace0", stderr);
fprintf (stderr, "lalr: done");
end_use_class ("trace0", stderr);
fputc ('\n', stderr);
}
} }
+283 -84
View File
@@ -21,10 +21,18 @@
#include <config.h> #include <config.h>
#include "system.h" #include "system.h"
#include <mbfile.h>
#include <mbswidth.h> #include <mbswidth.h>
#include <quotearg.h> #include <quotearg.h>
#include <stdio.h> /* fileno */ #include <stdio.h> /* fileno */
#include <sys/ioctl.h>
#include <sys/stat.h> /* fstat */ #include <sys/stat.h> /* fstat */
#include <termios.h>
#ifdef WINSIZE_IN_PTEM
# include <sys/stream.h>
# include <sys/ptem.h>
#endif
#include "complain.h" #include "complain.h"
#include "getargs.h" #include "getargs.h"
@@ -32,6 +40,49 @@
location const empty_loc = EMPTY_LOCATION_INIT; location const empty_loc = EMPTY_LOCATION_INIT;
static int
min_int (int a, int b)
{
return a < b ? a : b;
}
static int
max_int (int a, int b)
{
return a >= b ? a : b;
}
/* The terminal width. Not less than 40. */
static int
columns (void)
{
const char *cp = getenv ("COLUMNS");
int res = 80;
if (cp && *cp)
{
long l = strtol (cp, NULL, 10);
res = 0 <= l && l <= INT_MAX ? l : INT_MAX;
}
else
{
#ifdef TIOCGWINSZ
struct winsize ws;
if (ioctl (STDERR_FILENO, TIOCGWINSZ, &ws) != -1
&& 0 < ws.ws_col && ws.ws_col == (size_t) ws.ws_col)
res = ws.ws_col;
#endif
}
return max_int (res, 40);
}
/* Available screen width. */
static int screen_width = 80;
/* The ellipsis symbol to use for this locale, and the number of
screen-columns it uses. */
static const char *ellipsis = "...";
static int ellipsize = 3;
/* If BUF is null, add BUFSIZE (which in this case must be less than /* If BUF is null, add BUFSIZE (which in this case must be less than
INT_MAX) to COLUMN; otherwise, add mbsnwidth (BUF, BUFSIZE, 0) to INT_MAX) to COLUMN; otherwise, add mbsnwidth (BUF, BUFSIZE, 0) to
COLUMN. If an overflow occurs, return INT_MAX. */ COLUMN. If an overflow occurs, return INT_MAX. */
@@ -46,11 +97,8 @@ add_column_width (int column, char const *buf, size_t bufsize)
return column <= INT_MAX - width ? column + width : INT_MAX; return column <= INT_MAX - width ? column + width : INT_MAX;
} }
/* Set *LOC and adjust scanner cursor to account for token TOKEN of static void
size SIZE. */ boundary_compute (boundary *cur, char const *token, size_t size)
void
location_compute (location *loc, boundary *cur, char const *token, size_t size)
{ {
int line = cur->line; int line = cur->line;
int column = cur->column; int column = cur->column;
@@ -59,8 +107,6 @@ location_compute (location *loc, boundary *cur, char const *token, size_t size)
char const *p = token; char const *p = token;
char const *lim = token + size; char const *lim = token + size;
loc->start = *cur;
for (p = token; p < lim; ++p) for (p = token; p < lim; ++p)
switch (*p) switch (*p)
{ {
@@ -82,22 +128,34 @@ location_compute (location *loc, boundary *cur, char const *token, size_t size)
byte += byte < INT_MAX; byte += byte < INT_MAX;
break; break;
} }
column = add_column_width (column, p0, p - p0);
cur->line = line; cur->line = line;
cur->column = column = add_column_width (column, p0, p - p0); cur->column = column;
cur->byte = byte; cur->byte = byte;
}
/* Set *LOC and adjust scanner cursor to account for token TOKEN of
size SIZE. */
void
location_compute (location *loc, boundary *cur, char const *token, size_t size)
{
loc->start = *cur;
boundary_compute (cur, token, size);
loc->end = *cur; loc->end = *cur;
if (line == INT_MAX && loc->start.line != INT_MAX) if (loc->end.line == INT_MAX && loc->start.line != INT_MAX)
complain (loc, Wother, _("line number overflow")); complain (loc, Wother, _("line number overflow"));
if (column == INT_MAX && loc->start.column != INT_MAX) if (loc->end.column == INT_MAX && loc->start.column != INT_MAX)
complain (loc, Wother, _("column number overflow")); complain (loc, Wother, _("column number overflow"));
if (byte == INT_MAX && loc->start.byte != INT_MAX) /* TRANSLATORS: we are counting bytes, and there are too many. */
if (loc->end.byte == INT_MAX && loc->start.byte != INT_MAX)
complain (loc, Wother, _("byte number overflow")); complain (loc, Wother, _("byte number overflow"));
} }
static unsigned static int
boundary_print (boundary const *b, FILE *out) boundary_print (boundary const *b, FILE *out)
{ {
return fprintf (out, "%s:%d.%d@%d", return fprintf (out, "%s:%d.%d@%d",
@@ -105,10 +163,10 @@ boundary_print (boundary const *b, FILE *out)
b->line, b->column, b->byte); b->line, b->column, b->byte);
} }
unsigned int
location_print (location loc, FILE *out) location_print (location loc, FILE *out)
{ {
unsigned res = 0; int res = 0;
if (trace_flag & trace_locations) if (trace_flag & trace_locations)
{ {
res += boundary_print (&loc.start, out); res += boundary_print (&loc.start, out);
@@ -120,10 +178,10 @@ location_print (location loc, FILE *out)
int end_col = 0 != loc.end.column ? loc.end.column - 1 : 0; int end_col = 0 != loc.end.column ? loc.end.column - 1 : 0;
res += fprintf (out, "%s", res += fprintf (out, "%s",
quotearg_n_style (3, escape_quoting_style, loc.start.file)); quotearg_n_style (3, escape_quoting_style, loc.start.file));
if (0 <= loc.start.line) if (0 < loc.start.line)
{ {
res += fprintf (out, ":%d", loc.start.line); res += fprintf (out, ":%d", loc.start.line);
if (0 <= loc.start.column) if (0 < loc.start.column)
res += fprintf (out, ".%d", loc.start.column); res += fprintf (out, ".%d", loc.start.column);
} }
if (loc.start.file != loc.end.file) if (loc.start.file != loc.end.file)
@@ -131,14 +189,14 @@ location_print (location loc, FILE *out)
res += fprintf (out, "-%s", res += fprintf (out, "-%s",
quotearg_n_style (3, escape_quoting_style, quotearg_n_style (3, escape_quoting_style,
loc.end.file)); loc.end.file));
if (0 <= loc.end.line) if (0 < loc.end.line)
{ {
res += fprintf (out, ":%d", loc.end.line); res += fprintf (out, ":%d", loc.end.line);
if (0 <= end_col) if (0 <= end_col)
res += fprintf (out, ".%d", end_col); res += fprintf (out, ".%d", end_col);
} }
} }
else if (0 <= loc.end.line) else if (0 < loc.end.line)
{ {
if (loc.start.line < loc.end.line) if (loc.start.line < loc.end.line)
{ {
@@ -159,137 +217,264 @@ location_print (location loc, FILE *out)
same file all over for each error. */ same file all over for each error. */
static struct static struct
{ {
FILE *source; /* Raw input file. */
/* The last file we tried to open. If non NULL, but SOURCE is NULL, FILE *file;
it means this file is special and should not be quoted. */ /* Input file as a stream of multibyte characters. */
uniqstr file; mb_file_t mbfile;
size_t line; /* The position within the last file we quoted. If POS.FILE is non
/* Offset in SOURCE where line LINE starts. */ NULL, but FILE is NULL, it means this file is special and should
not be quoted. */
boundary pos;
/* Offset in FILE of the current line (i.e., where line POS.LINE
starts). */
size_t offset; size_t offset;
/* Length of the current line. */
int line_len;
/* Given the initial column to display, the offset (number of
characters to skip at the beginning of the line). */
int skip;
/* Available width to quote the source file. Eight chars are
consumed by the left-margin (with line number). */
int width;
} caret_info; } caret_info;
void void caret_init (void)
caret_free ()
{ {
if (caret_info.source) screen_width = columns ();
{ /* TRANSLATORS: This is used when a line is too long, and is
fclose (caret_info.source); displayed truncated. Use an ellipsis appropriate for your
caret_info.source = NULL; language, remembering that "" (U+2026 HORIZONTAL ELLIPSIS)
} sometimes misdisplays and that "..." (three ASCII periods) is a
safer choice in some locales. */
ellipsis = _("...");
ellipsize = mbswidth (ellipsis, 0);
} }
void void
location_caret (location loc, const char *style, FILE *out) caret_free (void)
{ {
if (loc.start.column == -1 || loc.start.line == -1) if (caret_info.file)
return;
/* If a different source than before, close and let the rest open
the new one. */
if (caret_info.file && caret_info.file != loc.start.file)
{ {
caret_free (); fclose (caret_info.file);
caret_info.file = NULL; caret_info.file = NULL;
} }
if (!caret_info.file) }
/* Open FILE for quoting, if needed, and if possible. Return whether
the file can quoted. */
static bool
caret_set_file (const char *file)
{
/* If a different file than before, close and let the rest open
the new one. */
if (caret_info.pos.file && caret_info.pos.file != file)
{ {
caret_info.file = loc.start.file; caret_free ();
if ((caret_info.source = fopen (caret_info.file, "r"))) caret_info.pos.file = NULL;
}
if (!caret_info.pos.file)
{
caret_info.pos.file = file;
if ((caret_info.file = fopen (caret_info.pos.file, "r")))
{ {
/* If the file is not regular (imagine #line 1 "/dev/stdin" /* If the file is not regular (imagine #line 1 "/dev/stdin"
in the input file for instance), don't try to quote the in the input file for instance), don't try to quote the
source. Keep caret_info.file set so that we don't try to file. Keep caret_info.file set so that we don't try to
open it again, but leave caret_info.source NULL so that open it again, but leave caret_info.file NULL so that we
we don't try to quote it. */ don't try to quote it. */
struct stat buf; struct stat buf;
if (fstat (fileno (caret_info.source), &buf) == 0 if (fstat (fileno (caret_info.file), &buf) == 0
&& buf.st_mode & S_IFREG) && buf.st_mode & S_IFREG)
{ {
caret_info.line = 1; caret_info.pos.line = 1;
caret_info.offset = 0; mbf_init (caret_info.mbfile, caret_info.file);
} }
else else
caret_free (); caret_free ();
} }
} }
if (!caret_info.source) return !!caret_info.file;
return; }
/* Getc, but smash \r\n as \n. */
static void
caret_getc_internal (mbchar_t *res)
{
mbf_getc (*res, caret_info.mbfile);
if (mb_iseq (*res, '\r'))
{
mbchar_t c;
mbf_getc (c, caret_info.mbfile);
if (mb_iseq (c, '\n'))
mb_copy (res, &c);
else
mbf_ungetc (c, caret_info.mbfile);
}
}
#define caret_getc(Var) caret_getc_internal(&Var)
/* Move CARET_INFO (which has a valid FILE) to the line number LINE.
Compute and cache that line's length in CARET_INFO.LINE_LEN.
Return whether succesful.*/
static bool
caret_set_line (int line)
{
/* If the line we want to quote is seekable (the same line as the previous /* 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, location), just seek it. If it was a previous line, we lost track of it,
so return to the start of file. */ so return to the start of file. */
if (caret_info.line <= loc.start.line) if (line < caret_info.pos.line)
fseek (caret_info.source, caret_info.offset, SEEK_SET);
else
{ {
caret_info.line = 1; caret_info.pos.line = 1;
caret_info.offset = 0; caret_info.offset = 0;
fseek (caret_info.source, caret_info.offset, SEEK_SET);
} }
if (fseek (caret_info.file, caret_info.offset, SEEK_SET))
return false;
/* If this is the same line as the previous one, we are done. */
if (line < caret_info.pos.line)
return true;
/* Advance to the line's position, keeping track of the offset. */ /* Advance to the line's position, keeping track of the offset. */
while (caret_info.line < loc.start.line) while (caret_info.pos.line < line)
{ {
int c = getc (caret_info.source); mbchar_t c;
if (c == EOF) caret_getc (c);
if (mb_iseof (c))
/* Something is wrong, that line number does not exist. */ /* Something is wrong, that line number does not exist. */
return; return false;
caret_info.line += c == '\n'; caret_info.pos.line += mb_iseq (c, '\n');
} }
caret_info.offset = ftell (caret_info.source); caret_info.offset = ftell (caret_info.file);
caret_info.pos.column = 1;
/* Reset mbf's internal state.
FIXME: should be done in mbfile. */
caret_info.mbfile.eof_seen = 0;
/* Find the number of columns of this line. */
while (true)
{
mbchar_t c;
caret_getc (c);
if (mb_iseof (c) || mb_iseq (c, '\n'))
break;
boundary_compute (&caret_info.pos, mb_ptr (c), mb_len (c));
}
caret_info.line_len = caret_info.pos.column;
/* Go back to the beginning of line. */
if (fseek (caret_info.file, caret_info.offset, SEEK_SET))
return false;
/* Reset mbf's internal state.
FIXME: should be done in mbfile. */
caret_info.mbfile.eof_seen = 0;
caret_info.pos.column = 1;
return true;
}
/* Compute CARET_INFO.WIDTH and CARET_INFO.SKIP based on the fact that
the first column to display in the current line is COL. */
static bool
caret_set_column (int col)
{
/* Available width. Eight chars are consumed by the left-margin
(with line number). */
caret_info.width = screen_width - 8;
caret_info.skip = 0;
if (caret_info.width < caret_info.line_len)
{
/* We cannot quote the whole line. Make sure we can see the
beginning of the location. */
caret_info.skip = caret_info.width < col ? col - 10 : 0;
}
/* If we skip the initial part, we insert "..." before. */
if (caret_info.skip)
caret_info.width -= ellipsize;
/* If the end of line does not fit, we also need to truncate the
end, and leave "..." there. */
if (caret_info.width < caret_info.line_len - caret_info.skip)
caret_info.width -= ellipsize;
return true;
}
void
location_caret (location loc, const char *style, FILE *out)
{
if (!loc.start.line)
return;
if (!caret_set_file (loc.start.file))
return;
if (!caret_set_line (loc.start.line))
return;
if (!caret_set_column (loc.start.column))
return;
const int width = caret_info.width;
const int skip = caret_info.skip;
/* Read the actual line. Don't update the offset, so that we keep a pointer /* Read the actual line. Don't update the offset, so that we keep a pointer
to the start of the line. */ to the start of the line. */
{ {
int c = getc (caret_info.source); mbchar_t c;
if (c != EOF) caret_getc (c);
if (!mb_iseof (c))
{ {
bool single_line = loc.start.line == loc.end.line; /* The last column to highlight. Only the first line of
multiline locations are quoted, in which case the ending
column is the end of line. Single point locations (with
equal boundaries) denote the character that they
follow. */
int col_end
= loc.start.line == loc.end.line
? loc.end.column + (loc.start.column == loc.end.column)
: caret_info.line_len;
/* Quote the file (at most the first line in the case of /* Quote the file (at most the first line in the case of
multiline locations). */ multiline locations). */
{ {
fprintf (out, "%5d | ", loc.start.line); fprintf (out, "%5d | %s", loc.start.line, skip ? ellipsis : "");
/* Consider that single point location (with equal boundaries)
actually denote the character that they follow. */
int byte_end = loc.end.byte +
(single_line && loc.start.byte == loc.end.byte);
/* Byte number. */
int byte = 1;
/* Whether we opened the style. If the line is not as /* Whether we opened the style. If the line is not as
expected (maybe the file was changed since the scanner expected (maybe the file was changed since the scanner
ran), we might reach the end before we actually saw the ran), we might reach the end before we actually saw the
opening column. */ opening column. */
bool opened = false; bool opened = false;
while (c != EOF && c != '\n') while (!mb_iseof (c) && !mb_iseq (c, '\n'))
{ {
if (byte == loc.start.byte) if (caret_info.pos.column == loc.start.column)
{ {
begin_use_class (style, out); begin_use_class (style, out);
opened = true; opened = true;
} }
fputc (c, out); if (skip < caret_info.pos.column)
c = getc (caret_info.source); mb_putc (c, out);
++byte; boundary_compute (&caret_info.pos, mb_ptr (c), mb_len (c));
caret_getc (c);
if (opened if (opened
&& (single_line && (caret_info.pos.column == col_end
? byte == byte_end || width < caret_info.pos.column - skip))
: c == '\n' || c == EOF)) {
end_use_class (style, out); end_use_class (style, out);
opened = false;
}
if (width < caret_info.pos.column - skip)
{
fputs (ellipsis, out);
break;
}
} }
putc ('\n', out); putc ('\n', out);
} }
/* Print the carets with the same indentation as above. */ /* Print the carets with the same indentation as above. */
{ {
fprintf (out, " | %*s", loc.start.column - 1, ""); fprintf (out, " | %*s",
loc.start.column - 1 - skip + (skip ? ellipsize : 0), "");
begin_use_class (style, out); begin_use_class (style, out);
putc ('^', out); putc ('^', out);
/* Underlining a multiline location ends with the first /* Underlining a multiline location ends with the first
line. */ line. */
int len = single_line for (int i = loc.start.column - 1 - skip + 1,
? loc.end.column i_end = min_int (col_end - 1 - skip, width);
: ftell (caret_info.source) - caret_info.offset; i < i_end; ++i)
for (int i = loc.start.column + 1; i < len; ++i)
putc ('~', out); putc ('~', out);
end_use_class (style, out); end_use_class (style, out);
putc ('\n', out); putc ('\n', out);
@@ -298,6 +483,20 @@ location_caret (location loc, const char *style, FILE *out)
} }
} }
void
location_caret_suggestion (location loc, const char *s, FILE *out)
{
const char *style = "fixit-insert";
fprintf (out, " | %*s",
loc.start.column - 1 - caret_info.skip
+ (caret_info.skip ? ellipsize : 0),
"");
begin_use_class (style, out);
fputs (s, out);
end_use_class (style, out);
putc ('\n', out);
}
bool bool
location_empty (location loc) location_empty (location loc)
{ {
+22 -9
View File
@@ -33,25 +33,25 @@ typedef struct
/* The name of the file that contains the boundary. */ /* The name of the file that contains the boundary. */
uniqstr file; uniqstr file;
/* If nonnegative, the (origin-1) line that contains the boundary. /* If positive, the line (starting at 1) that contains the boundary.
If this is INT_MAX, the line number has overflowed. If this is INT_MAX, the line number has overflowed.
Meaningless and not displayed if negative. Meaningless and not displayed if nonpositive.
*/ */
int line; int line;
/* If nonnegative, the (origin-1) column just after the boundary. /* If positive, the column (starting at 1) just after the boundary.
This is neither a byte count, nor a character count; it is a This is neither a byte count, nor a character count; it is a
column count. If this is INT_MAX, the column number has column count. If this is INT_MAX, the column number has
overflowed. overflowed.
Meaningless and not displayed if negative. Meaningless and not displayed if nonpositive.
*/ */
int column; int column;
/* If nonnegative, (origin-0) bytes number in the current line. /* If nonnegative, the byte number (starting at 0) in the current line.
Never displayed, used when printing error messages with colors to Never displayed, used when printing error messages with colors to
know where colors start and ends. */ know where colors start and end. */
int byte; int byte;
} boundary; } boundary;
@@ -71,7 +71,12 @@ boundary_set (boundary *p, const char *f, int l, int c, int b)
static inline int static inline int
boundary_cmp (boundary a, boundary b) boundary_cmp (boundary a, boundary b)
{ {
int res = strcmp (a.file, b.file); /* Locations with no file first. */
int res =
a.file && b.file ? strcmp (a.file, b.file)
: a.file ? 1
: b.file ? -1
: 0;
if (!res) if (!res)
res = a.line - b.line; res = a.line - b.line;
if (!res) if (!res)
@@ -112,15 +117,23 @@ void location_compute (location *loc,
/* Print location to file. /* Print location to file.
Return number of actually printed characters. Return number of actually printed characters.
Warning: uses quotearg's slot 3. */ Warning: uses quotearg's slot 3. */
unsigned location_print (location loc, FILE *out); int location_print (location loc, FILE *out);
/* Prepare the use of location_caret. */
void caret_init (void);
/* Free any allocated resources and close any open file handles that are /* Free any allocated resources 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 caret_free (void); void caret_free (void);
/* Output to OUT the line and caret corresponding to location LOC. */ /* Quote the line containing LOC onto OUT. Highlight the part of LOC
with the color STYLE. */
void location_caret (location loc, const char* style, FILE *out); void location_caret (location loc, const char* style, FILE *out);
/* Display a suggestion of replacement for LOC with S. To call after
location_caret. */
void location_caret_suggestion (location loc, const char *s, FILE *out);
/* 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. */
static inline int static inline int
+33
View File
@@ -158,6 +158,14 @@ kernel_print (FILE *out)
} }
} }
/* Make sure the kernel is in sane state. */
static void
kernel_check (void)
{
for (symbol_number i = 0; i < nsyms - 1; ++i)
assert (kernel_base[i] + kernel_size[i] <= kernel_base[i + 1]);
}
static void static void
allocate_storage (void) allocate_storage (void)
{ {
@@ -209,9 +217,21 @@ new_itemsets (state *s)
bitset_zero (shift_symbol); bitset_zero (shift_symbol);
if (trace_flag & trace_automaton)
{
fprintf (stderr, "initial kernel:\n");
kernel_print (stderr);
}
for (size_t i = 0; i < nitemset; ++i) for (size_t i = 0; i < nitemset; ++i)
if (item_number_is_symbol_number (ritem[itemset[i]])) if (item_number_is_symbol_number (ritem[itemset[i]]))
{ {
if (trace_flag & trace_automaton)
{
fputs ("working on: ", stderr);
item_print (ritem + itemset[i], NULL, stderr);
fputc ('\n', stderr);
}
symbol_number sym = item_number_as_symbol_number (ritem[itemset[i]]); symbol_number sym = item_number_as_symbol_number (ritem[itemset[i]]);
bitset_set (shift_symbol, sym); bitset_set (shift_symbol, sym);
kernel_base[sym][kernel_size[sym]] = itemset[i] + 1; kernel_base[sym][kernel_size[sym]] = itemset[i] + 1;
@@ -220,9 +240,11 @@ new_itemsets (state *s)
if (trace_flag & trace_automaton) if (trace_flag & trace_automaton)
{ {
fprintf (stderr, "final kernel:\n");
kernel_print (stderr); kernel_print (stderr);
fprintf (stderr, "new_itemsets: end: state = %d\n\n", s->number); fprintf (stderr, "new_itemsets: end: state = %d\n\n", s->number);
} }
kernel_check ();
} }
@@ -309,6 +331,17 @@ save_reductions (state *s)
} }
} }
if (trace_flag & trace_automaton)
{
fprintf (stderr, "reduction[%d] = {\n", s->number);
for (int i = 0; i < count; ++i)
{
rule_print (redset[i], NULL, stderr);
fputc ('\n', stderr);
}
fputs ("}\n", stderr);
}
/* Make a reductions structure and copy the data into it. */ /* Make a reductions structure and copy the data into it. */
state_reductions_set (s, count, redset); state_reductions_set (s, count, redset);
} }
+4 -4
View File
@@ -101,7 +101,7 @@ main (int argc, char *argv[])
the grammar; see gram.h. */ the grammar; see gram.h. */
timevar_push (tv_reader); timevar_push (tv_reader);
reader (); reader (grammar_file);
timevar_pop (tv_reader); timevar_pop (tv_reader);
if (complaint_status == status_complaint) if (complaint_status == status_complaint)
@@ -207,6 +207,8 @@ main (int argc, char *argv[])
timevar_pop (tv_parser); timevar_pop (tv_parser);
} }
finish:
timevar_push (tv_free); timevar_push (tv_free);
nullable_free (); nullable_free ();
derives_free (); derives_free ();
@@ -223,14 +225,11 @@ main (int argc, char *argv[])
muscle_free (); muscle_free ();
code_scanner_free (); code_scanner_free ();
skel_scanner_free (); skel_scanner_free ();
quotearg_free ();
timevar_pop (tv_free); timevar_pop (tv_free);
if (trace_flag & trace_bitsets) if (trace_flag & trace_bitsets)
bitset_stats_dump (stderr); bitset_stats_dump (stderr);
finish:
/* Stop timing and print the times. */ /* Stop timing and print the times. */
timevar_stop (tv_total); timevar_stop (tv_total);
timevar_print (stderr); timevar_print (stderr);
@@ -249,6 +248,7 @@ main (int argc, char *argv[])
uniqstrs_free (); uniqstrs_free ();
complain_free (); complain_free ();
quotearg_free ();
return complaint_status ? EXIT_FAILURE : EXIT_SUCCESS; return complaint_status ? EXIT_FAILURE : EXIT_SUCCESS;
} }
+2 -2
View File
@@ -525,7 +525,7 @@ muscle_percent_define_insert (char const *var, location variable_loc,
= atoi (muscle_find_const (how_name)); = atoi (muscle_find_const (how_name));
if (how_old == MUSCLE_PERCENT_DEFINE_F) if (how_old == MUSCLE_PERCENT_DEFINE_F)
goto end; goto end;
unsigned i = 0; int i = 0;
/* If assigning the same value, make it a warning. */ /* If assigning the same value, make it a warning. */
warnings warn = STREQ (value, current_value) ? Wother : complaint; warnings warn = STREQ (value, current_value) ? Wother : complaint;
complain_indent (&variable_loc, warn, &i, complain_indent (&variable_loc, warn, &i,
@@ -739,7 +739,7 @@ muscle_percent_define_check_values (char const * const *values)
if (!*values) if (!*values)
{ {
location loc = muscle_percent_define_get_loc (*variablep); location loc = muscle_percent_define_get_loc (*variablep);
unsigned i = 0; int i = 0;
complain_indent (&loc, complaint, &i, complain_indent (&loc, complaint, &i,
_("invalid value for %%define variable %s: %s"), _("invalid value for %%define variable %s: %s"),
quote (*variablep), quote_n (1, value)); quote (*variablep), quote_n (1, value));
+30 -20
View File
@@ -91,7 +91,6 @@ Name (char const *name, Type *table_data, Type first, \
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_table, unsigned)
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)
@@ -214,17 +213,17 @@ prepare_symbols (void)
static void static void
prepare_rules (void) prepare_rules (void)
{ {
unsigned *prhs = xnmalloc (nrules, sizeof *prhs); int *prhs = xnmalloc (nrules, sizeof *prhs);
item_number *rhs = xnmalloc (nritems, sizeof *rhs); item_number *rhs = xnmalloc (nritems, sizeof *rhs);
unsigned *rline = xnmalloc (nrules, sizeof *rline); int *rline = xnmalloc (nrules, sizeof *rline);
symbol_number *r1 = xnmalloc (nrules, sizeof *r1); symbol_number *r1 = xnmalloc (nrules, sizeof *r1);
unsigned *r2 = xnmalloc (nrules, sizeof *r2); int *r2 = xnmalloc (nrules, sizeof *r2);
int *dprec = xnmalloc (nrules, sizeof *dprec); int *dprec = xnmalloc (nrules, sizeof *dprec);
int *merger = xnmalloc (nrules, sizeof *merger); int *merger = xnmalloc (nrules, sizeof *merger);
int *immediate = xnmalloc (nrules, sizeof *immediate); int *immediate = xnmalloc (nrules, sizeof *immediate);
/* Index in RHS. */ /* Index in RHS. */
unsigned i = 0; int i = 0;
for (rule_number r = 0; r < nrules; ++r) for (rule_number r = 0; r < nrules; ++r)
{ {
/* Index of rule R in RHS. */ /* Index of rule R in RHS. */
@@ -251,10 +250,10 @@ prepare_rules (void)
aver (i == nritems); aver (i == nritems);
muscle_insert_item_number_table ("rhs", rhs, ritem[0], 1, nritems); muscle_insert_item_number_table ("rhs", rhs, ritem[0], 1, nritems);
muscle_insert_unsigned_table ("prhs", prhs, 0, 0, nrules); muscle_insert_int_table ("prhs", prhs, 0, 0, nrules);
muscle_insert_unsigned_table ("rline", rline, 0, 0, nrules); muscle_insert_int_table ("rline", rline, 0, 0, nrules);
muscle_insert_symbol_number_table ("r1", r1, 0, 0, nrules); muscle_insert_symbol_number_table ("r1", r1, 0, 0, nrules);
muscle_insert_unsigned_table ("r2", r2, 0, 0, nrules); muscle_insert_int_table ("r2", r2, 0, 0, nrules);
muscle_insert_int_table ("dprec", dprec, 0, 0, nrules); muscle_insert_int_table ("dprec", dprec, 0, 0, nrules);
muscle_insert_int_table ("merger", merger, 0, 0, nrules); muscle_insert_int_table ("merger", merger, 0, 0, nrules);
muscle_insert_int_table ("immediate", immediate, 0, 0, nrules); muscle_insert_int_table ("immediate", immediate, 0, 0, nrules);
@@ -359,9 +358,9 @@ symbol_numbers_output (FILE *out)
} }
/*---------------------------------. /*-------------------------------------------.
| Output the user actions to OUT. | | Output the user reduction actions to OUT. |
`---------------------------------*/ `-------------------------------------------*/
static void static void
user_actions_output (FILE *out) user_actions_output (FILE *out)
@@ -370,11 +369,20 @@ user_actions_output (FILE *out)
for (rule_number r = 0; r < nrules; ++r) for (rule_number r = 0; r < nrules; ++r)
if (rules[r].action) if (rules[r].action)
{ {
fprintf (out, "%s(%d, [b4_syncline(%d, ", /* The useless "" is there to pacify syntax-check. */
fprintf (out, "%s""(%d, [",
rules[r].is_predicate ? "b4_predicate_case" : "b4_case", rules[r].is_predicate ? "b4_predicate_case" : "b4_case",
r + 1, rules[r].action_loc.start.line); r + 1);
string_output (out, rules[r].action_loc.start.file); if (!no_lines_flag)
fprintf (out, ")dnl\n[ %s]])\n\n", rules[r].action); {
fprintf (out, "b4_syncline(%d, ",
rules[r].action_loc.start.line);
string_output (out, rules[r].action_loc.start.file);
fprintf (out, ")dnl\n");
}
fprintf (out, "[%*s%s]])\n\n",
rules[r].action_loc.start.column - 1, "",
rules[r].action);
} }
fputs ("])\n\n", out); fputs ("])\n\n", out);
} }
@@ -482,7 +490,9 @@ prepare_symbol_definitions (void)
muscle_location_grow (key, p->location); muscle_location_grow (key, p->location);
SET_KEY (pname); SET_KEY (pname);
MUSCLE_INSERT_STRING_RAW (key, p->code); obstack_printf (&muscle_obstack,
"%*s%s", p->location.start.column - 1, "", p->code);
muscle_insert (key, obstack_finish0 (&muscle_obstack));
} }
} }
#undef SET_KEY2 #undef SET_KEY2
@@ -532,10 +542,10 @@ prepare_actions (void)
parser, so we could avoid accidents by not writing them out in parser, so we could avoid accidents by not writing them out in
that case. Nevertheless, it seems even better to be able to use that case. Nevertheless, it seems even better to be able to use
the GLR skeletons even without the non-deterministic tables. */ the GLR skeletons even without the non-deterministic tables. */
muscle_insert_unsigned_table ("conflict_list_heads", conflict_table, muscle_insert_int_table ("conflict_list_heads", conflict_table,
conflict_table[0], 1, high + 1); conflict_table[0], 1, high + 1);
muscle_insert_unsigned_table ("conflicting_rules", conflict_list, muscle_insert_int_table ("conflicting_rules", conflict_list,
0, 1, conflict_list_cnt); 0, 1, conflict_list_cnt);
} }
+374 -339
View File
File diff suppressed because it is too large Load Diff
+59 -61
View File
@@ -1,4 +1,4 @@
/* A Bison parser, made by GNU Bison 3.4.1.26-d17af. */ /* A Bison parser, made by GNU Bison 3.4.2.213-aa24. */
/* Bison interface for Yacc-like parsers in C /* Bison interface for Yacc-like parsers in C
@@ -78,63 +78,63 @@ extern int gram_debug;
enum gram_tokentype enum gram_tokentype
{ {
GRAM_EOF = 0, GRAM_EOF = 0,
STRING = 258, STRING = 3,
PERCENT_TOKEN = 259, PERCENT_TOKEN = 4,
PERCENT_NTERM = 260, PERCENT_NTERM = 5,
PERCENT_TYPE = 261, PERCENT_TYPE = 6,
PERCENT_DESTRUCTOR = 262, PERCENT_DESTRUCTOR = 7,
PERCENT_PRINTER = 263, PERCENT_PRINTER = 8,
PERCENT_LEFT = 264, PERCENT_LEFT = 9,
PERCENT_RIGHT = 265, PERCENT_RIGHT = 10,
PERCENT_NONASSOC = 266, PERCENT_NONASSOC = 11,
PERCENT_PRECEDENCE = 267, PERCENT_PRECEDENCE = 12,
PERCENT_PREC = 268, PERCENT_PREC = 13,
PERCENT_DPREC = 269, PERCENT_DPREC = 14,
PERCENT_MERGE = 270, PERCENT_MERGE = 15,
PERCENT_CODE = 271, PERCENT_CODE = 16,
PERCENT_DEFAULT_PREC = 272, PERCENT_DEFAULT_PREC = 17,
PERCENT_DEFINE = 273, PERCENT_DEFINE = 18,
PERCENT_DEFINES = 274, PERCENT_DEFINES = 19,
PERCENT_ERROR_VERBOSE = 275, PERCENT_ERROR_VERBOSE = 20,
PERCENT_EXPECT = 276, PERCENT_EXPECT = 21,
PERCENT_EXPECT_RR = 277, PERCENT_EXPECT_RR = 22,
PERCENT_FLAG = 278, PERCENT_FLAG = 23,
PERCENT_FILE_PREFIX = 279, PERCENT_FILE_PREFIX = 24,
PERCENT_GLR_PARSER = 280, PERCENT_GLR_PARSER = 25,
PERCENT_INITIAL_ACTION = 281, PERCENT_INITIAL_ACTION = 26,
PERCENT_LANGUAGE = 282, PERCENT_LANGUAGE = 27,
PERCENT_NAME_PREFIX = 283, PERCENT_NAME_PREFIX = 28,
PERCENT_NO_DEFAULT_PREC = 284, PERCENT_NO_DEFAULT_PREC = 29,
PERCENT_NO_LINES = 285, PERCENT_NO_LINES = 30,
PERCENT_NONDETERMINISTIC_PARSER = 286, PERCENT_NONDETERMINISTIC_PARSER = 31,
PERCENT_OUTPUT = 287, PERCENT_OUTPUT = 32,
PERCENT_PURE_PARSER = 288, PERCENT_PURE_PARSER = 33,
PERCENT_REQUIRE = 289, PERCENT_REQUIRE = 34,
PERCENT_SKELETON = 290, PERCENT_SKELETON = 35,
PERCENT_START = 291, PERCENT_START = 36,
PERCENT_TOKEN_TABLE = 292, PERCENT_TOKEN_TABLE = 37,
PERCENT_VERBOSE = 293, PERCENT_VERBOSE = 38,
PERCENT_YACC = 294, PERCENT_YACC = 39,
BRACED_CODE = 295, BRACED_CODE = 40,
BRACED_PREDICATE = 296, BRACED_PREDICATE = 41,
BRACKETED_ID = 297, BRACKETED_ID = 42,
CHAR = 298, CHAR = 43,
COLON = 299, COLON = 44,
EPILOGUE = 300, EPILOGUE = 45,
EQUAL = 301, EQUAL = 46,
ID = 302, ID = 47,
ID_COLON = 303, ID_COLON = 48,
PERCENT_PERCENT = 304, PERCENT_PERCENT = 49,
PIPE = 305, PIPE = 50,
PROLOGUE = 306, PROLOGUE = 51,
SEMICOLON = 307, SEMICOLON = 52,
TAG = 308, TAG = 53,
TAG_ANY = 309, TAG_ANY = 54,
TAG_NONE = 310, TAG_NONE = 55,
INT = 311, INT = 56,
PERCENT_PARAM = 312, PERCENT_PARAM = 57,
PERCENT_UNION = 313, PERCENT_UNION = 58,
PERCENT_EMPTY = 314 PERCENT_EMPTY = 59
}; };
#endif #endif
@@ -207,8 +207,6 @@ union GRAM_STYPE
uniqstr PERCENT_NAME_PREFIX; uniqstr PERCENT_NAME_PREFIX;
/* "%pure-parser" */ /* "%pure-parser" */
uniqstr PERCENT_PURE_PARSER; uniqstr PERCENT_PURE_PARSER;
/* "%yacc" */
uniqstr PERCENT_YACC;
/* "[identifier]" */ /* "[identifier]" */
uniqstr BRACKETED_ID; uniqstr BRACKETED_ID;
/* "identifier" */ /* "identifier" */
@@ -223,7 +221,7 @@ union GRAM_STYPE
uniqstr tag; uniqstr tag;
/* variable */ /* variable */
uniqstr variable; uniqstr variable;
/* "char" */ /* "character literal" */
unsigned char CHAR; unsigned char CHAR;
/* value */ /* value */
value_type value; value_type value;
+72 -51
View File
@@ -32,21 +32,23 @@
%code %code
{ {
#include "system.h" #include "system.h"
#include <errno.h>
#include "c-ctype.h" #include <c-ctype.h>
#include <errno.h>
#include <intprops.h>
#include <quotearg.h>
#include <vasnprintf.h>
#include <xmemdup0.h>
#include "complain.h" #include "complain.h"
#include "conflicts.h" #include "conflicts.h"
#include "files.h" #include "files.h"
#include "getargs.h" #include "getargs.h"
#include "gram.h" #include "gram.h"
#include "named-ref.h" #include "named-ref.h"
#include "quotearg.h"
#include "reader.h" #include "reader.h"
#include "scan-code.h" #include "scan-code.h"
#include "scan-gram.h" #include "scan-gram.h"
#include "vasnprintf.h"
#include "xmemdup0.h"
static int current_prec = 0; static int current_prec = 0;
static location current_lhs_loc; static location current_lhs_loc;
@@ -104,18 +106,14 @@
static void handle_skeleton (location const *loc, char const *skel); static void handle_skeleton (location const *loc, char const *skel);
/* Handle a %yacc directive. */ /* Handle a %yacc directive. */
static void handle_yacc (location const *loc, char const *directive); static void handle_yacc (location const *loc);
/* Implementation of yyerror. */
static void gram_error (location const *, char const *); static void gram_error (location const *, char const *);
/* A string that describes a char (e.g., 'a' -> "'a'"). */ /* A string that describes a char (e.g., 'a' -> "'a'"). */
static char const *char_name (char); static char const *char_name (char);
#define YYTYPE_INT16 int_fast16_t
#define YYTYPE_INT8 int_fast8_t
#define YYTYPE_UINT16 uint_fast16_t
#define YYTYPE_UINT8 uint_fast8_t
/* Add style to semantic values in traces. */ /* Add style to semantic values in traces. */
static void tron (FILE *yyo); static void tron (FILE *yyo);
static void troff (FILE *yyo); static void troff (FILE *yyo);
@@ -124,6 +122,7 @@
%define api.header.include {"parse-gram.h"} %define api.header.include {"parse-gram.h"}
%define api.prefix {gram_} %define api.prefix {gram_}
%define api.pure full %define api.pure full
%define api.token.raw
%define api.value.type union %define api.value.type union
%define locations %define locations
%define parse.error verbose %define parse.error verbose
@@ -137,8 +136,8 @@
{ {
/* Bison's grammar can initial empty locations, hence a default /* Bison's grammar can initial empty locations, hence a default
location is needed. */ location is needed. */
boundary_set (&@$.start, current_file, 1, 1, 1); boundary_set (&@$.start, grammar_file, 1, 1, 1);
boundary_set (&@$.end, current_file, 1, 1, 1); boundary_set (&@$.end, grammar_file, 1, 1, 1);
} }
/* Define the tokens together with their human representation. */ /* Define the tokens together with their human representation. */
@@ -196,7 +195,7 @@
%token BRACED_CODE "{...}" %token BRACED_CODE "{...}"
%token BRACED_PREDICATE "%?{...}" %token BRACED_PREDICATE "%?{...}"
%token BRACKETED_ID "[identifier]" %token BRACKETED_ID "[identifier]"
%token CHAR "char" %token CHAR "character literal"
%token COLON ":" %token COLON ":"
%token EPILOGUE "epilogue" %token EPILOGUE "epilogue"
%token EQUAL "=" %token EQUAL "="
@@ -223,7 +222,7 @@
%type <uniqstr> %type <uniqstr>
BRACKETED_ID ID ID_COLON BRACKETED_ID ID ID_COLON
PERCENT_ERROR_VERBOSE PERCENT_FILE_PREFIX PERCENT_FLAG PERCENT_NAME_PREFIX PERCENT_ERROR_VERBOSE PERCENT_FILE_PREFIX PERCENT_FLAG PERCENT_NAME_PREFIX
PERCENT_PURE_PARSER PERCENT_YACC PERCENT_PURE_PARSER
TAG tag tag.opt variable TAG tag tag.opt variable
%printer { fputs ($$, yyo); } <uniqstr> %printer { fputs ($$, yyo); } <uniqstr>
%printer { fprintf (yyo, "[%s]", $$); } BRACKETED_ID %printer { fprintf (yyo, "[%s]", $$); } BRACKETED_ID
@@ -352,7 +351,7 @@ prologue_declaration:
| "%skeleton" STRING { handle_skeleton (&@2, $2); } | "%skeleton" STRING { handle_skeleton (&@2, $2); }
| "%token-table" { token_table_flag = true; } | "%token-table" { token_table_flag = true; }
| "%verbose" { report_flag |= report_states; } | "%verbose" { report_flag |= report_states; }
| "%yacc" { handle_yacc (&@$, $1); } | "%yacc" { handle_yacc (&@$); }
| error ";" { current_class = unknown_sym; yyerrok; } | error ";" { current_class = unknown_sym; yyerrok; }
| /*FIXME: Err? What is this horror doing here? */ ";" | /*FIXME: Err? What is this horror doing here? */ ";"
; ;
@@ -732,12 +731,24 @@ id:
{ $$ = symbol_from_uniqstr ($1, @1); } { $$ = symbol_from_uniqstr ($1, @1); }
| CHAR | CHAR
{ {
const char *var = "api.token.raw";
if (current_class == nterm_sym) if (current_class == nterm_sym)
{ {
gram_error (&@1, complain (&@1, complaint,
_("character literals cannot be nonterminals")); _("character literals cannot be nonterminals"));
YYERROR; YYERROR;
} }
if (muscle_percent_define_ifdef (var))
{
int indent = 0;
complain_indent (&@1, complaint, &indent,
_("character literals cannot be used together"
" with %s"), var);
indent += SUB_INDENT;
location loc = muscle_percent_define_get_loc (var);
complain_indent (&loc, complaint, &indent,
_("definition of %s"), var);
}
$$ = symbol_get (char_name ($1), @1); $$ = symbol_get (char_name ($1), @1);
symbol_class_set ($$, token_sym, @1, false); symbol_class_set ($$, token_sym, @1, false);
symbol_user_token_number_set ($$, $1, @1); symbol_user_token_number_set ($$, $1, @1);
@@ -960,36 +971,55 @@ handle_pure_parser (location const *loc, char const *directive)
} }
/* Convert VERSION into an int (MAJOR * 100 + MINOR). Return -1 on
errors.
Changes of behavior are only on minor version changes, so "3.0.5"
is the same as "3.0": 300. */
static int
str_to_version (char const *version)
{
IGNORE_TYPE_LIMITS_BEGIN
int res = 0;
errno = 0;
char *cp = NULL;
long major = strtol (version, &cp, 10);
if (errno || cp == version || *cp != '.' || major < 0
|| INT_MULTIPLY_WRAPV (major, 100, &res))
return -1;
++cp;
char *cp1 = NULL;
long minor = strtol (cp, &cp1, 10);
if (errno || cp1 == cp || (*cp1 != '\0' && *cp1 != '.')
|| ! (0 <= minor && minor < 100)
|| INT_ADD_WRAPV (minor, res, &res))
return -1;
IGNORE_TYPE_LIMITS_END
return res;
}
static void static void
handle_require (location const *loc, char const *version) handle_require (location const *loc, char const *version)
{ {
/* Changes of behavior are only on minor version changes, so "3.0.5" required_version = str_to_version (version);
is the same as "3.0". */ if (required_version == -1)
errno = 0;
char* cp = NULL;
unsigned long major = strtoul (version, &cp, 10);
if (errno || *cp != '.')
{ {
complain (loc, complaint, _("invalid version requirement: %s"), complain (loc, complaint, _("invalid version requirement: %s"),
version); version);
required_version = 0;
return; return;
} }
++cp;
unsigned long minor = strtoul (cp, NULL, 10);
if (errno)
{
complain (loc, complaint, _("invalid version requirement: %s"),
version);
return;
}
required_version = major * 100 + minor;
/* Pretend to be at least 3.4, to check features published in 3.4 /* Pretend to be at least 3.4, to check features published in 3.4
while developping it. */ while developping it. */
const char* api_version = "3.4"; const char* api_version = "3.4";
const char* package_version = const char* package_version =
strverscmp (api_version, PACKAGE_VERSION) > 0 0 < strverscmp (api_version, PACKAGE_VERSION)
? api_version : PACKAGE_VERSION; ? api_version : PACKAGE_VERSION;
if (strverscmp (version, package_version) > 0) if (0 < strverscmp (version, package_version))
{ {
complain (loc, complaint, _("require bison %s, but have %s"), complain (loc, complaint, _("require bison %s, but have %s"),
version, package_version); version, package_version);
@@ -1003,16 +1033,16 @@ handle_skeleton (location const *loc, char const *skel)
char const *skeleton_user = skel; char const *skeleton_user = skel;
if (strchr (skeleton_user, '/')) if (strchr (skeleton_user, '/'))
{ {
size_t dir_length = strlen (current_file); size_t dir_length = strlen (grammar_file);
while (dir_length && current_file[dir_length - 1] != '/') while (dir_length && grammar_file[dir_length - 1] != '/')
--dir_length; --dir_length;
while (dir_length && current_file[dir_length - 1] == '/') while (dir_length && grammar_file[dir_length - 1] == '/')
--dir_length; --dir_length;
char *skeleton_build = char *skeleton_build =
xmalloc (dir_length + 1 + strlen (skeleton_user) + 1); xmalloc (dir_length + 1 + strlen (skeleton_user) + 1);
if (dir_length > 0) if (dir_length > 0)
{ {
memcpy (skeleton_build, current_file, dir_length); memcpy (skeleton_build, grammar_file, dir_length);
skeleton_build[dir_length++] = '/'; skeleton_build[dir_length++] = '/';
} }
strcpy (skeleton_build + dir_length, skeleton_user); strcpy (skeleton_build + dir_length, skeleton_user);
@@ -1024,23 +1054,14 @@ handle_skeleton (location const *loc, char const *skel)
static void static void
handle_yacc (location const *loc, char const *directive) handle_yacc (location const *loc)
{ {
const char *directive = "%yacc";
bison_directive (loc, directive); bison_directive (loc, directive);
bool warned = false;
if (location_empty (yacc_loc)) if (location_empty (yacc_loc))
yacc_loc = *loc; yacc_loc = *loc;
else else
{ duplicate_directive (directive, yacc_loc, *loc);
duplicate_directive (directive, yacc_loc, *loc);
warned = true;
}
if (!warned
&& STRNEQ (directive, "%fixed-output-files")
&& STRNEQ (directive, "%yacc"))
deprecated_directive (loc, directive, "%fixed-output-files");
} }
+15 -32
View File
@@ -124,7 +124,7 @@ record_merge_function_type (int merger, uniqstr type, location declaration_loc)
aver (merge_function != NULL && merger_find == merger); aver (merge_function != NULL && merger_find == merger);
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; int indent = 0;
complain_indent (&declaration_loc, complaint, &indent, complain_indent (&declaration_loc, complaint, &indent,
_("result type clash on merge function %s: " _("result type clash on merge function %s: "
"<%s> != <%s>"), "<%s> != <%s>"),
@@ -358,6 +358,8 @@ grammar_rule_check_and_complete (symbol_list *r)
&& warning_is_enabled (Wempty_rule)) && warning_is_enabled (Wempty_rule))
{ {
complain (&r->rhs_loc, Wempty_rule, _("empty rule without %%empty")); complain (&r->rhs_loc, Wempty_rule, _("empty rule without %%empty"));
if (feature_flag & feature_caret)
location_caret_suggestion (r->rhs_loc, "%empty", stderr);
location loc = r->rhs_loc; location loc = r->rhs_loc;
loc.end = loc.start; loc.end = loc.start;
fixits_register (&loc, " %empty "); fixits_register (&loc, " %empty ");
@@ -603,15 +605,14 @@ grammar_current_rule_expect_rr (int count, location loc)
} }
/*---------------------------------------------------------------. /*---------------------------------------------.
| Convert the rules into the representation using RRHS, RLHS and | | Build RULES and RITEM from what was parsed. |
| RITEM. | `---------------------------------------------*/
`---------------------------------------------------------------*/
static void static void
packgram (void) packgram (void)
{ {
unsigned itemno = 0; int itemno = 0;
ritem = xnmalloc (nritems + 1, sizeof *ritem); ritem = xnmalloc (nritems + 1, sizeof *ritem);
/* This sentinel is used by build_relations in gram.c. */ /* This sentinel is used by build_relations in gram.c. */
*ritem++ = 0; *ritem++ = 0;
@@ -699,7 +700,8 @@ packgram (void)
if (trace_flag & trace_sets) if (trace_flag & trace_sets)
ritem_print (stderr); ritem_print (stderr);
} }
/*------------------------------------------------------------------. /*------------------------------------------------------------------.
| Read in the grammar specification and record it in the format | | Read in the grammar specification and record it in the format |
| described in gram.h. All actions are copied into ACTION_OBSTACK, | | described in gram.h. All actions are copied into ACTION_OBSTACK, |
@@ -708,39 +710,20 @@ packgram (void)
`------------------------------------------------------------------*/ `------------------------------------------------------------------*/
void void
reader (void) reader (const char *gram)
{ {
/* Initialize the symbol table. */ /* Set up symbol_table, semantic_type_table, and the built-in
symbols. */
symbols_new (); symbols_new ();
/* Construct the accept symbol. */ gram_scanner_open (gram);
accept = symbol_get ("$accept", empty_loc);
accept->content->class = nterm_sym;
accept->content->number = nvars++;
/* Construct the error token */
errtoken = symbol_get ("error", empty_loc);
errtoken->content->class = token_sym;
errtoken->content->number = ntokens++;
/* Construct a token that represents all undefined literal tokens.
It is always token number 2. */
undeftoken = symbol_get ("$undefined", empty_loc);
undeftoken->content->class = token_sym;
undeftoken->content->number = ntokens++;
gram_in = xfopen (grammar_file, "r");
gram__flex_debug = trace_flag & trace_scan;
gram_debug = trace_flag & trace_parse;
gram_scanner_initialize ();
gram_parse (); gram_parse ();
gram_scanner_close ();
prepare_percent_define_front_end_variables (); prepare_percent_define_front_end_variables ();
if (complaint_status < status_complaint) if (complaint_status < status_complaint)
check_and_convert_grammar (); check_and_convert_grammar ();
xfclose (gram_in);
} }
static void static void
+1 -1
View File
@@ -60,7 +60,7 @@ void grammar_current_rule_action_append (const char *action, location loc,
named_ref *nref, uniqstr tag); named_ref *nref, uniqstr tag);
/* Attach a PREDICATE to the current rule. */ /* Attach a PREDICATE to the current rule. */
void grammar_current_rule_predicate_append (const char *predicate, location loc); void grammar_current_rule_predicate_append (const char *predicate, location loc);
void reader (void); void reader (const char *gram);
void free_merger_functions (void); void free_merger_functions (void);
extern merger_list *merge_functions; extern merger_list *merge_functions;
+4 -4
View File
@@ -52,8 +52,8 @@ static bitset V;
'useless', but no warning should be issued). */ 'useless', but no warning should be issued). */
static bitset V1; static bitset V1;
unsigned nuseless_productions; int nuseless_productions;
unsigned nuseless_nonterminals; int nuseless_nonterminals;
#define bitset_swap(Lhs, Rhs) \ #define bitset_swap(Lhs, Rhs) \
do { \ do { \
@@ -195,10 +195,10 @@ inaccessable_symbols (void)
bitset_free (P); bitset_free (P);
P = Pp; P = Pp;
unsigned nuseful_productions = bitset_count (P); int nuseful_productions = bitset_count (P);
nuseless_productions = nrules - nuseful_productions; nuseless_productions = nrules - nuseful_productions;
unsigned nuseful_nonterminals = 0; int nuseful_nonterminals = 0;
for (symbol_number i = ntokens; i < nsyms; ++i) for (symbol_number i = ntokens; i < nsyms; ++i)
nuseful_nonterminals += bitset_test (V, i); nuseful_nonterminals += bitset_test (V, i);
nuseless_nonterminals = nvars - nuseful_nonterminals; nuseless_nonterminals = nvars - nuseful_nonterminals;
+2 -2
View File
@@ -36,7 +36,7 @@ void reduce_free (void);
* reduce_grammar. Size nvars + nuseless_nonterminals. */ * reduce_grammar. Size nvars + nuseless_nonterminals. */
extern symbol_number *nterm_map; extern symbol_number *nterm_map;
extern unsigned nuseless_nonterminals; extern int nuseless_nonterminals;
extern unsigned nuseless_productions; extern int nuseless_productions;
#endif /* !REDUCE_H_ */ #endif /* !REDUCE_H_ */
+3 -3
View File
@@ -33,14 +33,14 @@ relation_print (const char *title,
{ {
if (title) if (title)
fprintf (out, "%s:\n", title); fprintf (out, "%s:\n", title);
for (size_t i = 0; i < size; ++i) for (relation_node i = 0; i < size; ++i)
if (r[i]) if (r[i])
{ {
fputs (" ", out); fputs (" ", out);
if (print) if (print)
print (i, out); print (i, out);
else else
fprintf (out, "%3lu", (unsigned long) i); fprintf (out, "%3ld", (long) i);
fputc (':', out); fputc (':', out);
for (relation_node j = 0; r[i][j] != END_NODE; ++j) for (relation_node j = 0; r[i][j] != END_NODE; ++j)
{ {
@@ -48,7 +48,7 @@ relation_print (const char *title,
if (print) if (print)
print (r[i][j], out); print (r[i][j], out);
else else
fprintf (out, "%3lu", (unsigned long) r[i][j]); fprintf (out, "%3ld", (long) r[i][j]);
} }
fputc ('\n', out); fputc ('\n', out);
} }
+41 -40
View File
@@ -48,11 +48,12 @@ YY_DECL;
#define YY_USER_ACTION location_compute (loc, &loc->end, yytext, yyleng); #define YY_USER_ACTION location_compute (loc, &loc->end, yytext, yyleng);
static char *fetch_type_name (char *cp, char const **type_name, static char *fetch_type_name (char *cp, char const **type_name,
location dollar_loc); const location *dollar_loc);
static void handle_action_dollar (symbol_list *rule, char *cp, static void handle_action_dollar (symbol_list *rule, char *cp,
location dollar_loc); const location *dollar_loc);
static void handle_action_at (symbol_list *rule, char *cp, location at_loc); static void handle_action_at (symbol_list *rule, char *cp,
const location *at_loc);
/* A string to be pushed to obstack after dollar/at has been handled. */ /* A string to be pushed to obstack after dollar/at has been handled. */
static char *ref_tail_fields; static char *ref_tail_fields;
@@ -163,13 +164,13 @@ ref -?[0-9]+|{id}|"["{id}"]"|"$"
{ {
"$"("<"{tag}">")?{ref} { "$"("<"{tag}">")?{ref} {
ref_tail_fields = NULL; ref_tail_fields = NULL;
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);
} }
"@"{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);
} }
@@ -179,7 +180,7 @@ ref -?[0-9]+|{id}|"["{id}"]"|"$"
{ {
"$"("<"{tag}">")?"$" { "$"("<"{tag}">")?"$" {
const char *type_name = NULL; const char *type_name = NULL;
fetch_type_name (yytext + 1, &type_name, *loc)[-1] = 0; fetch_type_name (yytext + 1, &type_name, loc)[-1] = 0;
obstack_sgrow (&obstack_for_string, "]b4_dollar_dollar("); obstack_sgrow (&obstack_for_string, "]b4_dollar_dollar(");
obstack_quote (&obstack_for_string, type_name); obstack_quote (&obstack_for_string, type_name);
obstack_sgrow (&obstack_for_string, ")["); obstack_sgrow (&obstack_for_string, ")[");
@@ -215,14 +216,14 @@ is_dot_or_dash (char ch)
static inline bool static inline bool
contains_dot_or_dash (const char* p) contains_dot_or_dash (const char* p)
{ {
return strpbrk(p, ".-"); return !!strpbrk (p, ".-");
} }
/* Defines a variant of a symbolic name resolution. */ /* Defines a variant of a symbolic name resolution. */
typedef struct typedef struct
{ {
/* Index in symbol list. */ /* Index in symbol list. */
unsigned symbol_index; int symbol_index;
/* Matched symbol id and loc. */ /* Matched symbol id and loc. */
uniqstr id; uniqstr id;
@@ -249,8 +250,8 @@ typedef struct
#define VARIANT_NOT_VISIBLE_FROM_MIDRULE (1 << 2) #define VARIANT_NOT_VISIBLE_FROM_MIDRULE (1 << 2)
static variant *variant_table = NULL; static variant *variant_table = NULL;
static unsigned variant_table_size = 0; static int variant_table_size = 0;
static unsigned variant_count = 0; static int variant_count = 0;
static variant * static variant *
variant_table_grow (void) variant_table_grow (void)
@@ -285,7 +286,7 @@ find_prefix_end (char const *prefix, char const *cp, char const *end)
} }
static variant * static variant *
variant_add (uniqstr id, location id_loc, unsigned symbol_index, variant_add (uniqstr id, location id_loc, int symbol_index,
char const *cp, char const *cp_end, bool explicit_bracketing) char const *cp, char const *cp_end, bool explicit_bracketing)
{ {
char const *prefix_end = find_prefix_end (id, cp, cp_end); char const *prefix_end = find_prefix_end (id, cp, cp_end);
@@ -306,7 +307,7 @@ variant_add (uniqstr id, location id_loc, unsigned symbol_index,
} }
static const char * static const char *
get_at_spec(unsigned symbol_index) get_at_spec(int symbol_index)
{ {
static char at_buf[20]; static char at_buf[20];
if (symbol_index == 0) if (symbol_index == 0)
@@ -320,7 +321,7 @@ static void
show_sub_message (warnings warning, show_sub_message (warnings warning,
const char* cp, bool explicit_bracketing, const char* cp, bool explicit_bracketing,
int midrule_rhs_index, char dollar_or_at, int midrule_rhs_index, char dollar_or_at,
unsigned indent, const variant *var) int indent, const variant *var)
{ {
const char *at_spec = get_at_spec (var->symbol_index); const char *at_spec = get_at_spec (var->symbol_index);
@@ -384,9 +385,9 @@ static void
show_sub_messages (warnings warning, show_sub_messages (warnings warning,
const char* cp, bool explicit_bracketing, const char* cp, bool explicit_bracketing,
int midrule_rhs_index, char dollar_or_at, int midrule_rhs_index, char dollar_or_at,
unsigned indent) int indent)
{ {
for (unsigned i = 0; i < variant_count; ++i) for (int i = 0; i < variant_count; ++i)
show_sub_message (warning | silent, show_sub_message (warning | silent,
cp, explicit_bracketing, cp, explicit_bracketing,
midrule_rhs_index, dollar_or_at, midrule_rhs_index, dollar_or_at,
@@ -406,7 +407,7 @@ show_sub_messages (warnings warning,
accesses. */ accesses. */
static long static long
parse_ref (char *cp, symbol_list *rule, int rule_length, parse_ref (char *cp, symbol_list *rule, int rule_length,
int midrule_rhs_index, char *text, location text_loc, int midrule_rhs_index, char *text, const location *text_loc,
char dollar_or_at) char dollar_or_at)
{ {
if ('$' == *cp) if ('$' == *cp)
@@ -419,7 +420,7 @@ parse_ref (char *cp, symbol_list *rule, int rule_length,
return num; return num;
else else
{ {
complain (&text_loc, complaint, _("integer out of range: %s"), complain (text_loc, complaint, _("integer out of range: %s"),
quote (text)); quote (text));
return INVALID_REF; return INVALID_REF;
} }
@@ -436,7 +437,7 @@ parse_ref (char *cp, symbol_list *rule, int rule_length,
/* Add all relevant variants. */ /* Add all relevant variants. */
{ {
unsigned symbol_index; int symbol_index;
symbol_list *l; symbol_list *l;
variant_count = 0; variant_count = 0;
for (symbol_index = 0, l = rule; !symbol_list_null (l); for (symbol_index = 0, l = rule; !symbol_list_null (l);
@@ -458,12 +459,12 @@ parse_ref (char *cp, symbol_list *rule, int rule_length,
} }
/* Check errors. */ /* Check errors. */
unsigned valid_variants = 0; int valid_variants = 0;
unsigned valid_variant_index = 0; int valid_variant_index = 0;
for (unsigned i = 0; i < variant_count; ++i) for (int i = 0; i < variant_count; ++i)
{ {
variant *var = &variant_table[i]; variant *var = &variant_table[i];
unsigned symbol_index = var->symbol_index; int symbol_index = var->symbol_index;
/* Check visibility from midrule actions. */ /* Check visibility from midrule actions. */
if (midrule_rhs_index != 0 if (midrule_rhs_index != 0
@@ -489,16 +490,16 @@ parse_ref (char *cp, symbol_list *rule, int rule_length,
{ {
case 0: case 0:
{ {
unsigned len = (explicit_bracketing || !ref_tail_fields) ? int len = (explicit_bracketing || !ref_tail_fields) ?
cp_end - cp : ref_tail_fields - cp; cp_end - cp : ref_tail_fields - cp;
unsigned indent = 0; int indent = 0;
complain_indent (&text_loc, complaint, &indent, 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)
{ {
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, complain_indent (&sym_loc, complaint, &indent,
@@ -524,17 +525,17 @@ parse_ref (char *cp, symbol_list *rule, int rule_length,
} }
case 1: case 1:
{ {
unsigned indent = 0; int indent = 0;
if (variant_count > 1) if (variant_count > 1)
{ {
complain_indent (&text_loc, Wother, &indent, 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);
} }
{ {
unsigned symbol_index = int symbol_index =
variant_table[valid_variant_index].symbol_index; variant_table[valid_variant_index].symbol_index;
return (symbol_index == midrule_rhs_index) ? LHS_REF : symbol_index; return (symbol_index == midrule_rhs_index) ? LHS_REF : symbol_index;
} }
@@ -542,8 +543,8 @@ parse_ref (char *cp, symbol_list *rule, int rule_length,
case 2: case 2:
default: default:
{ {
unsigned indent = 0; int indent = 0;
complain_indent (&text_loc, complaint, &indent, 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,
@@ -566,7 +567,7 @@ int max_left_semantic_context = 0;
static static
char * char *
fetch_type_name (char *cp, char const **type_name, fetch_type_name (char *cp, char const **type_name,
location dollar_loc) const location *dollar_loc)
{ {
if (*cp == '<') if (*cp == '<')
{ {
@@ -579,7 +580,7 @@ fetch_type_name (char *cp, char const **type_name,
'text' is needed for error messages. */ 'text' is needed for error messages. */
++cp; ++cp;
if (untyped_var_seen) if (untyped_var_seen)
complain (&dollar_loc, complaint, complain (dollar_loc, complaint,
_("explicit type given in untyped grammar")); _("explicit type given in untyped grammar"));
tag_seen = true; tag_seen = true;
} }
@@ -595,7 +596,7 @@ fetch_type_name (char *cp, char const **type_name,
`------------------------------------------------------------------*/ `------------------------------------------------------------------*/
static void static void
handle_action_dollar (symbol_list *rule, char *text, location dollar_loc) handle_action_dollar (symbol_list *rule, char *text, const location *dollar_loc)
{ {
symbol_list *effective_rule; symbol_list *effective_rule;
int effective_rule_length; int effective_rule_length;
@@ -634,13 +635,13 @@ handle_action_dollar (symbol_list *rule, char *text, location dollar_loc)
if (union_seen || tag_seen) if (union_seen || tag_seen)
{ {
if (rule->midrule_parent_rule) if (rule->midrule_parent_rule)
complain (&dollar_loc, complaint, complain (dollar_loc, complaint,
_("$$ for the midrule at $%d of %s" _("$$ for the midrule at $%d of %s"
" has no declared type"), " has no declared type"),
rule->midrule_parent_rhs_index, rule->midrule_parent_rhs_index,
quote (effective_rule->content.sym->tag)); quote (effective_rule->content.sym->tag));
else else
complain (&dollar_loc, complaint, complain (dollar_loc, complaint,
_("$$ of %s has no declared type"), _("$$ of %s has no declared type"),
quote (rule->content.sym->tag)); quote (rule->content.sym->tag));
} }
@@ -666,7 +667,7 @@ handle_action_dollar (symbol_list *rule, char *text, location dollar_loc)
&& (!sym || !sym->content.sym->content->type_name)) && (!sym || !sym->content.sym->content->type_name))
{ {
if (union_seen || tag_seen) if (union_seen || tag_seen)
complain (&dollar_loc, complaint, complain (dollar_loc, complaint,
_("$%s of %s has no declared type"), cp, _("$%s of %s has no declared type"), cp,
quote (effective_rule->content.sym->tag)); quote (effective_rule->content.sym->tag));
else else
@@ -689,7 +690,7 @@ handle_action_dollar (symbol_list *rule, char *text, location dollar_loc)
{ {
if (muscle_percent_define_ifdef ("api.value.automove") if (muscle_percent_define_ifdef ("api.value.automove")
&& sym->action_props.is_value_used) && sym->action_props.is_value_used)
complain (&dollar_loc, Wother, complain (dollar_loc, Wother,
_("multiple occurrences of $%d with api.value.automove"), _("multiple occurrences of $%d with api.value.automove"),
n); n);
sym->action_props.is_value_used = true; sym->action_props.is_value_used = true;
@@ -706,7 +707,7 @@ handle_action_dollar (symbol_list *rule, char *text, location dollar_loc)
`------------------------------------------------------*/ `------------------------------------------------------*/
static void static void
handle_action_at (symbol_list *rule, char *text, location at_loc) handle_action_at (symbol_list *rule, char *text, const location *at_loc)
{ {
symbol_list *effective_rule; symbol_list *effective_rule;
int effective_rule_length; int effective_rule_length;
@@ -722,7 +723,7 @@ handle_action_at (symbol_list *rule, char *text, location at_loc)
effective_rule_length = symbol_list_length (rule->next); effective_rule_length = symbol_list_length (rule->next);
} }
muscle_percent_define_ensure("locations", at_loc, true); muscle_percent_define_ensure ("locations", *at_loc, true);
int n = parse_ref (text + 1, effective_rule, effective_rule_length, int n = parse_ref (text + 1, effective_rule, effective_rule_length,
rule->midrule_parent_rhs_index, text, at_loc, '@'); rule->midrule_parent_rhs_index, text, at_loc, '@');
+6 -9
View File
@@ -21,18 +21,15 @@
#ifndef SCAN_GRAM_H_ #ifndef SCAN_GRAM_H_
# define SCAN_GRAM_H_ # define SCAN_GRAM_H_
/* From the scanner. */ /* Initialize the scanner to read file GRAM. */
extern FILE *gram_in; void gram_scanner_open (const char *gram);
extern int gram__flex_debug; /* Close the open files. */
void gram_scanner_initialize (void); void gram_scanner_close (void);
/* Free all the memory allocated to the scanner. */
void gram_scanner_free (void); void gram_scanner_free (void);
void gram_scanner_last_string_free (void); void gram_scanner_last_string_free (void);
/* These are declared by the scanner, but not used. We put them here
to pacify "make syntax-check". */
extern FILE *gram_out;
extern int gram_lineno;
# define GRAM_LEX_DECL int gram_lex (GRAM_STYPE *val, location *loc) # define GRAM_LEX_DECL int gram_lex (GRAM_STYPE *val, location *loc)
GRAM_LEX_DECL; GRAM_LEX_DECL;
+54 -94
View File
@@ -21,6 +21,8 @@
%option prefix="gram_" outfile="lex.yy.c" %option prefix="gram_" outfile="lex.yy.c"
%{ %{
#include <errno.h>
#include <c-ctype.h> #include <c-ctype.h>
#include <mbswidth.h> #include <mbswidth.h>
#include <quote.h> #include <quote.h>
@@ -49,9 +51,6 @@ static boundary scanner_cursor;
#define YY_USER_ACTION location_compute (loc, &scanner_cursor, yytext, yyleng); #define YY_USER_ACTION location_compute (loc, &scanner_cursor, yytext, yyleng);
static size_t no_cr_read (FILE *, char *, size_t);
#define YY_INPUT(buf, result, size) ((result) = no_cr_read (yyin, buf, size))
/* Report that yytext is an extension, and evaluate to its token type. */ /* Report that yytext is an extension, and evaluate to its token type. */
#define BISON_DIRECTIVE(Directive) \ #define BISON_DIRECTIVE(Directive) \
(bison_directive (loc, yytext), PERCENT_ ## Directive) (bison_directive (loc, yytext), PERCENT_ ## Directive)
@@ -84,6 +83,9 @@ static size_t no_cr_read (FILE *, char *, size_t);
unput (Msg[i - 1]); \ unput (Msg[i - 1]); \
} while (0) } while (0)
/* The current file name. Might change with #line. */
static uniqstr current_file = NULL;
/* A string representing the most recently saved token. */ /* A string representing the most recently saved token. */
static char *last_string = NULL; static char *last_string = NULL;
@@ -100,7 +102,7 @@ gram_scanner_last_string_free (void)
} }
static void handle_syncline (char *, location); static void handle_syncline (char *, location);
static unsigned long scan_integer (char const *p, int base, location loc); static int scan_integer (char const *p, int base, location loc);
static int convert_ucn_to_byte (char const *hex_text); static int convert_ucn_to_byte (char const *hex_text);
static void unexpected_eof (boundary, char const *); static void unexpected_eof (boundary, char const *);
static void unexpected_newline (boundary, char const *); static void unexpected_newline (boundary, char const *);
@@ -139,12 +141,14 @@ id {letter}({letter}|[-0-9])*
int [0-9]+ int [0-9]+
xint 0[xX][0-9abcdefABCDEF]+ xint 0[xX][0-9abcdefABCDEF]+
eol \n|\r\n
/* UTF-8 Encoded Unicode Code Point, from Flex's documentation. */ /* UTF-8 Encoded Unicode Code Point, from Flex's documentation. */
mbchar [\x09\x0A\x0D\x20-\x7E]|[\xC2-\xDF][\x80-\xBF]|\xE0[\xA0-\xBF][\x80-\xBF]|[\xE1-\xEC\xEE\xEF]([\x80-\xBF]{2})|\xED[\x80-\x9F][\x80-\xBF]|\xF0[\x\90-\xBF]([\x80-\xBF]{2})|[\xF1-\xF3]([\x80-\xBF]{3})|\xF4[\x80-\x8F]([\x80-\xBF]{2}) mbchar [\x09\x0A\x0D\x20-\x7E]|[\xC2-\xDF][\x80-\xBF]|\xE0[\xA0-\xBF][\x80-\xBF]|[\xE1-\xEC\xEE\xEF]([\x80-\xBF]{2})|\xED[\x80-\x9F][\x80-\xBF]|\xF0[\x\90-\xBF]([\x80-\xBF]{2})|[\xF1-\xF3]([\x80-\xBF]{3})|\xF4[\x80-\x8F]([\x80-\xBF]{2})
/* 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]*{eol})*
/* An equal sign, with optional leading whitespaces. This is used in some /* An equal sign, with optional leading whitespaces. This is used in some
deprecated constructs. */ deprecated constructs. */
@@ -193,7 +197,7 @@ eqopt ({sp}=)?
"," { "," {
complain (loc, Wother, _("stray ',' treated as white space")); complain (loc, Wother, _("stray ',' treated as white space"));
} }
[ \f\n\t\v] | [ \f\t\v\r]|{eol} |
"//".* continue; "//".* continue;
"/*" { "/*" {
token_start = loc->start; token_start = loc->start;
@@ -201,9 +205,7 @@ eqopt ({sp}=)?
BEGIN SC_YACC_COMMENT; BEGIN SC_YACC_COMMENT;
} }
/* #line directives are not documented, and may be withdrawn or ^"#line "{int}(" \"".*"\"")?{eol} {
modified in future versions of Bison. */
^"#line "{int}(" \"".*"\"")?"\n" {
handle_syncline (yytext + sizeof "#line " - 1, *loc); handle_syncline (yytext + sizeof "#line " - 1, *loc);
} }
} }
@@ -233,7 +235,6 @@ eqopt ({sp}=)?
"%expect" return BISON_DIRECTIVE (EXPECT); "%expect" return BISON_DIRECTIVE (EXPECT);
"%expect-rr" return BISON_DIRECTIVE (EXPECT_RR); "%expect-rr" return BISON_DIRECTIVE (EXPECT_RR);
"%file-prefix" RETURN_VALUE (PERCENT_FILE_PREFIX, uniqstr_new (yytext)); "%file-prefix" RETURN_VALUE (PERCENT_FILE_PREFIX, uniqstr_new (yytext));
"%fixed-output-files" RETURN_VALUE (PERCENT_YACC, uniqstr_new (yytext));
"%initial-action" return BISON_DIRECTIVE (INITIAL_ACTION); "%initial-action" return BISON_DIRECTIVE (INITIAL_ACTION);
"%glr-parser" return BISON_DIRECTIVE (GLR_PARSER); "%glr-parser" return BISON_DIRECTIVE (GLR_PARSER);
"%language" return BISON_DIRECTIVE (LANGUAGE); "%language" return BISON_DIRECTIVE (LANGUAGE);
@@ -262,7 +263,7 @@ eqopt ({sp}=)?
"%type" return PERCENT_TYPE; "%type" return PERCENT_TYPE;
"%union" return PERCENT_UNION; "%union" return PERCENT_UNION;
"%verbose" return BISON_DIRECTIVE (VERBOSE); "%verbose" return BISON_DIRECTIVE (VERBOSE);
"%yacc" RETURN_VALUE (PERCENT_YACC, uniqstr_new (yytext)); "%yacc" return PERCENT_YACC;
/* Deprecated since Bison 2.3b (2008-05-27), but the warning is /* Deprecated since Bison 2.3b (2008-05-27), but the warning is
issued only since Bison 3.4. */ issued only since Bison 3.4. */
@@ -281,7 +282,7 @@ eqopt ({sp}=)?
"%error"[-_]"verbose" RETURN_VALUE (PERCENT_ERROR_VERBOSE, uniqstr_new (yytext)); "%error"[-_]"verbose" RETURN_VALUE (PERCENT_ERROR_VERBOSE, uniqstr_new (yytext));
"%expect"[-_]"rr" DEPRECATED ("%expect-rr"); "%expect"[-_]"rr" DEPRECATED ("%expect-rr");
"%file-prefix"{eqopt} RETURN_VALUE (PERCENT_FILE_PREFIX, uniqstr_new (yytext)); "%file-prefix"{eqopt} RETURN_VALUE (PERCENT_FILE_PREFIX, uniqstr_new (yytext));
"%fixed"[-_]"output"[-_]"files" RETURN_VALUE (PERCENT_YACC, uniqstr_new (yytext)); "%fixed"[-_]"output"[-_]"files" DEPRECATED ("%output \"y.tab.c\"");
"%no"[-_]"default"[-_]"prec" DEPRECATED ("%no-default-prec"); "%no"[-_]"default"[-_]"prec" DEPRECATED ("%no-default-prec");
"%no"[-_]"lines" DEPRECATED ("%no-lines"); "%no"[-_]"lines" DEPRECATED ("%no-lines");
"%output"{eqopt} DEPRECATED ("%output"); "%output"{eqopt} DEPRECATED ("%output");
@@ -330,7 +331,7 @@ eqopt ({sp}=)?
} }
/* Semantic predicate. */ /* Semantic predicate. */
"%?"[ \f\n\t\v]*"{" { "%?"([ \f\t\v]|{eol})*"{" {
nesting = 0; nesting = 0;
code_start = loc->start; code_start = loc->start;
BEGIN SC_PREDICATE; BEGIN SC_PREDICATE;
@@ -359,7 +360,7 @@ eqopt ({sp}=)?
BEGIN SC_BRACKETED_ID; BEGIN SC_BRACKETED_ID;
} }
[^\[%A-Za-z0-9_<>{}\"\'*;|=/, \f\n\t\v]+|. { [^\[%A-Za-z0-9_<>{}\"\'*;|=/, \f\r\n\t\v]+|. {
complain (loc, complaint, "%s: %s", complain (loc, complaint, "%s: %s",
ngettext ("invalid character", "invalid characters", yyleng), ngettext ("invalid character", "invalid characters", yyleng),
quote_mem (yytext, yyleng)); quote_mem (yytext, yyleng));
@@ -458,7 +459,7 @@ eqopt ({sp}=)?
complain (loc, complaint, _("an identifier expected")); complain (loc, complaint, _("an identifier expected"));
} }
[^\].A-Za-z0-9_/ \f\n\t\v]+|. { [^\].A-Za-z0-9_/ \f\r\n\t\v]+|. {
complain (loc, complaint, "%s: %s", complain (loc, complaint, "%s: %s",
ngettext ("invalid character in bracketed name", ngettext ("invalid character in bracketed name",
"invalid characters in bracketed name", yyleng), "invalid characters in bracketed name", yyleng),
@@ -491,7 +492,7 @@ eqopt ({sp}=)?
<SC_YACC_COMMENT> <SC_YACC_COMMENT>
{ {
"*/" BEGIN context_state; "*/" BEGIN context_state;
.|\n continue; .|{eol} continue;
<<EOF>> unexpected_eof (token_start, "*/"); BEGIN context_state; <<EOF>> unexpected_eof (token_start, "*/"); BEGIN context_state;
} }
@@ -513,7 +514,7 @@ eqopt ({sp}=)?
<SC_LINE_COMMENT> <SC_LINE_COMMENT>
{ {
"\n" STRING_GROW; BEGIN context_state; {eol} STRING_GROW; BEGIN context_state;
{splice} STRING_GROW; {splice} STRING_GROW;
<<EOF>> BEGIN context_state; <<EOF>> BEGIN context_state;
} }
@@ -535,7 +536,7 @@ eqopt ({sp}=)?
RETURN_VALUE (STRING, last_string); RETURN_VALUE (STRING, last_string);
} }
<<EOF>> unexpected_eof (token_start, "\""); <<EOF>> unexpected_eof (token_start, "\"");
"\n" unexpected_newline (token_start, "\""); {eol} unexpected_newline (token_start, "\"");
} }
/*----------------------------------------------------------. /*----------------------------------------------------------.
@@ -564,7 +565,7 @@ eqopt ({sp}=)?
BEGIN INITIAL; BEGIN INITIAL;
return CHAR; return CHAR;
} }
"\n" unexpected_newline (token_start, "'"); {eol} unexpected_newline (token_start, "'");
<<EOF>> unexpected_eof (token_start, "'"); <<EOF>> unexpected_eof (token_start, "'");
} }
@@ -604,22 +605,22 @@ eqopt ({sp}=)?
{ {
\\[0-7]{1,3} { \\[0-7]{1,3} {
verify (UCHAR_MAX < ULONG_MAX); verify (UCHAR_MAX < ULONG_MAX);
unsigned long c = strtoul (yytext + 1, NULL, 8); long c = strtol (yytext + 1, NULL, 8);
if (!c || UCHAR_MAX < c) if (0 < c && c <= UCHAR_MAX)
obstack_1grow (&obstack_for_string, c);
else
complain (loc, complaint, _("invalid number after \\-escape: %s"), complain (loc, complaint, _("invalid number after \\-escape: %s"),
yytext+1); yytext+1);
else
obstack_1grow (&obstack_for_string, c);
} }
\\x[0-9abcdefABCDEF]+ { \\x[0-9abcdefABCDEF]+ {
verify (UCHAR_MAX < ULONG_MAX); verify (UCHAR_MAX < ULONG_MAX);
unsigned long c = strtoul (yytext + 2, NULL, 16); long c = strtol (yytext + 2, NULL, 16);
if (!c || UCHAR_MAX < c) if (0 < c && c <= UCHAR_MAX)
obstack_1grow (&obstack_for_string, c);
else
complain (loc, complaint, _("invalid number after \\-escape: %s"), complain (loc, complaint, _("invalid number after \\-escape: %s"),
yytext+1); yytext+1);
else
obstack_1grow (&obstack_for_string, c);
} }
\\a obstack_1grow (&obstack_for_string, '\a'); \\a obstack_1grow (&obstack_for_string, '\a');
@@ -641,7 +642,7 @@ eqopt ({sp}=)?
else else
obstack_1grow (&obstack_for_string, c); obstack_1grow (&obstack_for_string, c);
} }
\\(.|\n) { \\(.|{eol}) {
char const *p = yytext + 1; char const *p = yytext + 1;
/* Quote only if escaping won't make the character visible. */ /* Quote only if escaping won't make the character visible. */
if (c_isspace ((unsigned char) *p) && c_isprint ((unsigned char) *p)) if (c_isspace ((unsigned char) *p) && c_isprint ((unsigned char) *p))
@@ -665,14 +666,14 @@ eqopt ({sp}=)?
<SC_CHARACTER> <SC_CHARACTER>
{ {
"'" STRING_GROW; BEGIN context_state; "'" STRING_GROW; BEGIN context_state;
\n unexpected_newline (token_start, "'"); {eol} unexpected_newline (token_start, "'");
<<EOF>> unexpected_eof (token_start, "'"); <<EOF>> unexpected_eof (token_start, "'");
} }
<SC_STRING> <SC_STRING>
{ {
"\"" STRING_GROW; BEGIN context_state; "\"" STRING_GROW; BEGIN context_state;
\n unexpected_newline (token_start, "\""); {eol} unexpected_newline (token_start, "\"");
<<EOF>> unexpected_eof (token_start, "\""); <<EOF>> unexpected_eof (token_start, "\"");
} }
@@ -809,59 +810,12 @@ eqopt ({sp}=)?
%% %%
/* Read bytes from FP into buffer BUF of size SIZE. Return the
number of bytes read. Remove '\r' from input, treating \r\n
and isolated \r as \n. */
static size_t
no_cr_read (FILE *fp, char *buf, size_t size)
{
size_t bytes_read = fread (buf, 1, size, fp);
if (bytes_read)
{
char *w = memchr (buf, '\r', bytes_read);
if (w)
{
char const *r = ++w;
char const *lim = buf + bytes_read;
for (;;)
{
/* Found an '\r'. Treat it like '\n', but ignore any
'\n' that immediately follows. */
w[-1] = '\n';
if (r == lim)
{
int ch = getc (fp);
if (ch != '\n' && ungetc (ch, fp) != ch)
break;
}
else if (*r == '\n')
r++;
/* Copy until the next '\r'. */
do
{
if (r == lim)
return w - buf;
}
while ((*w++ = *r++) != '\r');
}
return w - buf;
}
}
return bytes_read;
}
/*------------------------------------------------------. /*------------------------------------------------------.
| Scan NUMBER for a base-BASE integer at location LOC. | | Scan NUMBER for a base-BASE integer at location LOC. |
`------------------------------------------------------*/ `------------------------------------------------------*/
static unsigned long static int
scan_integer (char const *number, int base, location loc) scan_integer (char const *number, int base, location loc)
{ {
verify (INT_MAX < ULONG_MAX); verify (INT_MAX < ULONG_MAX);
@@ -869,9 +823,10 @@ scan_integer (char const *number, int base, location loc)
complain (&loc, Wyacc, complain (&loc, Wyacc,
_("POSIX Yacc does not support hexadecimal literals")); _("POSIX Yacc does not support hexadecimal literals"));
unsigned long num = strtoul (number, NULL, base); errno = 0;
long num = strtol (number, NULL, base);
if (INT_MAX < num) if (! (0 <= num && num <= INT_MAX && errno == 0))
{ {
complain (&loc, complaint, _("integer out of range: %s"), complain (&loc, complaint, _("integer out of range: %s"),
quote (number)); quote (number));
@@ -892,7 +847,7 @@ static int
convert_ucn_to_byte (char const *ucn) convert_ucn_to_byte (char const *ucn)
{ {
verify (UCHAR_MAX <= INT_MAX); verify (UCHAR_MAX <= INT_MAX);
unsigned long code = strtoul (ucn + 2, NULL, 16); long code = strtol (ucn + 2, NULL, 16);
/* FIXME: Currently we assume Unicode-compatible unibyte characters /* FIXME: Currently we assume Unicode-compatible unibyte characters
on ASCII hosts (i.e., Latin-1 on hosts with 8-bit bytes). On on ASCII hosts (i.e., Latin-1 on hosts with 8-bit bytes). On
@@ -900,7 +855,7 @@ convert_ucn_to_byte (char const *ucn)
These limitations should be removed once we add support for These limitations should be removed once we add support for
multibyte characters. */ multibyte characters. */
if (UCHAR_MAX < code) if (! (0 <= code && code <= UCHAR_MAX))
return -1; return -1;
#if ! ('$' == 0x24 && '@' == 0x40 && '`' == 0x60 && '~' == 0x7e) #if ! ('$' == 0x24 && '@' == 0x40 && '`' == 0x60 && '~' == 0x7e)
@@ -947,8 +902,9 @@ static void
handle_syncline (char *args, location loc) handle_syncline (char *args, location loc)
{ {
char *file; char *file;
unsigned long lineno = strtoul (args, &file, 10); errno = 0;
if (INT_MAX <= lineno) long lineno = strtol (args, &file, 10);
if (! (0 <= lineno && lineno <= INT_MAX && errno == 0))
{ {
complain (&loc, Wother, _("line number overflow")); complain (&loc, Wother, _("line number overflow"));
lineno = INT_MAX; lineno = INT_MAX;
@@ -1018,25 +974,29 @@ unexpected_newline (boundary start, char const *token_end)
} }
/*-------------------------.
| Initialize the scanner. |
`-------------------------*/
void void
gram_scanner_initialize (void) gram_scanner_open (const char *gram)
{ {
gram__flex_debug = trace_flag & trace_scan;
gram_debug = trace_flag & trace_parse;
obstack_init (&obstack_for_string); obstack_init (&obstack_for_string);
current_file = gram;
gram_in = xfopen (gram, "r");
}
void
gram_scanner_close ()
{
xfclose (gram_in);
/* Reclaim Flex's buffers. */
yylex_destroy ();
} }
/*-----------------------------------------------.
| Free all the memory allocated to the scanner. |
`-----------------------------------------------*/
void void
gram_scanner_free (void) gram_scanner_free (void)
{ {
obstack_free (&obstack_for_string, 0); obstack_free (&obstack_for_string, 0);
/* Reclaim Flex's buffers. */
yylex_destroy ();
} }
+1 -1
View File
@@ -209,7 +209,7 @@ at_basename (int argc, char *argv[], char **out_namep, int *out_linenop)
static void static void
at_complain (int argc, char *argv[], char **out_namep, int *out_linenop) at_complain (int argc, char *argv[], char **out_namep, int *out_linenop)
{ {
static unsigned indent; static int indent;
warnings w = flag (argv[1]); warnings w = flag (argv[1]);
location loc; location loc;
location *locp = NULL; location *locp = NULL;
+136 -92
View File
@@ -24,18 +24,27 @@
#include "system.h" #include "system.h"
#include <assure.h> #include <assure.h>
#include <fstrcmp.h>
#include <hash.h> #include <hash.h>
#include "complain.h" #include "complain.h"
#include "getargs.h"
#include "gram.h" #include "gram.h"
#include "intprops.h"
#include "quote.h"
/*-------------------------------------------------------------------.
| Symbols sorted by tag. Allocated by the first invocation of | static struct hash_table *symbol_table = NULL;
| symbols_do, after which no more symbols should be created. | static struct hash_table *semantic_type_table = NULL;
`-------------------------------------------------------------------*/
/*----------------------------------------------------------------.
| Symbols sorted by tag. Allocated by table_sort, after which no |
| more symbols should be created. |
`----------------------------------------------------------------*/
static symbol **symbols_sorted = NULL; static symbol **symbols_sorted = NULL;
static symbol **semantic_types_sorted = NULL; static semantic_type **semantic_types_sorted = NULL;
/*------------------------. /*------------------------.
| Distinguished symbols. | | Distinguished symbols. |
@@ -149,8 +158,8 @@ symbol_free (void *ptr)
declaration first. declaration first.
*/ */
static static void
void symbols_sort (symbol **first, symbol **second) symbols_sort (symbol **first, symbol **second)
{ {
if (0 < location_cmp ((*first)->location, (*second)->location)) if (0 < location_cmp ((*first)->location, (*second)->location))
{ {
@@ -162,8 +171,8 @@ void symbols_sort (symbol **first, symbol **second)
/* Likewise, for locations. */ /* Likewise, for locations. */
static static void
void locations_sort (location *first, location *second) locations_sort (location *first, location *second)
{ {
if (0 < location_cmp (*first, *second)) if (0 < location_cmp (*first, *second))
{ {
@@ -279,7 +288,7 @@ static void
complain_symbol_redeclared (symbol *s, const char *what, location first, complain_symbol_redeclared (symbol *s, const char *what, location first,
location second) location second)
{ {
unsigned i = 0; int i = 0;
locations_sort (&first, &second); locations_sort (&first, &second);
complain_indent (&second, complaint, &i, complain_indent (&second, complaint, &i,
_("%s redeclaration for %s"), what, s->tag); _("%s redeclaration for %s"), what, s->tag);
@@ -292,7 +301,7 @@ static void
complain_semantic_type_redeclared (semantic_type *s, const char *what, location first, complain_semantic_type_redeclared (semantic_type *s, const char *what, location first,
location second) location second)
{ {
unsigned i = 0; int i = 0;
locations_sort (&first, &second); locations_sort (&first, &second);
complain_indent (&second, complaint, &i, complain_indent (&second, complaint, &i,
_("%s redeclaration for <%s>"), what, s->tag); _("%s redeclaration for <%s>"), what, s->tag);
@@ -304,7 +313,7 @@ complain_semantic_type_redeclared (semantic_type *s, const char *what, location
static void static void
complain_class_redeclared (symbol *sym, symbol_class class, location second) complain_class_redeclared (symbol *sym, symbol_class class, location second)
{ {
unsigned i = 0; int i = 0;
complain_indent (&second, complaint, &i, complain_indent (&second, complaint, &i,
class == token_sym class == token_sym
? _("symbol %s redeclared as a token") ? _("symbol %s redeclared as a token")
@@ -317,6 +326,55 @@ complain_class_redeclared (symbol *sym, symbol_class class, location second)
} }
} }
static const symbol *
symbol_from_uniqstr_fuzzy (const uniqstr key)
{
aver (symbols_sorted);
#define FSTRCMP_THRESHOLD 0.6
double best_similarity = FSTRCMP_THRESHOLD;
const symbol *res = NULL;
size_t count = hash_get_n_entries (symbol_table);
for (int i = 0; i < count; ++i)
{
symbol *sym = symbols_sorted[i];
if (STRNEQ (key, sym->tag)
&& (sym->content->status == declared
|| sym->content->status == undeclared))
{
double similarity = fstrcmp_bounded (key, sym->tag, best_similarity);
if (best_similarity < similarity)
{
res = sym;
best_similarity = similarity;
}
}
}
return res;
}
static void
complain_symbol_undeclared (symbol *sym)
{
assert (sym->content->status != declared);
const symbol *best = symbol_from_uniqstr_fuzzy (sym->tag);
if (best)
{
complain (&sym->location,
sym->content->status == needed ? complaint : Wother,
_("symbol %s is used, but is not defined as a token"
" and has no rules; did you mean %s?"),
quote_n (0, sym->tag),
quote_n (1, best->tag));
if (feature_flag & feature_caret)
location_caret_suggestion (sym->location, best->tag, stderr);
}
else
complain (&sym->location,
sym->content->status == needed ? complaint : Wother,
_("symbol %s is used, but is not defined as a token"
" and has no rules"),
quote (sym->tag));
}
void void
symbol_location_as_lhs_set (symbol *sym, location loc) symbol_location_as_lhs_set (symbol *sym, location loc)
@@ -463,8 +521,9 @@ symbol_class_set (symbol *sym, symbol_class class, location loc, bool declaring)
{ {
if (s->status == declared) if (s->status == declared)
{ {
unsigned i = 0; int i = 0;
complain (&loc, Wother, _("symbol %s redeclared"), sym->tag); complain_indent (&loc, Wother, &i,
_("symbol %s redeclared"), sym->tag);
i += SUB_INDENT; i += SUB_INDENT;
complain_indent (&sym->location, Wother, &i, complain_indent (&sym->location, Wother, &i,
_("previous declaration")); _("previous declaration"));
@@ -491,6 +550,9 @@ symbol_user_token_number_set (symbol *sym, int user_token_number, location loc)
&& *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"),
sym->tag); sym->tag);
else if (user_token_number == INT_MAX)
complain (&loc, complaint, _("user token number of %s too large"),
sym->tag);
else else
{ {
*user_token_numberp = user_token_number; *user_token_numberp = user_token_number;
@@ -513,18 +575,13 @@ symbol_user_token_number_set (symbol *sym, int user_token_number, location loc)
| nonterminal. | | nonterminal. |
`----------------------------------------------------------*/ `----------------------------------------------------------*/
static inline bool static void
symbol_check_defined (symbol *sym) symbol_check_defined (symbol *sym)
{ {
sym_content *s = sym->content; sym_content *s = sym->content;
if (s->class == unknown_sym) if (s->class == unknown_sym)
{ {
assert (s->status != declared); complain_symbol_undeclared (sym);
complain (&sym->location,
s->status == needed ? complaint : Wother,
_("symbol %s is used, but is not defined as a token"
" and has no rules"),
sym->tag);
s->class = nterm_sym; s->class = nterm_sym;
s->number = nvars++; s->number = nvars++;
} }
@@ -540,11 +597,9 @@ symbol_check_defined (symbol *sym)
if (sem_type) if (sem_type)
sem_type->status = declared; sem_type->status = declared;
} }
return true;
} }
static inline bool static void
semantic_type_check_defined (semantic_type *sem_type) semantic_type_check_defined (semantic_type *sem_type)
{ {
/* <*> and <> do not have to be "declared". */ /* <*> and <> do not have to be "declared". */
@@ -563,24 +618,8 @@ semantic_type_check_defined (semantic_type *sem_type)
complain (&sem_type->location, Wother, complain (&sem_type->location, Wother,
_("type <%s> is used, but is not associated to any symbol"), _("type <%s> is used, but is not associated to any symbol"),
sem_type->tag); sem_type->tag);
return true;
} }
static bool
symbol_check_defined_processor (void *sym, void *null ATTRIBUTE_UNUSED)
{
return symbol_check_defined (sym);
}
static bool
semantic_type_check_defined_processor (void *sem_type,
void *null ATTRIBUTE_UNUSED)
{
return semantic_type_check_defined (sem_type);
}
/*-------------------------------------------------------------------. /*-------------------------------------------------------------------.
| Merge the properties (precedence, associativity, etc.) of SYM, and | | Merge the properties (precedence, associativity, etc.) of SYM, and |
| its string-named alias STR; check consistency. | | its string-named alias STR; check consistency. |
@@ -647,7 +686,7 @@ symbol_make_alias (symbol *sym, symbol *str, location loc)
| into FDEFINES. Put in SYMBOLS. | | into FDEFINES. Put in SYMBOLS. |
`-------------------------------------------------------------------*/ `-------------------------------------------------------------------*/
static inline bool static void
symbol_pack (symbol *this) symbol_pack (symbol *this)
{ {
aver (this->content->number != NUMBER_UNDEFINED); aver (this->content->number != NUMBER_UNDEFINED);
@@ -655,19 +694,12 @@ symbol_pack (symbol *this)
this->content->number += ntokens; this->content->number += ntokens;
symbols[this->content->number] = this->content->symbol; symbols[this->content->number] = this->content->symbol;
return true;
}
static bool
symbol_pack_processor (void *this, void *null ATTRIBUTE_UNUSED)
{
return symbol_pack (this);
} }
static void static void
complain_user_token_number_redeclared (int num, symbol *first, symbol *second) complain_user_token_number_redeclared (int num, symbol *first, symbol *second)
{ {
unsigned i = 0; int i = 0;
symbols_sort (&first, &second); symbols_sort (&first, &second);
complain_indent (&second->location, complaint, &i, complain_indent (&second->location, complaint, &i,
_("user token number %d redeclaration for %s"), _("user token number %d redeclaration for %s"),
@@ -682,7 +714,7 @@ complain_user_token_number_redeclared (int num, symbol *first, symbol *second)
| Put THIS in TOKEN_TRANSLATIONS if it is a token. | | Put THIS in TOKEN_TRANSLATIONS if it is a token. |
`--------------------------------------------------*/ `--------------------------------------------------*/
static inline bool static void
symbol_translation (symbol *this) symbol_translation (symbol *this)
{ {
/* Nonterminal? */ /* Nonterminal? */
@@ -699,14 +731,6 @@ symbol_translation (symbol *this)
token_translations[this->content->user_token_number] token_translations[this->content->user_token_number]
= this->content->number; = this->content->number;
} }
return true;
}
static bool
symbol_translation_processor (void *this, void *null ATTRIBUTE_UNUSED)
{
return symbol_translation (this);
} }
@@ -717,9 +741,6 @@ symbol_translation_processor (void *this, void *null ATTRIBUTE_UNUSED)
/* Initial capacity of symbol and semantic type hash table. */ /* Initial capacity of symbol and semantic type hash table. */
#define HT_INITIAL_CAPACITY 257 #define HT_INITIAL_CAPACITY 257
static struct hash_table *symbol_table = NULL;
static struct hash_table *semantic_type_table = NULL;
static inline bool static inline bool
hash_compare_symbol (const symbol *m1, const symbol *m2) hash_compare_symbol (const symbol *m1, const symbol *m2)
{ {
@@ -784,6 +805,23 @@ symbols_new (void)
hash_symbol_hasher, hash_symbol_hasher,
hash_symbol_comparator, hash_symbol_comparator,
symbol_free); symbol_free);
/* Construct the accept symbol. */
accept = symbol_get ("$accept", empty_loc);
accept->content->class = nterm_sym;
accept->content->number = nvars++;
/* Construct the error token */
errtoken = symbol_get ("error", empty_loc);
errtoken->content->class = token_sym;
errtoken->content->number = ntokens++;
/* Construct a token that represents all undefined literal tokens.
It is always token number 2. */
undeftoken = symbol_get ("$undefined", empty_loc);
undeftoken->content->class = token_sym;
undeftoken->content->number = ntokens++;
semantic_type_table = hash_xinitialize (HT_INITIAL_CAPACITY, semantic_type_table = hash_xinitialize (HT_INITIAL_CAPACITY,
NULL, NULL,
hash_semantic_type_hasher, hash_semantic_type_hasher,
@@ -905,36 +943,25 @@ symbols_free (void)
} }
/*---------------------------------------------------------------.
| Look for undefined symbols, report an error, and consider them |
| terminals. |
`---------------------------------------------------------------*/
static int static int
symbols_cmp (symbol const *a, symbol const *b) symbol_cmp (void const *a, void const *b)
{ {
return strcmp (a->tag, b->tag); return location_cmp ((*(symbol * const *)a)->location,
(*(symbol * const *)b)->location);
} }
static int /* Store in *SORTED an array of pointers to the symbols contained in
symbols_cmp_qsort (void const *a, void const *b) TABLE, sorted (alphabetically) by tag. */
{
return symbols_cmp (*(symbol * const *)a, *(symbol * const *)b);
}
static void static void
symbols_do (Hash_processor processor, void *processor_data, table_sort (struct hash_table *table, symbol ***sorted)
struct hash_table *table, symbol ***sorted)
{ {
aver (!*sorted);
size_t count = hash_get_n_entries (table); size_t count = hash_get_n_entries (table);
if (!*sorted) *sorted = xnmalloc (count + 1, sizeof **sorted);
{ hash_get_entries (table, (void**)*sorted, count);
*sorted = xnmalloc (count, sizeof **sorted); qsort (*sorted, count, sizeof **sorted, symbol_cmp);
hash_get_entries (table, (void**)*sorted, count); (*sorted)[count] = NULL;
qsort (*sorted, count, sizeof **sorted, symbols_cmp_qsort);
}
for (size_t i = 0; i < count; ++i)
processor ((*sorted)[i], processor_data);
} }
/*--------------------------------------------------------------. /*--------------------------------------------------------------.
@@ -945,10 +972,20 @@ symbols_do (Hash_processor processor, void *processor_data,
void void
symbols_check_defined (void) symbols_check_defined (void)
{ {
symbols_do (symbol_check_defined_processor, NULL, table_sort (symbol_table, &symbols_sorted);
symbol_table, &symbols_sorted); /* semantic_type, like symbol, starts with a 'tag' field and then a
symbols_do (semantic_type_check_defined_processor, NULL, 'location' field. And here we only deal with arrays/hashes of
semantic_type_table, &semantic_types_sorted); pointers, sizeof is not an issue.
So instead of implementing table_sort (and symbol_cmp) once for
each type, let's lie a bit to the typing system, and treat
'semantic_type' as if it were 'symbol'. */
table_sort (semantic_type_table, (symbol ***) &semantic_types_sorted);
for (int i = 0; symbols_sorted[i]; ++i)
symbol_check_defined (symbols_sorted[i]);
for (int i = 0; semantic_types_sorted[i]; ++i)
semantic_type_check_defined (semantic_types_sorted[i]);
} }
/*------------------------------------------------------------------. /*------------------------------------------------------------------.
@@ -989,7 +1026,13 @@ symbols_token_translations_init (void)
{ {
sym_content *this = symbols[i]->content; 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; {
IGNORE_TYPE_LIMITS_BEGIN
if (INT_ADD_WRAPV (max_user_token_number, 1, &max_user_token_number))
complain (NULL, fatal, _("token number too large"));
IGNORE_TYPE_LIMITS_END
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)
max_user_token_number = this->user_token_number; max_user_token_number = this->user_token_number;
} }
@@ -999,10 +1042,10 @@ 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 (int i = 0; i < max_user_token_number + 1; i++) for (int i = 0; i < max_user_token_number + 1; ++i)
token_translations[i] = undeftoken->content->number; token_translations[i] = undeftoken->content->number;
symbols_do (symbol_translation_processor, NULL, for (int i = 0; symbols_sorted[i]; ++i)
symbol_table, &symbols_sorted); symbol_translation (symbols_sorted[i]);
} }
@@ -1015,7 +1058,8 @@ void
symbols_pack (void) symbols_pack (void)
{ {
symbols = xcalloc (nsyms, sizeof *symbols); symbols = xcalloc (nsyms, sizeof *symbols);
symbols_do (symbol_pack_processor, NULL, symbol_table, &symbols_sorted); for (int i = 0; symbols_sorted[i]; ++i)
symbol_pack (symbols_sorted[i]);
/* Aliases leave empty slots in symbols, so remove them. */ /* Aliases leave empty slots in symbols, so remove them. */
{ {
+2 -1
View File
@@ -345,7 +345,8 @@ void semantic_type_code_props_set (semantic_type *type,
| Symbol and semantic type tables. | | Symbol and semantic type tables. |
`----------------------------------*/ `----------------------------------*/
/** Create the symbol and semantic type tables. */ /** Create the symbol and semantic type tables, and the built-in
symbols. */
void symbols_new (void); void symbols_new (void);
/** Free all the memory allocated for symbols and semantic types. */ /** Free all the memory allocated for symbols and semantic types. */
+13 -10
View File
@@ -74,6 +74,19 @@ typedef size_t uintptr_t;
# include <xalloc.h> # include <xalloc.h>
/* See https://lists.gnu.org/archive/html/bug-bison/2019-10/msg00061.html. */
# if defined __GNUC__ && ! defined __clang__ && ! defined __ICC && __GNUC__ < 5
# define IGNORE_TYPE_LIMITS_BEGIN \
_Pragma ("GCC diagnostic push") \
_Pragma ("GCC diagnostic ignored \"-Wtype-limits\"")
# define IGNORE_TYPE_LIMITS_END \
_Pragma ("GCC diagnostic pop")
# else
# define IGNORE_TYPE_LIMITS_BEGIN
# define IGNORE_TYPE_LIMITS_END
# endif
/*-----------------. /*-----------------.
| GCC extensions. | | GCC extensions. |
`-----------------*/ `-----------------*/
@@ -249,14 +262,4 @@ typedef size_t uintptr_t;
} \ } \
} while (0) } while (0)
/*---------------------------------------------.
| Debugging memory allocation (must be last). |
`---------------------------------------------*/
# if WITH_DMALLOC
# define DMALLOC_FUNC_CHECK
# include <dmalloc.h>
# endif /* WITH_DMALLOC */
#endif /* ! BISON_SYSTEM_H */ #endif /* ! BISON_SYSTEM_H */
+6 -6
View File
@@ -84,7 +84,7 @@ int nvectors;
static base_number **froms; static base_number **froms;
static base_number **tos; static base_number **tos;
static unsigned **conflict_tos; static int **conflict_tos;
static size_t *tally; static size_t *tally;
static base_number *width; static base_number *width;
@@ -115,9 +115,9 @@ base_number base_ninf = 0;
-nstates..table_size (as an upper bound) */ -nstates..table_size (as an upper bound) */
static bitset pos_set = NULL; static bitset pos_set = NULL;
static unsigned *conflrow; static int *conflrow;
unsigned *conflict_table; int *conflict_table;
unsigned *conflict_list; int *conflict_list;
int conflict_list_cnt; int conflict_list_cnt;
static int conflict_list_free; static int conflict_list_free;
@@ -391,7 +391,7 @@ save_row (state_number s)
/* Allocate non defaulted actions. */ /* Allocate non defaulted actions. */
base_number *sp1 = froms[s] = xnmalloc (count, sizeof *sp1); base_number *sp1 = froms[s] = xnmalloc (count, sizeof *sp1);
base_number *sp2 = tos[s] = xnmalloc (count, sizeof *sp2); base_number *sp2 = tos[s] = xnmalloc (count, sizeof *sp2);
unsigned *sp3 = conflict_tos[s] = int *sp3 = conflict_tos[s] =
nondeterministic_parser ? xnmalloc (count, sizeof *sp3) : NULL; nondeterministic_parser ? xnmalloc (count, sizeof *sp3) : NULL;
/* Store non defaulted actions. */ /* Store non defaulted actions. */
@@ -646,7 +646,7 @@ pack_vector (vector_number vector)
size_t t = tally[i]; size_t t = tally[i];
base_number *from = froms[i]; base_number *from = froms[i];
base_number *to = tos[i]; base_number *to = tos[i];
unsigned *conflict_to = conflict_tos[i]; int *conflict_to = conflict_tos[i];
aver (t != 0); aver (t != 0);
+2 -2
View File
@@ -122,8 +122,8 @@ extern base_number *base;
keep parser tables small. */ keep parser tables small. */
extern base_number base_ninf; extern base_number base_ninf;
extern unsigned *conflict_table; extern int *conflict_table;
extern unsigned *conflict_list; extern int *conflict_list;
extern int conflict_list_cnt; extern int conflict_list_cnt;
extern base_number *table; extern base_number *table;
+25 -20
View File
@@ -134,6 +134,7 @@ AT_BISON_CHECK([-fcaret -Wempty-rule 1.y], [0], [],
[[1.y:11.17-18: warning: empty rule without %empty [-Wempty-rule] [[1.y:11.17-18: warning: empty rule without %empty [-Wempty-rule]
11 | a: /* empty. */ {}; 11 | a: /* empty. */ {};
| ^~ | ^~
| %empty
1.y: warning: fix-its can be applied. Rerun with option '--update'. [-Wother] 1.y: warning: fix-its can be applied. Rerun with option '--update'. [-Wother]
]]) ]])
@@ -149,9 +150,11 @@ AT_BISON_CHECK([-fcaret 2.y], [0], [],
[[2.y:11.17-18: warning: empty rule without %empty [-Wempty-rule] [[2.y:11.17-18: warning: empty rule without %empty [-Wempty-rule]
11 | a: /* empty. */ {}; 11 | a: /* empty. */ {};
| ^~ | ^~
| %empty
2.y:13.17-18: warning: empty rule without %empty [-Wempty-rule] 2.y:13.17-18: warning: empty rule without %empty [-Wempty-rule]
13 | c: /* empty. */ {}; 13 | c: /* empty. */ {};
| ^~ | ^~
| %empty
2.y: warning: fix-its can be applied. Rerun with option '--update'. [-Wother] 2.y: warning: fix-its can be applied. Rerun with option '--update'. [-Wother]
]]) ]])
@@ -342,9 +345,9 @@ int
main (void) main (void)
{]AT_CXX_IF([[ {]AT_CXX_IF([[
yy::parser p; yy::parser p;
p.set_debug_level (!!getenv("YYDEBUG")); p.set_debug_level (!!getenv ("YYDEBUG"));
return p.parse ();]], [[ return p.parse ();]], [[
yydebug = !!getenv("YYDEBUG"); yydebug = !!getenv ("YYDEBUG");
return !!yyparse (]AT_PARAM_IF([0])[);]])[ return !!yyparse (]AT_PARAM_IF([0])[);]])[
} }
]]) ]])
@@ -422,6 +425,7 @@ AT_DATA_GRAMMAR([[input.y]],
]$3[ ]$3[
%code %code
{ {
#include <stdio.h> /* putchar. */
]AT_YYERROR_DECLARE[ ]AT_YYERROR_DECLARE[
]AT_YYLEX_DECLARE[ ]AT_YYLEX_DECLARE[
} }
@@ -769,7 +773,7 @@ static
int c = ]AT_VAL[]m4_ifval([$6], [.ival])[ = counter++; 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[ = ]AT_CXX_IF([(unsigned)], [(int)])[(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 (c <= (int) strlen (source)); assert (c <= (int) strlen (source));
if (source[c]) if (source[c])
@@ -1079,17 +1083,17 @@ AT_DATA_GRAMMAR([[input.y]],
} <*> } <*>
%printer { %printer {
fprintf (yyoutput, "<> printer for '%c' @ %d", $$, @$.first_column); fprintf (yyo, "<> printer for '%c' @ %d", $$, @$.first_column);
} <> } <>
%destructor { %destructor {
fprintf (stdout, "<> destructor for '%c' @ %d.\n", $$, @$.first_column); printf ("<> destructor for '%c' @ %d.\n", $$, @$.first_column);
} <> } <>
%printer { %printer {
fprintf (yyoutput, "'b'/'c' printer for '%c' @ %d", $$, @$.first_column); fprintf (yyo, "'b'/'c' printer for '%c' @ %d", $$, @$.first_column);
} 'b' 'c' } 'b' 'c'
%destructor { %destructor {
fprintf (stdout, "'b'/'c' destructor for '%c' @ %d.\n", $$, @$.first_column); printf ("'b'/'c' destructor for '%c' @ %d.\n", $$, @$.first_column);
} 'b' 'c' } 'b' 'c'
%destructor { %destructor {
@@ -1175,23 +1179,23 @@ AT_DATA_GRAMMAR([[input.y]],
%type <field1> 'e' %type <field1> 'e'
%type <field2> 'f' %type <field2> 'f'
%printer { %printer {
fprintf (yyoutput, "<*>/<field2>/e printer"); fprintf (yyo, "<*>/<field2>/e printer");
} <*> 'e' <field2> } <*> 'e' <field2>
%destructor { %destructor {
fprintf (stdout, "<*>/<field2>/e destructor.\n"); printf ("<*>/<field2>/e destructor.\n");
} <*> 'e' <field2> } <*> 'e' <field2>
%type <field1> 'b' %type <field1> 'b'
%printer { fprintf (yyoutput, "<field1> printer"); } <field1> %printer { fprintf (yyo, "<field1> printer"); } <field1>
%destructor { fprintf (stdout, "<field1> destructor.\n"); } <field1> %destructor { printf ("<field1> destructor.\n"); } <field1>
%type <field0> 'c' %type <field0> 'c'
%printer { fprintf (yyoutput, "'c' printer"); } 'c' %printer { fprintf (yyo, "'c' printer"); } 'c'
%destructor { fprintf (stdout, "'c' destructor.\n"); } 'c' %destructor { printf ("'c' destructor.\n"); } 'c'
%type <field1> 'd' %type <field1> 'd'
%printer { fprintf (yyoutput, "'d' printer"); } 'd' %printer { fprintf (yyo, "'d' printer"); } 'd'
%destructor { fprintf (stdout, "'d' destructor.\n"); } 'd' %destructor { printf ("'d' destructor.\n"); } 'd'
%destructor { %destructor {
#error "<> destructor should not be used." #error "<> destructor should not be used."
@@ -1300,10 +1304,10 @@ AT_DATA_GRAMMAR([[input]]$1[[.y]],
%token END 0 %token END 0
%printer { %printer {
fprintf (yyoutput, "<]]kind[[> for '%c' @ %d", $$, @$.first_column); fprintf (yyo, "<]]kind[[> for '%c' @ %d", $$, @$.first_column);
} <]]kind[[> } <]]kind[[>
%destructor { %destructor {
fprintf (stdout, "<]]kind[[> for '%c' @ %d.\n", $$, @$.first_column); printf ("<]]kind[[> for '%c' @ %d.\n", $$, @$.first_column);
} <]]kind[[> } <]]kind[[>
%printer { %printer {
@@ -1406,7 +1410,7 @@ AT_DATA_GRAMMAR([[input.y]],
%} %}
%printer { %printer {
fprintf (yyoutput, "'%c'", $$); fprintf (yyo, "'%c'", $$);
} <> <*> } <> <*>
%destructor { %destructor {
fprintf (stderr, "DESTROY '%c'\n", $$); fprintf (stderr, "DESTROY '%c'\n", $$);
@@ -1505,7 +1509,7 @@ AT_DATA_GRAMMAR([[input.y]],
%printer { %printer {
char chr = $$; char chr = $$;
fprintf (yyoutput, "'%c'", chr); fprintf (yyo, "'%c'", chr);
} <> <*> } <> <*>
%destructor { %destructor {
char chr = $$; char chr = $$;
@@ -1555,7 +1559,7 @@ AT_DATA_GRAMMAR([[input.y]],
# define LOCATION_PRINT(File, Loc) # define LOCATION_PRINT(File, Loc)
%} %}
%printer { fprintf (yyoutput, "%d", @$); } <> %printer { fprintf (yyo, "%d", @$); } <>
%destructor { fprintf (stderr, "DESTROY %d\n", @$); } <> %destructor { fprintf (stderr, "DESTROY %d\n", @$); } <>
%printer { #error "<*> printer should not be used" } <*> %printer { #error "<*> printer should not be used" } <*>
%destructor { #error "<*> destructor should not be used" } <*> %destructor { #error "<*> destructor should not be used" } <*>
@@ -1725,6 +1729,7 @@ AT_DATA_GRAMMAR([[input.y]],
# define YYSTYPE sem_type # define YYSTYPE sem_type
]AT_CXX_IF([[ ]AT_CXX_IF([[
# include <cstdio> // EOF.
# include <iostream> # include <iostream>
namespace namespace
{ {
+3 -8
View File
@@ -16,9 +16,8 @@
# 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 'testsuite.h', (srcdir/test), 'config.h' (builddir/lib), and # We need 'testsuite.h' (srcdir/test).
# the gnulib headers (srcdir/lib). CPPFLAGS="-I$abs_top_srcdir/tests @CPPFLAGS@"
CPPFLAGS="-I$abs_top_srcdir/tests -I$abs_top_srcdir/lib -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
# as /bin/sh, sets the shell variable POSIXLY_CORRECT to y, but not # as /bin/sh, sets the shell variable POSIXLY_CORRECT to y, but not
@@ -73,11 +72,7 @@ fi
if $BISON_CXX_WORKS; then if $BISON_CXX_WORKS; then
# See AT_DATA_SOURCE_PROLOGUE. # See AT_DATA_SOURCE_PROLOGUE.
cat >conftest.cc <<EOF cat >conftest.cc <<EOF
#include <config.h> #include <testsuite.h>
/* We don't need perfect functions for these tests. */
#undef malloc
#undef memcmp
#undef realloc
#include <iostream> #include <iostream>
int main () int main ()
+5
View File
@@ -34,6 +34,11 @@ if test -t 2; then
shift shift
fi fi
# We redirect stderr, which breaks the computation of the terminal
# screen width. So export COLUMNS to Bison, hoping for the shell to
# have defined it.
: ${COLUMNS=`tput cols || echo 132`}
export COLUMNS
$PREBISON "$abs_top_builddir/src/bison" ${1+"$@"} 2>"$stderr" $PREBISON "$abs_top_builddir/src/bison" ${1+"$@"} 2>"$stderr"
status=$? status=$?
+63 -2
View File
@@ -760,7 +760,7 @@ EXTRACT_PRIVATE = AT_DOXYGEN_PRIVATE
EXTRACT_STATIC = AT_DOXYGEN_PRIVATE EXTRACT_STATIC = AT_DOXYGEN_PRIVATE
]) ])
AT_CHECK([doxygen --version || exit 77], 0, ignore) AT_REQUIRE([doxygen --version], 0, ignore)
AT_CHECK([doxygen], 0, [], [ignore]) AT_CHECK([doxygen], 0, [], [ignore])
AT_BISON_OPTION_POPDEFS AT_BISON_OPTION_POPDEFS
@@ -988,7 +988,8 @@ yy::parser::error (const std::string &m)
# Another file to check syntax_error's linkage. # Another file to check syntax_error's linkage.
AT_DATA_SOURCE([scan.cc], AT_DATA_SOURCE([scan.cc],
[[#include "input.hh" [[#include <cstdio> // getchar
#include "input.hh"
// 'a': valid item, 's': syntax error, 'l': lexical error. // 'a': valid item, 's': syntax error, 'l': lexical error.
int int
@@ -1479,3 +1480,63 @@ AT_COMPILE_CXX([parser], [[x[12].o main.cc]], [-Iinclude])
AT_PARSER_CHECK([parser], [0]) AT_PARSER_CHECK([parser], [0])
AT_CLEANUP AT_CLEANUP
## ---------------- ##
## Default action. ##
## ---------------- ##
# In C++ we generate explicitly the code for the default action
# instead of simply copying blindly the semantic value buffer. This
# is important when copying raw memory is not enough, as exemplified
# by move-only types.
AT_SETUP([Default action])
AT_KEYWORDS([action])
AT_BISON_OPTION_PUSHDEFS([%skeleton "lalr1.cc"
%define api.token.constructor
%define api.value.type variant])
AT_DATA_GRAMMAR([test.y],
[[%code requires {
#include <memory> // unique_ptr
}
%code {
]AT_YYERROR_DECLARE[
]AT_YYLEX_DECLARE[
}
]AT_BISON_OPTIONS[
%define api.value.automove
%token ONE TWO EOI 0
%type <std::unique_ptr<int>> ONE TWO one two one.opt two.opt
%%
exp: one.opt two.opt { std::cout << *$][1 << ", " << *$][2 << '\n'; }
one.opt: one | %empty {}
two.opt: two | %empty {}
one: ONE
two: TWO
%%
]AT_YYERROR_DEFINE[
]AT_YYLEX_DEFINE(["12"],
[ if (res == '1')
return yy::parser::make_ONE (std::make_unique<int> (10));
else if (res == '2')
return yy::parser::make_TWO (std::make_unique<int> (20));
else
return yy::parser::make_EOI ();
])[
]AT_MAIN_DEFINE[
]])
AT_LANG_FOR_EACH_STD([
AT_REQUIRE_CXX_STD(14, [echo "$at_std not supported"; continue])
AT_FULL_COMPILE([[test]], [], [], [], [-fcaret])
AT_PARSER_CHECK([[test]], 0, [[10, 20
]])
])
AT_BISON_OPTION_POPDEFS
AT_CLEANUP
+172 -118
View File
@@ -19,44 +19,13 @@
## Compile the grammar described in the documentation. ## ## Compile the grammar described in the documentation. ##
## ---------------------------------------------------- ## ## ---------------------------------------------------- ##
# -------------- #
# AT_CALC_MAIN. #
# -------------- #
# ------------------------- # m4_pushdef([AT_CALC_MAIN], [AT_LANG_DISPATCH([$0], $@)])
# Helping Autotest macros. #
# ------------------------- #
m4_define([AT_CALC_MAIN(c)],
# _AT_DATA_CALC_Y($1, $2, $3, [BISON-DIRECTIVES])
# -----------------------------------------------
# Produce 'calc.y' and, if %defines was specified, 'calc-lex.c' or
# 'calc-lex.cc'.
#
# Don't call this macro directly, because it contains some occurrences
# of '$1' etc. which will be interpreted by m4. So you should call it
# 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.
# Otherwise, generate three: calc.y with the parser, calc-lex.c with
# the scanner, and calc-main.c with "main()". This is in order to
# stress the use of the generated parser header. To avoid code
# duplication, AT_CALC_LEX and AT_CALC_MAIN contain the body of these
# two later files.
m4_define([_AT_DATA_CALC_Y],
[m4_if([$1$2$3], $[1]$[2]$[3], [],
[m4_fatal([$0: Invalid arguments: $@])])dnl
AT_D_IF([m4_pushdef([AT_CALC_MAIN],
[[int main (string[] args)
{
semantic_value result = 0;
int count = 0;
File input = args.length == 2 ? File (args[1], "r") : stdin;
auto l = calcLexer (input);
auto p = new YYParser (l);
return !p.parse ();
}
]])],
[m4_pushdef([AT_CALC_MAIN],
[[#include <assert.h> [[#include <assert.h>
#include <unistd.h> #include <unistd.h>
@@ -113,76 +82,33 @@ main (int argc, const char **argv)
assert (global_count == count); (void) count; assert (global_count == count); (void) count;
return status; return status;
} }
]])]) ]])
AT_D_IF([m4_pushdef([AT_CALC_LEX], m4_copy([AT_CALC_MAIN(c)], [AT_CALC_MAIN(c++)])
[[import std.range.primitives;
import std.stdio;
auto calcLexer(R)(R range) m4_define([AT_CALC_MAIN(d)],
if (isInputRange!R && is (ElementType!R : dchar)) [[int main (string[] args)
{ {
return new CalcLexer!R(range); semantic_value result = 0;
int count = 0;
File input = args.length == 2 ? File (args[1], "r") : stdin;
auto l = calcLexer (input);
auto p = new YYParser (l);
return !p.parse ();
} }
]])
auto calcLexer (File f)
{
import std.algorithm : map, joiner;
import std.utf : byDchar;
return f.byChunk(1024) // avoid making a syscall roundtrip per char
.map!(chunk => cast(char[]) chunk) // because byChunk returns ubyte[]
.joiner // combine chunks into a single virtual range of char
.calcLexer; // forward to other overload
}
class CalcLexer(R) : Lexer # --------------- #
if (isInputRange!R && is (ElementType!R : dchar)) # AT_CALC_YYLEX. #
{ # --------------- #
R input;
this(R r) { input = r; } m4_pushdef([AT_CALC_YYLEX], [AT_LANG_DISPATCH([$0], $@)])
public void yyerror (string s)
{
stderr.writeln (s);
}
YYSemanticType semanticVal_; m4_define([AT_CALC_YYLEX(c)],
public final @property YYSemanticType semanticVal()
{
return semanticVal_;
}
int yylex ()
{
import std.uni : isWhite, isNumber;
// Skip initial spaces
while (!input.empty && input.front != '\n' && isWhite (input.front))
input.popFront;
// Handle EOF.
if (input.empty)
return YYTokenType.EOF;
// Numbers.
if (input.front == '.' || input.front.isNumber)
{
import std.conv : parse;
semanticVal_.ival = input.parse!int;
return YYTokenType.NUM;
}
// Individual characters
auto c = input.front;
input.popFront;
return c;
}
}
]])],
[m4_pushdef([AT_CALC_LEX],
[[#include <ctype.h> [[#include <ctype.h>
]AT_YYLEX_DECLARE_EXTERN[ ]AT_YYLEX_DECLARE_EXTERN[
@@ -257,8 +183,8 @@ read_integer (]AT_YYLEX_FORMALS[)
} }
while ((c = get_char (]AT_YYLEX_ARGS[)) == ' ' || c == '\t'); while ((c = get_char (]AT_YYLEX_ARGS[)) == ' ' || c == '\t');
/* Process numbers */ /* Process numbers. */
if (c == '.' || isdigit (c)) if (isdigit (c))
{ {
unget_char (]AT_YYLEX_PRE_ARGS[ c); unget_char (]AT_YYLEX_PRE_ARGS[ c);
]AT_VAL[.ival = read_integer (]AT_YYLEX_ARGS[); ]AT_VAL[.ival = read_integer (]AT_YYLEX_ARGS[);
@@ -273,7 +199,136 @@ read_integer (]AT_YYLEX_FORMALS[)
return c; return c;
} }
]]) ]])
])
m4_copy([AT_CALC_YYLEX(c)], [AT_CALC_YYLEX(c++)])
m4_define([AT_CALC_YYLEX(d)],
[[import std.range.primitives;
import std.stdio;
auto calcLexer(R)(R range)
if (isInputRange!R && is (ElementType!R : dchar))
{
return new CalcLexer!R(range);
}
auto calcLexer (File f)
{
import std.algorithm : map, joiner;
import std.utf : byDchar;
return f.byChunk(1024) // avoid making a syscall roundtrip per char
.map!(chunk => cast(char[]) chunk) // because byChunk returns ubyte[]
.joiner // combine chunks into a single virtual range of char
.calcLexer; // forward to other overload
}
class CalcLexer(R) : Lexer
if (isInputRange!R && is (ElementType!R : dchar))
{
R input;
this(R r) {
input = r;
}
]AT_YYERROR_DEFINE[
YYSemanticType semanticVal_;]AT_LOCATION_IF([[
YYLocation location = new YYLocation;
public final @property YYPosition startPos()
{
return location.begin;
}
public final @property YYPosition endPos()
{
return location.end;
}
]])[
public final @property YYSemanticType semanticVal()
{
return semanticVal_;
}
int parseInt ()
{
auto res = 0;
import std.uni : isNumber;
while (input.front.isNumber)
{
res = res * 10 + (input.front - '0');]AT_LOCATION_IF([[
location.end.column += 1;]])[
input.popFront;
}
return res;
}
int yylex ()
{]AT_LOCATION_IF([[
location.begin = location.end;]])[
import std.uni : isWhite, isNumber;
// Skip initial spaces
while (!input.empty && input.front != '\n' && isWhite (input.front))
{
input.popFront;]AT_LOCATION_IF([[
location.begin.column += 1;
location.end.column += 1;]])[
}
// Handle EOF.
if (input.empty)
return YYTokenType.EOF;
// Numbers.
if (input.front.isNumber)
{
semanticVal_.ival = parseInt;
return YYTokenType.NUM;
}
// Individual characters
auto c = input.front;]AT_LOCATION_IF([[
if (c == '\n')
{
location.end.line += 1;
location.end.column = 1;
}
else
location.end.column += 1;]])[
input.popFront;
return c;
}
}
]])
# -------------- #
# AT_DATA_CALC. #
# -------------- #
# _AT_DATA_CALC_Y($1, $2, $3, [BISON-DIRECTIVES])
# -----------------------------------------------
# Produce 'calc.y' and, if %defines was specified, 'calc-lex.c' or
# 'calc-lex.cc'.
#
# Don't call this macro directly, because it contains some occurrences
# of '$1' etc. which will be interpreted by m4. So you should call it
# 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.
# Otherwise, generate three: calc.y with the parser, calc-lex.c with
# the scanner, and calc-main.c with "main()". This is in order to
# stress the use of the generated parser header. To avoid code
# duplication, AT_CALC_YYLEX and AT_CALC_MAIN contain the body of these
# two later files.
m4_define([_AT_DATA_CALC_Y],
[m4_if([$1$2$3], $[1]$[2]$[3], [],
[m4_fatal([$0: Invalid arguments: $@])])dnl
AT_DATA_GRAMMAR([calc.y], AT_DATA_GRAMMAR([calc.y],
[[/* Infix notation calculator--calc */ [[/* Infix notation calculator--calc */
@@ -281,8 +336,6 @@ AT_DATA_GRAMMAR([calc.y],
]AT_CXX_IF([%define global_tokens_and_yystype])[ ]AT_CXX_IF([%define global_tokens_and_yystype])[
]AT_D_IF([[ ]AT_D_IF([[
%code imports { %code imports {
import std.ascii;
import std.stdio;
alias semantic_value = int; alias semantic_value = int;
} }
]], [[ ]], [[
@@ -346,15 +399,15 @@ void location_print (FILE *o, Span s);
%code %code
{ {
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
#define USE(Var) #define USE(Var)
FILE *input; FILE *input;
static int power (int base, int exponent); static int power (int base, int exponent);
]AT_YYERROR_DECLARE[ ]AT_YYERROR_DECLARE[
]AT_YYLEX_DECLARE_EXTERN[ ]AT_YYLEX_DECLARE_EXTERN[
} }
]])[ ]])[
@@ -449,20 +502,18 @@ location_print (FILE *o, Span s)
]])])[ ]])])[
]AT_YYERROR_DEFINE[ ]AT_YYERROR_DEFINE[
]AT_DEFINES_IF([], ]AT_DEFINES_IF([],
[AT_CALC_LEX [AT_CALC_YYLEX
AT_CALC_MAIN])]) AT_CALC_MAIN])])
AT_DEFINES_IF([AT_DATA_SOURCE([[calc-lex.]AT_LANG_EXT], AT_DEFINES_IF([AT_DATA_SOURCE([[calc-lex.]AT_LANG_EXT],
[[#include "calc.]AT_LANG_HDR[" [[#include "calc.]AT_LANG_HDR["
]AT_CALC_LEX]) ]AT_CALC_YYLEX])
AT_DATA_SOURCE([[calc-main.]AT_LANG_EXT], AT_DATA_SOURCE([[calc-main.]AT_LANG_EXT],
[[#include "calc.]AT_LANG_HDR[" [[#include "calc.]AT_LANG_HDR["
]AT_CALC_MAIN]) ]AT_CALC_MAIN])
]) ])
m4_popdef([AT_CALC_MAIN])
m4_popdef([AT_CALC_LEX])
])# _AT_DATA_CALC_Y ])# _AT_DATA_CALC_Y
@@ -568,7 +619,7 @@ AT_CHECK([cat stderr], 0, [expout])
# Make sure we did not introduce bad spaces. Checked here because all # Make sure we did not introduce bad spaces. Checked here because all
# the skeletons are (or should be) exercized here. # the skeletons are (or should be) exercized here.
m4_define([AT_CHECK_SPACES], m4_define([AT_CHECK_SPACES],
[AT_CHECK([$PERL -ne ' [AT_PERL_CHECK([-ne '
chomp; chomp;
print "$ARGV:$.: {$_}\n" print "$ARGV:$.: {$_}\n"
if (# No starting/ending empty lines. if (# No starting/ending empty lines.
@@ -578,7 +629,7 @@ m4_define([AT_CHECK_SPACES],
# No tabs. # No tabs.
|| /\t/ || /\t/
)' $1 )' $1
])dnl ])
]) ])
@@ -598,7 +649,7 @@ AT_DATA_CALC_Y([$1])
AT_FULL_COMPILE([calc], AT_DEFINES_IF([[lex], [main]], [[], []]), [$2], [-Wno-deprecated]) AT_FULL_COMPILE([calc], AT_DEFINES_IF([[lex], [main]], [[], []]), [$2], [-Wno-deprecated])
AT_CHECK_SPACES([calc.AT_LANG_EXT AT_DEFINES_IF([calc.AT_LANG_HDR])]) AT_CHECK_SPACES([calc.AT_LANG_EXT AT_DEFINES_IF([calc.AT_LANG_HDR])])
# Test the priorities. # Test the precedences.
_AT_CHECK_CALC([$1], _AT_CHECK_CALC([$1],
[1 + 2 * 3 = 7 [1 + 2 * 3 = 7
1 + 2 * -3 = -5 1 + 2 * -3 = -5
@@ -856,14 +907,17 @@ m4_define([AT_CHECK_CALC_LALR1_D],
[AT_CHECK_CALC([%language "D" $1], [$2])]) [AT_CHECK_CALC([%language "D" $1], [$2])])
AT_CHECK_CALC_LALR1_D([]) AT_CHECK_CALC_LALR1_D([])
#AT_CHECK_CALC_LALR1_D([%locations]) AT_CHECK_CALC_LALR1_D([%locations])
#AT_CHECK_CALC_LALR1_D([%locations %define api.location.type {Span}]) #AT_CHECK_CALC_LALR1_D([%locations %define api.location.type {Span}])
AT_CHECK_CALC_LALR1_D([%define parse.error verbose %define api.prefix {calc} %verbose]) AT_CHECK_CALC_LALR1_D([%define parse.error verbose %define api.prefix {calc} %verbose])
#AT_CHECK_CALC_LALR1_D([%debug]) AT_CHECK_CALC_LALR1_D([%debug])
#AT_CHECK_CALC_LALR1_D([%define parse.error verbose %debug %verbose]) AT_CHECK_CALC_LALR1_D([%define parse.error verbose %debug %verbose])
#AT_CHECK_CALC_LALR1_D([%define parse.error verbose %debug %define api.token.prefix {TOK_} %verbose]) #AT_CHECK_CALC_LALR1_D([%define parse.error verbose %debug %define api.token.prefix {TOK_} %verbose])
#AT_CHECK_CALC_LALR1_D([%locations %define parse.error verbose %debug %verbose %parse-param {semantic_value *result} %parse-param {int *count}]) #AT_CHECK_CALC_LALR1_D([%locations %define parse.error verbose %debug %verbose %parse-param {semantic_value *result} %parse-param {int *count}])
#AT_CHECK_CALC_LALR1_D([%locations %define parse.error verbose %debug %define api.prefix {calc} %verbose %parse-param {semantic_value *result} %parse-param {int *count}]) #AT_CHECK_CALC_LALR1_D([%locations %define parse.error verbose %debug %define api.prefix {calc} %verbose %parse-param {semantic_value *result} %parse-param {int *count}])
m4_popdef([AT_CALC_MAIN])
m4_popdef([AT_CALC_YYLEX])
+15 -1
View File
@@ -541,7 +541,7 @@ AT_CONSISTENT_ERRORS_CHECK([[%define lr.type canonical-lr]],
[AT_PREVIOUS_STATE_INPUT], [AT_PREVIOUS_STATE_INPUT],
[[$end]], [[ab]]) [[$end]], [[ab]])
# Only LAC gets it right. # Only LAC gets it right. In C.
AT_CONSISTENT_ERRORS_CHECK([[%define lr.type canonical-lr AT_CONSISTENT_ERRORS_CHECK([[%define lr.type canonical-lr
%define parse.lac full]], %define parse.lac full]],
[AT_PREVIOUS_STATE_GRAMMAR], [AT_PREVIOUS_STATE_GRAMMAR],
@@ -553,6 +553,20 @@ AT_CONSISTENT_ERRORS_CHECK([[%define lr.type ielr
[AT_PREVIOUS_STATE_INPUT], [AT_PREVIOUS_STATE_INPUT],
[[$end]], [[b]]) [[$end]], [[b]])
# Only LAC gets it right. In C++.
AT_CONSISTENT_ERRORS_CHECK([[%language "c++"
%define lr.type canonical-lr
%define parse.lac full]],
[AT_PREVIOUS_STATE_GRAMMAR],
[AT_PREVIOUS_STATE_INPUT],
[[$end]], [[b]])
AT_CONSISTENT_ERRORS_CHECK([[%language "c++"
%define lr.type ielr
%define parse.lac full]],
[AT_PREVIOUS_STATE_GRAMMAR],
[AT_PREVIOUS_STATE_INPUT],
[[$end]], [[b]])
m4_popdef([AT_PREVIOUS_STATE_GRAMMAR]) m4_popdef([AT_PREVIOUS_STATE_GRAMMAR])
m4_popdef([AT_PREVIOUS_STATE_INPUT]) m4_popdef([AT_PREVIOUS_STATE_INPUT])
+198 -15
View File
@@ -18,7 +18,8 @@
AT_BANNER([[Diagnostics.]]) AT_BANNER([[Diagnostics.]])
# AT_TEST($1: TITLE, $2: GRAMMAR, $3: EXIT-STATUS, $4: OUTPUT-WITH-STYLE) # AT_TEST($1: TITLE, $2: GRAMMAR, $3: EXIT-STATUS, $4: OUTPUT-WITH-STYLE,
# $5: EXTRA_ENV
# ----------------------------------------------------------------------- # -----------------------------------------------------------------------
# Run Bison on GRAMMAR with debugging style enabled, and expect # Run Bison on GRAMMAR with debugging style enabled, and expect
# OUTPUT-WITH-STYLE as diagnostics. # OUTPUT-WITH-STYLE as diagnostics.
@@ -38,19 +39,21 @@ AT_DATA_GRAMMAR([[input.y]], [$2])
# For some reason, literal ^M in the input are removed and don't end # For some reason, literal ^M in the input are removed and don't end
# in `input.y`. So use the two-character ^M represent it, and let # in `input.y`. So use the two-character ^M represent it, and let
# Perl insert real CR characters. # Perl insert real CR characters.
AT_CHECK([perl -pi -e 's{\^M}{\r}gx' input.y]) if grep '\^M' input.y >/dev/null; then
AT_PERL_REQUIRE([-pi -e 's{\^M}{\r}gx' input.y])
fi
AT_DATA([experr], [$4]) AT_DATA([experr], [$4])
AT_CHECK([LC_ALL=en_US.UTF-8 bison -fcaret --color=debug -Wall input.y], [$3], [], [experr]) AT_CHECK([LC_ALL=en_US.UTF-8 $5 bison -fcaret --color=debug -Wall input.y], [$3], [], [experr])
# When no style, same messages, but without style. # When no style, same messages, but without style.
AT_CHECK([perl -pi -e 's{(</?\w+>)}{ $[]1 eq "<tag>" ? $[]1 : "" }ge' experr]) AT_PERL_REQUIRE([-pi -e 's{(</?(-|\w)+>)}{ $[]1 eq "<tag>" ? $[]1 : "" }ge' experr])
# Cannot use AT_BISON_CHECK easily as we need to change the # Cannot use AT_BISON_CHECK easily as we need to change the
# environment. # environment.
# FIXME: Enhance AT_BISON_CHECK. # FIXME: Enhance AT_BISON_CHECK.
AT_CHECK([LC_ALL=en_US.UTF-8 bison -fcaret -Wall input.y], [$3], [], [experr]) AT_CHECK([LC_ALL=en_US.UTF-8 $5 bison -fcaret -Wall input.y], [$3], [], [experr])
AT_BISON_OPTION_POPDEFS AT_BISON_OPTION_POPDEFS
@@ -73,31 +76,31 @@ exp: %empty;
[[input.y:9.12-14: <warning>warning:</warning> symbol FOO redeclared [<warning>-Wother</warning>] [[input.y:9.12-14: <warning>warning:</warning> symbol FOO redeclared [<warning>-Wother</warning>]
9 | %token FOO <warning>FOO</warning> FOO 9 | %token FOO <warning>FOO</warning> FOO
| <warning>^~~</warning> | <warning>^~~</warning>
input.y:9.8-10: previous declaration input.y:9.8-10: previous declaration
9 | %token <note>FOO</note> FOO FOO 9 | %token <note>FOO</note> FOO FOO
| <note>^~~</note> | <note>^~~</note>
input.y:9.16-18: <warning>warning:</warning> symbol FOO redeclared [<warning>-Wother</warning>] input.y:9.16-18: <warning>warning:</warning> symbol FOO redeclared [<warning>-Wother</warning>]
9 | %token FOO FOO <warning>FOO</warning> 9 | %token FOO FOO <warning>FOO</warning>
| <warning>^~~</warning> | <warning>^~~</warning>
input.y:9.8-10: previous declaration input.y:9.8-10: previous declaration
9 | %token <note>FOO</note> FOO FOO 9 | %token <note>FOO</note> FOO FOO
| <note>^~~</note> | <note>^~~</note>
input.y:10.8-10: <warning>warning:</warning> symbol FOO redeclared [<warning>-Wother</warning>] input.y:10.8-10: <warning>warning:</warning> symbol FOO redeclared [<warning>-Wother</warning>]
10 | %token <warning>FOO</warning> FOO FOO 10 | %token <warning>FOO</warning> FOO FOO
| <warning>^~~</warning> | <warning>^~~</warning>
input.y:9.8-10: previous declaration input.y:9.8-10: previous declaration
9 | %token <note>FOO</note> FOO FOO 9 | %token <note>FOO</note> FOO FOO
| <note>^~~</note> | <note>^~~</note>
input.y:10.13-15: <warning>warning:</warning> symbol FOO redeclared [<warning>-Wother</warning>] input.y:10.13-15: <warning>warning:</warning> symbol FOO redeclared [<warning>-Wother</warning>]
10 | %token FOO <warning>FOO</warning> FOO 10 | %token FOO <warning>FOO</warning> FOO
| <warning>^~~</warning> | <warning>^~~</warning>
input.y:9.8-10: previous declaration input.y:9.8-10: previous declaration
9 | %token <note>FOO</note> FOO FOO 9 | %token <note>FOO</note> FOO FOO
| <note>^~~</note> | <note>^~~</note>
input.y:10.18-20: <warning>warning:</warning> symbol FOO redeclared [<warning>-Wother</warning>] input.y:10.18-20: <warning>warning:</warning> symbol FOO redeclared [<warning>-Wother</warning>]
10 | %token FOO FOO <warning>FOO</warning> 10 | %token FOO FOO <warning>FOO</warning>
| <warning>^~~</warning> | <warning>^~~</warning>
input.y:9.8-10: previous declaration input.y:9.8-10: previous declaration
9 | %token <note>FOO</note> FOO FOO 9 | %token <note>FOO</note> FOO FOO
| <note>^~~</note> | <note>^~~</note>
]]) ]])
@@ -127,18 +130,23 @@ e:
[[input.y:11.4-5: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>] [[input.y:11.4-5: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
11 | a: <warning>{}</warning> 11 | a: <warning>{}</warning>
| <warning>^~</warning> | <warning>^~</warning>
| <fixit-insert>%empty</fixit-insert>
input.y:12.3-13.1: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>] input.y:12.3-13.1: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
12 | b:<warning>{</warning> 12 | b:<warning>{</warning>
| <warning>^</warning> | <warning>^</warning>
| <fixit-insert>%empty</fixit-insert>
input.y:14.3: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>] input.y:14.3: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
14 | c: 14 | c:
| <warning>^</warning> | <warning>^</warning>
| <fixit-insert>%empty</fixit-insert>
input.y:16.2: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>] input.y:16.2: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
16 | : 16 | :
| <warning>^</warning> | <warning>^</warning>
| <fixit-insert>%empty</fixit-insert>
input.y:17.3: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>] input.y:17.3: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
17 | e: 17 | e:
| <warning>^</warning> | <warning>^</warning>
| <fixit-insert>%empty</fixit-insert>
input.y: <warning>warning:</warning> fix-its can be applied. Rerun with option '--update'. [<warning>-Wother</warning>] input.y: <warning>warning:</warning> fix-its can be applied. Rerun with option '--update'. [<warning>-Wother</warning>]
]]) ]])
@@ -166,27 +174,35 @@ h: { 🐃 }
[[input.y:11.4-17: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>] [[input.y:11.4-17: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
11 | a: <warning>{ }</warning> 11 | a: <warning>{ }</warning>
| <warning>^~~~~~~~~~~~~~</warning> | <warning>^~~~~~~~~~~~~~</warning>
| <fixit-insert>%empty</fixit-insert>
input.y:12.4-17: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>] input.y:12.4-17: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
12 | b: <warning>{ }</warning> 12 | b: <warning>{ }</warning>
| <warning>^~~~~~~~~~~~~~</warning> | <warning>^~~~~~~~~~~~~~</warning>
| <fixit-insert>%empty</fixit-insert>
input.y:13.4-17: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>] input.y:13.4-17: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
13 | c: <warning>{------------}</warning> 13 | c: <warning>{------------}</warning>
| <warning>^~~~~~~~~~~~~~</warning> | <warning>^~~~~~~~~~~~~~</warning>
| <fixit-insert>%empty</fixit-insert>
input.y:14.4-17: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>] input.y:14.4-17: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
14 | d: <warning>{éééééééééééé}</warning> 14 | d: <warning>{éééééééééééé}</warning>
| <warning>^~~~~~~~~~~~~~</warning> | <warning>^~~~~~~~~~~~~~</warning>
| <fixit-insert>%empty</fixit-insert>
input.y:15.4-17: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>] input.y:15.4-17: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
15 | e: <warning>{∇⃗×𝐸⃗ = -∂𝐵⃗/∂t}</warning> 15 | e: <warning>{∇⃗×𝐸⃗ = -∂𝐵⃗/∂t}</warning>
| <warning>^~~~~~~~~~~~~~</warning> | <warning>^~~~~~~~~~~~~~</warning>
| <fixit-insert>%empty</fixit-insert>
input.y:16.4-17: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>] input.y:16.4-17: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
16 | f: <warning>{ 42 }</warning> 16 | f: <warning>{ 42 }</warning>
| <warning>^~~~~~~~~~~~~~</warning> | <warning>^~~~~~~~~~~~~~</warning>
| <fixit-insert>%empty</fixit-insert>
input.y:17.4-17: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>] input.y:17.4-17: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
17 | g: <warning>{ "฿¥$€₦" }</warning> 17 | g: <warning>{ "฿¥$€₦" }</warning>
| <warning>^~~~~~~~~~~~~~</warning> | <warning>^~~~~~~~~~~~~~</warning>
| <fixit-insert>%empty</fixit-insert>
input.y:18.4-17: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>] input.y:18.4-17: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
18 | h: <warning>{ 🐃 }</warning> 18 | h: <warning>{ 🐃 }</warning>
| <warning>^~~~~~~~~~~~~~</warning> | <warning>^~~~~~~~~~~~~~</warning>
| <fixit-insert>%empty</fixit-insert>
input.y: <warning>warning:</warning> fix-its can be applied. Rerun with option '--update'. [<warning>-Wother</warning>] input.y: <warning>warning:</warning> fix-its can be applied. Rerun with option '--update'. [<warning>-Wother</warning>]
]]) ]])
@@ -210,8 +226,10 @@ b: {}
[[input.y:11.4-5: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>] [[input.y:11.4-5: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
11 | a: <warning>{}</warning> 11 | a: <warning>{}</warning>
| <warning>^~</warning> | <warning>^~</warning>
| <fixit-insert>%empty</fixit-insert>
/dev/stdout:1.4-5: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>] /dev/stdout:1.4-5: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
/dev/stdout: <warning>warning:</warning> fix-its can be applied. Rerun with option '--update'. [<warning>-Wother</warning>] | <fixit-insert>%empty</fixit-insert>
input.y: <warning>warning:</warning> fix-its can be applied. Rerun with option '--update'. [<warning>-Wother</warning>]
]]) ]])
@@ -274,11 +292,174 @@ AT_TEST([[Carriage return]],
%% %%
]], ]],
[1], [1],
[[input.y:37.8-38.0: <error>error:</error> missing '"' at end of line [[input.y:10.8-11.0: <error>error:</error> missing '"' at end of line
input.y:37.8-38.0: <error>error:</error> syntax error, unexpected string, expecting char or identifier or <tag> 10 | %token <error>"</error>
| <error>^</error>
input.y:10.8-11.0: <error>error:</error> syntax error, unexpected string, expecting character literal or identifier or <tag>
10 | %token <error>"</error>
| <error>^</error>
]]) ]])
## ------- ##
## CR NL. ##
## ------- ##
# Check Windows EOLs.
AT_TEST([[CR NL]],
[[^M
%token ^M FOO^M
%token ^M FOO^M
%%^M
exp:^M
]],
[0],
[[input.y:11.9-11: <warning>warning:</warning> symbol FOO redeclared [<warning>-Wother</warning>]
11 | %token <warning>FOO</warning>
| <warning>^~~</warning>
input.y:10.9-11: previous declaration
10 | %token <note>FOO</note>
| <note>^~~</note>
input.y:13.5: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
13 | exp:
| <warning>^</warning>
| <fixit-insert>%empty</fixit-insert>
input.y: <warning>warning:</warning> fix-its can be applied. Rerun with option '--update'. [<warning>-Wother</warning>]
]])
## -------------- ##
## Screen width. ##
## -------------- ##
AT_TEST([[Screen width: 200 columns]],
[[%token ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ
%error-verbose
%%
exp: ABCDEFGHIJKLMNOPQRSTUVWXYZ
]],
[0],
[[input.y:9.36-61: <warning>warning:</warning> symbol ABCDEFGHIJKLMNOPQRSTUVWXYZ redeclared [<warning>-Wother</warning>]
9 | %token ABCDEFGHIJKLMNOPQRSTUVWXYZ <warning>ABCDEFGHIJKLMNOPQRSTUVWXYZ</warning> ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ
| <warning>^~~~~~~~~~~~~~~~~~~~~~~~~~</warning>
input.y:9.8-33: previous declaration
9 | %token <note>ABCDEFGHIJKLMNOPQRSTUVWXYZ</note> ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ
| <note>^~~~~~~~~~~~~~~~~~~~~~~~~~</note>
input.y:9.64-89: <warning>warning:</warning> symbol ABCDEFGHIJKLMNOPQRSTUVWXYZ redeclared [<warning>-Wother</warning>]
9 | %token ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ <warning>ABCDEFGHIJKLMNOPQRSTUVWXYZ</warning> ABCDEFGHIJKLMNOPQRSTUVWXYZ
| <warning>^~~~~~~~~~~~~~~~~~~~~~~~~~</warning>
input.y:9.8-33: previous declaration
9 | %token <note>ABCDEFGHIJKLMNOPQRSTUVWXYZ</note> ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ
| <note>^~~~~~~~~~~~~~~~~~~~~~~~~~</note>
input.y:9.92-117: <warning>warning:</warning> symbol ABCDEFGHIJKLMNOPQRSTUVWXYZ redeclared [<warning>-Wother</warning>]
9 | %token ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ <warning>ABCDEFGHIJKLMNOPQRSTUVWXYZ</warning>
| <warning>^~~~~~~~~~~~~~~~~~~~~~~~~~</warning>
input.y:9.8-33: previous declaration
9 | %token <note>ABCDEFGHIJKLMNOPQRSTUVWXYZ</note> ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ
| <note>^~~~~~~~~~~~~~~~~~~~~~~~~~</note>
input.y:10.56-69: <warning>warning:</warning> deprecated directive: '%error-verbose', use '%define parse.error verbose' [<warning>-Wdeprecated</warning>]
10 | <warning>%error-verbose</warning>
| <warning>^~~~~~~~~~~~~~</warning>
| <fixit-insert>%define parse.error verbose</fixit-insert>
input.y: <warning>warning:</warning> fix-its can be applied. Rerun with option '--update'. [<warning>-Wother</warning>]
]],
[[COLUMNS=200]])
AT_TEST([[Screen width: 80 columns]],
[[%token ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ
%error-verbose
%%
exp: ABCDEFGHIJKLMNOPQRSTUVWXYZ
]],
[0],
[[input.y:9.36-61: <warning>warning:</warning> symbol ABCDEFGHIJKLMNOPQRSTUVWXYZ redeclared [<warning>-Wother</warning>]
9 | %token ABCDEFGHIJKLMNOPQRSTUVWXYZ <warning>ABCDEFGHIJKLMNOPQRSTUVWXYZ</warning> ABCDEF...
| <warning>^~~~~~~~~~~~~~~~~~~~~~~~~~</warning>
input.y:9.8-33: previous declaration
9 | %token <note>ABCDEFGHIJKLMNOPQRSTUVWXYZ</note> ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEF...
| <note>^~~~~~~~~~~~~~~~~~~~~~~~~~</note>
input.y:9.64-89: <warning>warning:</warning> symbol ABCDEFGHIJKLMNOPQRSTUVWXYZ redeclared [<warning>-Wother</warning>]
9 | %token ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ <warning>ABCDEF</warning>...
| <warning>^~~~~~</warning>
input.y:9.8-33: previous declaration
9 | %token <note>ABCDEFGHIJKLMNOPQRSTUVWXYZ</note> ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEF...
| <note>^~~~~~~~~~~~~~~~~~~~~~~~~~</note>
input.y:9.92-117: <warning>warning:</warning> symbol ABCDEFGHIJKLMNOPQRSTUVWXYZ redeclared [<warning>-Wother</warning>]
9 | ...TUVWXYZ <warning>ABCDEFGHIJKLMNOPQRSTUVWXYZ</warning>
| <warning>^~~~~~~~~~~~~~~~~~~~~~~~~~</warning>
input.y:9.8-33: previous declaration
9 | %token <note>ABCDEFGHIJKLMNOPQRSTUVWXYZ</note> ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEF...
| <note>^~~~~~~~~~~~~~~~~~~~~~~~~~</note>
input.y:10.56-69: <warning>warning:</warning> deprecated directive: '%error-verbose', use '%define parse.error verbose' [<warning>-Wdeprecated</warning>]
10 | <warning>%error-verbose</warning>
| <warning>^~~~~~~~~~~~~~</warning>
| <fixit-insert>%define parse.error verbose</fixit-insert>
input.y: <warning>warning:</warning> fix-its can be applied. Rerun with option '--update'. [<warning>-Wother</warning>]
]],
[[COLUMNS=80]])
AT_TEST([[Screen width: 60 columns]],
[[%token ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ
%error-verbose
%%
exp: ABCDEFGHIJKLMNOPQRSTUVWXYZ
]],
[0],
[[input.y:9.36-61: <warning>warning:</warning> symbol ABCDEFGHIJKLMNOPQRSTUVWXYZ redeclared [<warning>-Wother</warning>]
9 | %token ABCDEFGHIJKLMNOPQRSTUVWXYZ <warning>ABCDEFGHIJKLMN</warning>...
| <warning>^~~~~~~~~~~~~~</warning>
input.y:9.8-33: previous declaration
9 | %token <note>ABCDEFGHIJKLMNOPQRSTUVWXYZ</note> ABCDEFGHIJKLMN...
| <note>^~~~~~~~~~~~~~~~~~~~~~~~~~</note>
input.y:9.64-89: <warning>warning:</warning> symbol ABCDEFGHIJKLMNOPQRSTUVWXYZ redeclared [<warning>-Wother</warning>]
9 | ...TUVWXYZ <warning>ABCDEFGHIJKLMNOPQRSTUVWXYZ</warning> ABCDEFGHI...
| <warning>^~~~~~~~~~~~~~~~~~~~~~~~~~</warning>
input.y:9.8-33: previous declaration
9 | %token <note>ABCDEFGHIJKLMNOPQRSTUVWXYZ</note> ABCDEFGHIJKLMN...
| <note>^~~~~~~~~~~~~~~~~~~~~~~~~~</note>
input.y:9.92-117: <warning>warning:</warning> symbol ABCDEFGHIJKLMNOPQRSTUVWXYZ redeclared [<warning>-Wother</warning>]
9 | ...TUVWXYZ <warning>ABCDEFGHIJKLMNOPQRSTUVWXYZ</warning>
| <warning>^~~~~~~~~~~~~~~~~~~~~~~~~~</warning>
input.y:9.8-33: previous declaration
9 | %token <note>ABCDEFGHIJKLMNOPQRSTUVWXYZ</note> ABCDEFGHIJKLMN...
| <note>^~~~~~~~~~~~~~~~~~~~~~~~~~</note>
input.y:10.56-69: <warning>warning:</warning> deprecated directive: '%error-verbose', use '%define parse.error verbose' [<warning>-Wdeprecated</warning>]
10 | ... <warning>%error-verbose</warning>
| <warning>^~~~~~~~~~~~~~</warning>
| <fixit-insert>%define parse.error verbose</fixit-insert>
input.y: <warning>warning:</warning> fix-its can be applied. Rerun with option '--update'. [<warning>-Wother</warning>]
]],
[[COLUMNS=60]])
## ------------- ##
## Suggestions. ##
## ------------- ##
# Don't suggest to fix QUX with QUUX and QUUX with QUX...
AT_TEST([[Suggestions]],
[[%%
res: QUX baz
bar: QUUX
]],
[1],
[[input.y:10.6-8: <error>error:</error> symbol 'QUX' is used, but is not defined as a token and has no rules
10 | res: <error>QUX</error> baz
| <error>^~~</error>
input.y:10.10-12: <error>error:</error> symbol 'baz' is used, but is not defined as a token and has no rules; did you mean 'bar'?
10 | res: QUX <error>baz</error>
| <error>^~~</error>
| <fixit-insert>bar</fixit-insert>
input.y:11.6-9: <error>error:</error> symbol 'QUUX' is used, but is not defined as a token and has no rules
11 | bar: <error>QUUX</error>
| <error>^~~~</error>
]])
m4_popdef([AT_TEST]) m4_popdef([AT_TEST])
@@ -302,12 +483,14 @@ exp : '0'
]]) ]])
AT_BISON_CHECK([[-fcaret -Wno-other input.y]], [0], [], AT_BISON_CHECK([[-fcaret -Wno-other input.y]], [0], [],
[[input.y:2.1-12: warning: deprecated directive, use '%define api.pure' [-Wdeprecated] [[input.y:2.1-12: warning: deprecated directive: '%pure-parser', use '%define api.pure' [-Wdeprecated]
2 | %pure-parser 2 | %pure-parser
| ^~~~~~~~~~~~ | ^~~~~~~~~~~~
input.y:3.1-14: warning: deprecated directive, use '%define parse.error verbose' [-Wdeprecated] | %define api.pure
input.y:3.1-14: warning: deprecated directive: '%error-verbose', use '%define parse.error verbose' [-Wdeprecated]
3 | %error-verbose 3 | %error-verbose
| ^~~~~~~~~~~~~~ | ^~~~~~~~~~~~~~
| %define parse.error verbose
]]) ]])
AT_CLEANUP AT_CLEANUP
+2 -2
View File
@@ -1711,10 +1711,10 @@ Reading a token: Now at end of input.
Stack 0 Entering state 7 Stack 0 Entering state 7
Now at end of input. Now at end of input.
Splitting off stack 1 from 0. Splitting off stack 1 from 0.
Reduced stack 1 by rule #2; action deferred. Now in state 2. Reduced stack 1 by rule 2 (line 24); action deferred. Now in state 2.
Stack 1 Entering state 2 Stack 1 Entering state 2
Now at end of input. Now at end of input.
Reduced stack 0 by rule #1; action deferred. Now in state 2. Reduced stack 0 by rule 1 (line 24); action deferred. Now in state 2.
Merging stack 0 into stack 1. Merging stack 0 into stack 1.
Stack 1 Entering state 2 Stack 1 Entering state 2
Now at end of input. Now at end of input.
+6 -4
View File
@@ -127,8 +127,9 @@ AT_DATA_GRAMMAR([input.y],
%define parse.error verbose %define parse.error verbose
]AT_VARIANT_IF([%token <int> 'x'], [%union {int integer;}])[ ]AT_VARIANT_IF([%token <int> 'x'], [%union {int integer;}])[
%code { %code {
#include <stdio.h> /* printf. */
]AT_PUSH_IF([[ ]AT_PUSH_IF([[
#if defined __GNUC__ && 7 == __GNUC__ #if defined __GNUC__ && (7 == __GNUC__ || 9 == __GNUC__)
# pragma GCC diagnostic ignored "-Wmaybe-uninitialized" # pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif #endif
]])[ ]])[
@@ -212,8 +213,9 @@ $2
int integer; int integer;
} }
%{ %{
#include <stdio.h> /* printf. */
]AT_PUSH_IF([[ ]AT_PUSH_IF([[
#if defined __GNUC__ && 7 == __GNUC__ #if defined __GNUC__ && (7 == __GNUC__ || 9 == __GNUC__)
# pragma GCC diagnostic ignored "-Wmaybe-uninitialized" # pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif #endif
]])[ ]])[
@@ -312,14 +314,14 @@ AT_TEST([x9], [%locations %code requires {#include "location.hh"} %define api.lo
# Ignore comments, YYChar (template parameter), YYPUSH_MORE(_DEFINED)? # Ignore comments, YYChar (template parameter), YYPUSH_MORE(_DEFINED)?
# (constant definition), YY_\w+_INCLUDED (header guards). # (constant definition), YY_\w+_INCLUDED (header guards).
# YYDEBUG (not renamed) can be read, but not changed. # YYDEBUG (not renamed) can be read, but not changed.
AT_CHECK([[$PERL -n -0777 -e ' AT_PERL_CHECK([[-n -0777 -e '
s{/\*.*?\*/}{}gs; s{/\*.*?\*/}{}gs;
s{//.*}{}g; s{//.*}{}g;
s{\b((defined|if)\ YYDEBUG s{\b((defined|if)\ YYDEBUG
|YYChar |YYChar
|YYPUSH_MORE(?:_DEFINED)? |YYPUSH_MORE(?:_DEFINED)?
|YYUSE |YYUSE
|YY_ATTRIBUTE(?:_PURE|_UNUSED)? |YY_ATTRIBUTE(?:_PURE|_UNUSED)
|YY_CONSTEXPR |YY_CONSTEXPR
|YY_COPY |YY_COPY
|YY_CPLUSPLUS |YY_CPLUSPLUS
+94 -50
View File
@@ -90,7 +90,7 @@ default: 'a' }
%- %-
%{ %{
]]) ]])
AT_CHECK([[$PERL -pi -e 's/\\(\d{3})/chr(oct($1))/ge' input.y || exit 77]]) AT_PERL_REQUIRE([[-pi -e 's/\\(\d{3})/chr(oct($1))/ge' input.y]])
AT_BISON_CHECK([input.y], [1], [], AT_BISON_CHECK([input.y], [1], [],
[[input.y:1.1-2: error: invalid characters: '\0\001\002\377?' [[input.y:1.1-2: error: invalid characters: '\0\001\002\377?'
@@ -232,10 +232,10 @@ input.y:3.17-24: error: nonterminals cannot be given a string alias
input.y:4.8-10: error: character literals cannot be nonterminals input.y:4.8-10: error: character literals cannot be nonterminals
4 | %nterm '+' '*'; 4 | %nterm '+' '*';
| ^~~ | ^~~
input.y:5.8-15: error: syntax error, unexpected string, expecting char or identifier or <tag> input.y:5.8-15: error: syntax error, unexpected string, expecting character literal or identifier or <tag>
5 | %nterm "number"; 5 | %nterm "number";
| ^~~~~~~~ | ^~~~~~~~
input.y:6.8-13: error: syntax error, unexpected string, expecting char or identifier or <tag> input.y:6.8-13: error: syntax error, unexpected string, expecting character literal or identifier or <tag>
6 | %token "tok1" 1; 6 | %token "tok1" 1;
| ^~~~~~ | ^~~~~~
input.y:7.14: error: syntax error, unexpected integer input.y:7.14: error: syntax error, unexpected integer
@@ -633,19 +633,19 @@ AT_BISON_CHECK([-fcaret input.y], [0], [],
[[input.y:1.12-14: warning: symbol FOO redeclared [-Wother] [[input.y:1.12-14: warning: symbol FOO redeclared [-Wother]
1 | %token FOO FOO 1 | %token FOO FOO
| ^~~ | ^~~
input.y:1.8-10: previous declaration input.y:1.8-10: previous declaration
1 | %token FOO FOO 1 | %token FOO FOO
| ^~~ | ^~~
input.y:2.15-17: warning: symbol BAR redeclared [-Wother] input.y:2.15-17: warning: symbol BAR redeclared [-Wother]
2 | %token BAR 12 BAR 12 2 | %token BAR 12 BAR 12
| ^~~ | ^~~
input.y:2.8-10: previous declaration input.y:2.8-10: previous declaration
2 | %token BAR 12 BAR 12 2 | %token BAR 12 BAR 12
| ^~~ | ^~~
input.y:3.14-16: warning: symbol EOF redeclared [-Wother] input.y:3.14-16: warning: symbol EOF redeclared [-Wother]
3 | %token EOF 0 EOF 0 3 | %token EOF 0 EOF 0
| ^~~ | ^~~
input.y:3.8-10: previous declaration input.y:3.8-10: previous declaration
3 | %token EOF 0 EOF 0 3 | %token EOF 0 EOF 0
| ^~~ | ^~~
]]) ]])
@@ -822,16 +822,16 @@ 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]
2 | %destructor {} bar
| ^~~
input.y:1.17-19: warning: symbol baz is used, but is not defined as a token and has no rules [-Wother]
1 | %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]
1 | %printer {} foo baz 1 | %printer {} foo baz
| ^~~ | ^~~
input.y:3.13-15: warning: symbol qux is used, but is not defined as a token and has no rules [-Wother] input.y:1.17-19: warning: symbol 'baz' is used, but is not defined as a token and has no rules [-Wother]
1 | %printer {} foo baz
| ^~~
input.y:2.16-18: error: symbol 'bar' is used, but is not defined as a token and has no rules
2 | %destructor {} bar
| ^~~
input.y:3.13-15: warning: symbol 'qux' is used, but is not defined as a token and has no rules [-Wother]
3 | %type <foo> qux 3 | %type <foo> qux
| ^~~ | ^~~
]]) ]])
@@ -1061,9 +1061,9 @@ AT_BISON_CHECK([-fcaret input.y], [1], [],
input.y:2.10-12: error: user token number 42 redeclaration for BAR input.y:2.10-12: error: user token number 42 redeclaration for BAR
2 | BAR 42 "foo" 2 | BAR 42 "foo"
| ^~~ | ^~~
input.y:1.8-10: previous declaration for FOO input.y:1.15-19: previous declaration for "foo"
1 | %token FOO 42 "foo" 1 | %token FOO 42 "foo"
| ^~~ | ^~~~~
]]) ]])
AT_CLEANUP AT_CLEANUP
@@ -1320,8 +1320,10 @@ yylex (void)
static char const input[] = "@<:@\1\2$@{@oline@__@&t@oline__\ static char const input[] = "@<:@\1\2$@{@oline@__@&t@oline__\
#output "; /* " #output "; /* "
*/ */
static size_t toknum; enum { input_elts = sizeof input };
assert (toknum < sizeof input); (void) input_elts;
static int toknum;
assert (0 <= toknum && toknum < input_elts);
yylval = value_as_yystype (input[toknum]); yylval = value_as_yystype (input[toknum]);
return input[toknum++]; return input[toknum++];
} }
@@ -1521,7 +1523,9 @@ start: TOO_LARGE_DEC TOO_LARGE_HEX
AT_BISON_CHECK([too-large.y], [1], [], AT_BISON_CHECK([too-large.y], [1], [],
[[too-large.y:9.22-42: error: integer out of range: '999999999999999999999' [[too-large.y:9.22-42: error: integer out of range: '999999999999999999999'
too-large.y:9.22-42: error: user token number of TOO_LARGE_DEC too large
too-large.y:10.24-44: error: integer out of range: '0xFFFFFFFFFFFFFFFFFFF' too-large.y:10.24-44: error: integer out of range: '0xFFFFFFFFFFFFFFFFFFF'
too-large.y:10.24-44: error: user token number of TOO_LARGE_HEX too large
]]) ]])
AT_BISON_OPTION_POPDEFS AT_BISON_OPTION_POPDEFS
@@ -1954,8 +1958,8 @@ AT_BISON_CHECK([[input.y]], [0], [],
[[input.y:5.1-40: warning: %define variable 'lr.type' requires keyword values [-Wdeprecated] [[input.y:5.1-40: warning: %define variable 'lr.type' requires keyword values [-Wdeprecated]
input.y:3.1-40: warning: %define variable 'lr.default-reduction' requires keyword values [-Wdeprecated] input.y:3.1-40: warning: %define variable 'lr.default-reduction' requires keyword values [-Wdeprecated]
input.y:4.1-40: warning: %define variable 'lr.keep-unreachable-state' requires keyword values [-Wdeprecated] input.y:4.1-40: warning: %define variable 'lr.keep-unreachable-state' requires keyword values [-Wdeprecated]
input.y:2.1-40: warning: %define variable 'api.push-pull' requires keyword values [-Wdeprecated]
input.y:1.1-38: warning: %define variable 'api.pure' requires keyword values [-Wdeprecated] input.y:1.1-38: warning: %define variable 'api.pure' requires keyword values [-Wdeprecated]
input.y:2.1-40: warning: %define variable 'api.push-pull' requires keyword values [-Wdeprecated]
]]) ]])
]) ])
@@ -2049,21 +2053,26 @@ AT_DATA([[input.y]],
start: %empty; start: %empty;
]]) ]])
AT_BISON_CHECK([[-fcaret input.y]], [1], [], AT_BISON_CHECK([[-fcaret input.y]], [1], [],
[[input.y:1.1-26: warning: deprecated directive, use '%define api.push-pull both' [-Wdeprecated] [[input.y:1.1-26: warning: deprecated directive: '%define api.push_pull both', use '%define api.push-pull both' [-Wdeprecated]
1 | %define api.push_pull both 1 | %define api.push_pull both
| ^~~~~~~~~~~~~~~~~~~~~~~~~~ | ^~~~~~~~~~~~~~~~~~~~~~~~~~
input.y:2.1-40: warning: deprecated directive, use '%define lr.keep-unreachable-state maybe' [-Wdeprecated] | %define api.push-pull both
input.y:2.1-40: warning: deprecated directive: '%define lr.keep_unreachable_states maybe', use '%define lr.keep-unreachable-state maybe' [-Wdeprecated]
2 | %define lr.keep_unreachable_states maybe 2 | %define lr.keep_unreachable_states maybe
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
input.y:3.1-23: warning: deprecated directive, use '%define api.namespace {foo}' [-Wdeprecated] | %define lr.keep-unreachable-state maybe
input.y:3.1-23: warning: deprecated directive: '%define namespace "foo"', use '%define api.namespace {foo}' [-Wdeprecated]
3 | %define namespace "foo" 3 | %define namespace "foo"
| ^~~~~~~~~~~~~~~~~~~~~~~ | ^~~~~~~~~~~~~~~~~~~~~~~
input.y:4.1-15: warning: deprecated directive, use '%define api.value.type variant' [-Wdeprecated] | %define api.namespace {foo}
input.y:4.1-15: warning: deprecated directive: '%define variant', use '%define api.value.type variant' [-Wdeprecated]
4 | %define variant 4 | %define variant
| ^~~~~~~~~~~~~~~ | ^~~~~~~~~~~~~~~
input.y:5.1-34: warning: deprecated directive, use '%define api.parser.class {parser}' [-Wdeprecated] | %define api.value.type variant
input.y:5.1-34: warning: deprecated directive: '%define parser_class_name {parser}', use '%define api.parser.class {parser}' [-Wdeprecated]
5 | %define parser_class_name {parser} 5 | %define parser_class_name {parser}
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| %define api.parser.class {parser}
input.y:2.1-40: error: invalid value for %define Boolean variable 'lr.keep-unreachable-state' input.y:2.1-40: error: invalid value for %define Boolean variable 'lr.keep-unreachable-state'
2 | %define lr.keep_unreachable_states maybe 2 | %define lr.keep_unreachable_states maybe
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -2166,18 +2175,13 @@ AT_CLEANUP
# Bison used to accept character literals that were empty or contained # Bison used to accept character literals that were empty or contained
# too many characters. # too many characters.
# FIXME: AT_DATA or some variant of AT_DATA may eventually permit
# the final newline to be omitted. See the threads starting at
# <http://lists.gnu.org/archive/html/bison-patches/2009-07/msg00019.html>.
AT_SETUP([[Bad character literals]]) AT_SETUP([[Bad character literals]])
AT_DATA([empty.y], AT_DATA_NO_FINAL_EOL([empty.y],
[[%% [[%%
start: ''; start: '';
start: ' start: '
]]) start: ']])
AT_CHECK([[$PERL -e "print 'start: \'';" >> empty.y || exit 77]])
AT_BISON_CHECK([-fcaret empty.y], [1], [], AT_BISON_CHECK([-fcaret empty.y], [1], [],
[[empty.y:2.8-9: warning: empty character literal [-Wother] [[empty.y:2.8-9: warning: empty character literal [-Wother]
@@ -2197,12 +2201,11 @@ empty.y:4.8: warning: empty character literal [-Wother]
| ^ | ^
]]) ]])
AT_DATA([two.y], AT_DATA_NO_FINAL_EOL([two.y],
[[%% [[%%
start: 'ab'; start: 'ab';
start: 'ab start: 'ab
]]) start: 'ab]])
AT_CHECK([[$PERL -e "print 'start: \'ab';" >> two.y || exit 77]])
AT_BISON_CHECK([two.y], [1], [], AT_BISON_CHECK([two.y], [1], [],
[[two.y:2.8-11: warning: extra characters in character literal [-Wother] [[two.y:2.8-11: warning: extra characters in character literal [-Wother]
@@ -2212,12 +2215,11 @@ two.y:4.8-10: error: missing "'" at end of file
two.y:4.8-10: warning: extra characters in character literal [-Wother] two.y:4.8-10: warning: extra characters in character literal [-Wother]
]]) ]])
AT_DATA([three.y], AT_DATA_NO_FINAL_EOL([three.y],
[[%% [[%%
start: 'abc'; start: 'abc';
start: 'abc start: 'abc
]]) start: 'abc]])
AT_CHECK([[$PERL -e "print 'start: \'abc';" >> three.y || exit 77]])
AT_BISON_CHECK([three.y], [1], [], AT_BISON_CHECK([three.y], [1], [],
[[three.y:2.8-12: warning: extra characters in character literal [-Wother] [[three.y:2.8-12: warning: extra characters in character literal [-Wother]
@@ -2247,8 +2249,7 @@ start: '\777' '\0' '\xfff' '\x0'
# Beside we cannot even expect "echo '\0'" to output two characters # Beside we cannot even expect "echo '\0'" to output two characters
# (well three with \n): at least Bash 3.2 converts the two-character # (well three with \n): at least Bash 3.2 converts the two-character
# sequence "\0" into a single NUL character. # sequence "\0" into a single NUL character.
AT_CHECK([[$PERL -e 'print "start: \"\\\t\\\f\\\0\\\1\" ;";' >> input.y \ AT_PERL_REQUIRE([[-e 'print "start: \"\\\t\\\f\\\0\\\1\" ;";' >> input.y]])
|| 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.9-12: error: invalid number after \-escape: 777
@@ -2285,6 +2286,7 @@ AT_CLEANUP
## ------------------------- ## ## ------------------------- ##
AT_SETUP([[LAC: Errors for %define]]) AT_SETUP([[LAC: Errors for %define]])
AT_KEYWORDS([lac])
AT_DATA([[input.y]], AT_DATA([[input.y]],
[[%% [[%%
@@ -2301,6 +2303,16 @@ AT_BISON_CHECK([[-Dparse.lac.memory-trace=full input.y]],
[[<command line>:3: error: %define variable 'parse.lac.memory-trace' is not used [[<command line>:3: error: %define variable 'parse.lac.memory-trace' is not used
]]) ]])
# parse.lac.* options are useless in C++ even if LAC isn't actually activated.
AT_BISON_CHECK([[-Dparse.lac.es-capacity-initial=1 -L C++ -Dparse.lac input.y]],
[[1]], [],
[[<command line>:3: error: %define variable 'parse.lac.es-capacity-initial' is not used
]])
AT_BISON_CHECK([[-Dparse.lac.memory-trace=full -L C++ -Dparse.lac input.y]],
[[1]], [],
[[<command line>:3: error: %define variable 'parse.lac.memory-trace' is not used
]])
AT_CLEANUP AT_CLEANUP
@@ -2576,14 +2588,12 @@ fix-it:"input.y":{13:1-13:15}:"%file-prefix"
input.y:14.1-16.5: warning: duplicate directive: '%file-prefix\n =' [-Wother] input.y:14.1-16.5: warning: duplicate directive: '%file-prefix\n =' [-Wother]
input.y:13.1-20: previous declaration input.y:13.1-20: previous declaration
fix-it:"input.y":{14:1-16:6}:"" fix-it:"input.y":{14:1-16:6}:""
input.y:17.9-27: warning: deprecated directive: '%fixed-output_files', use '%fixed-output-files' [-Wdeprecated] input.y:17.9-27: warning: deprecated directive: '%fixed-output_files', use '%output "y.tab.c"' [-Wdeprecated]
fix-it:"input.y":{17:2-17:21}:"%fixed-output-files" fix-it:"input.y":{17:2-17:21}:"%output \"y.tab.c\""
input.y:18.9-27: warning: duplicate directive: '%fixed_output-files' [-Wother] input.y:18.9-27: warning: deprecated directive: '%fixed_output-files', use '%output "y.tab.c"' [-Wdeprecated]
input.y:17.9-27: previous declaration fix-it:"input.y":{18:9-18:28}:"%output \"y.tab.c\""
fix-it:"input.y":{18:9-18:28}:"" input.y:19.1-19: warning: deprecated directive: '%fixed-output-files', use '%output "y.tab.c"' [-Wdeprecated]
input.y:19.1-19: warning: duplicate directive: '%fixed-output-files' [-Wother] fix-it:"input.y":{19:1-19:20}:"%output \"y.tab.c\""
input.y:17.9-27: previous declaration
fix-it:"input.y":{19:1-19:20}:""
input.y:20.1-19: warning: deprecated directive: '%name-prefix= "foo"', use '%define api.prefix {foo}' [-Wdeprecated] input.y:20.1-19: warning: deprecated directive: '%name-prefix= "foo"', use '%define api.prefix {foo}' [-Wdeprecated]
fix-it:"input.y":{20:1-20:20}:"%define api.prefix {foo}" fix-it:"input.y":{20:1-20:20}:"%define api.prefix {foo}"
input.y:21.1-16: warning: deprecated directive: '%no-default_prec', use '%no-default-prec' [-Wdeprecated] input.y:21.1-16: warning: deprecated directive: '%no-default_prec', use '%no-default-prec' [-Wdeprecated]
@@ -2634,8 +2644,9 @@ AT_CHECK([sed -e '1,8d' input.y], [],
%define parse.error verbose %define parse.error verbose
%expect-rr 0 %expect-rr 0
%file-prefix "foo" %file-prefix "foo"
%fixed-output-files %output "y.tab.c"
@&t@ %output "y.tab.c"
%output "y.tab.c"
%define api.prefix {foo} %define api.prefix {foo}
%no-default-prec %no-default-prec
%no-default-prec %no-default-prec
@@ -2712,7 +2723,6 @@ AT_DATA_GRAMMAR([[input.y]],
%file-prefix "foo" %file-prefix "foo"
%file-prefix %file-prefix
"bar" "bar"
%fixed-output-files
%no-default-prec %no-default-prec
%no-lines %no-lines
%output "foo" %output "foo"
@@ -2751,3 +2761,37 @@ AT_BISON_CHECK([[-fcaret input.y]], [[0]], [[]],
AT_BISON_OPTION_POPDEFS AT_BISON_OPTION_POPDEFS
AT_CLEANUP AT_CLEANUP
## -------------------------------------- ##
## Character literals and api.token.raw. ##
## -------------------------------------- ##
AT_SETUP([[Character literals and api.token.raw]])
AT_BISON_OPTION_PUSHDEFS
AT_DATA_GRAMMAR([[input.y]],
[[%define api.token.raw
%token 'a'
%%
exp: 'b' "c" {}
]])
AT_BISON_CHECK([[-fcaret input.y]], [[1]], [[]],
[[input.y:10.8-10: error: character literals cannot be used together with api.token.raw
10 | %token 'a'
| ^~~
input.y:9.1-21: definition of api.token.raw
9 | %define api.token.raw
| ^~~~~~~~~~~~~~~~~~~~~
input.y:12.6-8: error: character literals cannot be used together with api.token.raw
12 | exp: 'b' "c" {}
| ^~~
input.y:9.1-21: definition of api.token.raw
9 | %define api.token.raw
| ^~~~~~~~~~~~~~~~~~~~~
]])
AT_BISON_OPTION_POPDEFS
AT_CLEANUP
+14 -12
View File
@@ -60,7 +60,7 @@ AT_BISON_OPTION_PUSHDEFS([%language "Java" $4])
AT_DATA_GRAMMAR([Calc.y], AT_DATA_GRAMMAR([Calc.y],
[[/* Infix notation calculator--calc */ [[/* Infix notation calculator--calc */
%language "Java" %language "Java"
%name-prefix "Calc" %define api.prefix {Calc}
%define api.parser.class {Calc} %define api.parser.class {Calc}
%define public %define public
@@ -127,17 +127,17 @@ class CalcLexer implements Calc.Lexer {
]])[ ]])[
StreamTokenizer st; StreamTokenizer st;
public ]AT_LEXPARAM_IF([[YYLexer]], [[CalcLexer]]) (InputStream is) public ]AT_LEXPARAM_IF([[YYLexer]], [[CalcLexer]])[ (InputStream is)
{ {
st = new StreamTokenizer (new InputStreamReader (is)); st = new StreamTokenizer (new InputStreamReader (is));
st.resetSyntax (); st.resetSyntax ();
st.eolIsSignificant (true); st.eolIsSignificant (true);
st.whitespaceChars (9, 9); st.whitespaceChars ('\t', '\t');
st.whitespaceChars (32, 32); st.whitespaceChars (' ', ' ');
st.wordChars (48, 57); st.wordChars ('0', '9');
} }
AT_LOCATION_IF([[ ]AT_LOCATION_IF([[
Position yypos = new Position (1, 0); Position yypos = new Position (1, 0);
public Position getStartPos() { public Position getStartPos() {
@@ -157,15 +157,14 @@ AT_LOCATION_IF([[
} }
public int yylex () throws IOException { public int yylex () throws IOException {
int ttype = st.nextToken (); int ttype = st.nextToken ();]AT_LOCATION_IF([[
]AT_LOCATION_IF([[yypos = new Position (yypos.lineno (), yypos = new Position (yypos.lineno (), yypos.token () + 1);]])[
yypos.token () + 1);]])[
if (ttype == st.TT_EOF) if (ttype == st.TT_EOF)
return EOF; return EOF;
else if (ttype == st.TT_EOL) else if (ttype == st.TT_EOL)
{ {]AT_LOCATION_IF([[
]AT_LOCATION_IF([[yypos = new Position (yypos.lineno () + 1, 0);]])[ yypos = new Position (yypos.lineno () + 1, 0);]])[
return (int) '\n'; return (int) '\n';
} }
@@ -251,7 +250,7 @@ $2
AT_BISON_CHECK([-Wno-deprecated -o Calc.java Calc.y]) AT_BISON_CHECK([-Wno-deprecated -o Calc.java Calc.y])
AT_JAVA_COMPILE([Calc.java]) AT_JAVA_COMPILE([Calc.java])
# Test the priorities. # Test the precedences.
AT_DATA([[input]], AT_DATA([[input]],
[[1 + 2 * 3 = 7 [[1 + 2 * 3 = 7
1 + 2 * -3 = -5 1 + 2 * -3 = -5
@@ -445,6 +444,9 @@ 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.prefix {Prefix}]])
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.*]])

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