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
*.o
*.pdf
*.png
*.stamp
*.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
# an option on Travis).
stages:
- compile
- test
- dist
- 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.
git:
clone: false
@@ -29,7 +29,8 @@ git:
# (https://docs.travis-ci.com/user/conditional-builds-stages-jobs/).
jobs:
include:
- stage: "compile"
- stage: dist
name: "Make dist"
git:
clone: true
dist: bionic
@@ -49,23 +50,24 @@ jobs:
- git submodule update --init --recursive
- ./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; }
- make -j2
- make -j2 dist
# Can help understanding why we get "dirty" tarballs.
- git status
- dist=$(echo bison*.xz)
# 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
# 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.
#
# 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. ##
@@ -74,163 +76,167 @@ jobs:
# Start with three completely different environments, to get
# errors asap.
- name: "GCC 8 -O3"
stage: test
- name: "GCC 9 -O3"
stage: check
os: linux
dist: bionic
addons:
apt:
packages:
- g++-8
sources:
# See https://github.com/travis-ci/apt-source-safelist/issues/410.
- sourceline: 'ppa:ubuntu-toolchain-r/test'
packages: g++-9
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
# Travis if we run all the tests in one go. Run in two parts.
- name: "Clang 8 libc++ and ASAN part 1"
stage: test
- name: "Clang 9 libc++ and ASAN part 1"
stage: check
os: linux
dist: bionic
addons: &clang8
addons: &clang9
apt:
sources:
- llvm-toolchain-bionic-8
- ubuntu-toolchain-r-test
# See https://github.com/travis-ci/apt-source-safelist/issues/410.
- 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:
- clang-8
- libc++-8-dev
- libc++abi-8-dev
- clang-9
- libc++-9-dev
- libc++abi-9-dev
env:
# 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"
stage: test
- name: "Clang 9 libc++ and ASAN part 2"
stage: check
os: linux
dist: bionic
addons: *clang8
addons: *clang9
env:
# 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"
stage: test
# We need the build-aux/install-icc.sh script.
git:
clone: true
submodules: false
depth: 1
os: linux
dist: xenial
env:
# ICC's warnings are often very wrong (e.g., it thinks foo ?
# "bar" : "baz" is char* instead of const char*), so don't try
# to work around the, and obviously, don't die on them.
- MATRIX_EVAL="CC=icc && CXX=icpc"
- MAKE_ARGS='WERROR_CFLAGS= WERROR_CXXFLAGS='
# Currently no longer works (https://github.com/nemequ/icc-travis/issues/15).
# - name: "ICC"
# stage: check
# # We need the build-aux/install-icc.sh script.
# git:
# clone: true
# submodules: false
# depth: 1
# os: linux
# dist: xenial
# env:
# # ICC's warnings are often very wrong (e.g., it thinks foo ?
# # "bar" : "baz" is char* instead of const char*), so don't try
# # to work around the, and obviously, don't die on them.
# - MATRIX_EVAL="CC=icc && CXX=icpc"
# - MAKE_ARGS='WERROR_CFLAGS= WERROR_CXXFLAGS='
## ----- ##
## GCC. ##
## ----- ##
- name: "GCC 7 with sanitizers"
- name: "GCC 8 with sanitizers part 1"
os: linux
dist: bionic
addons:
apt:
packages:
- g++-7
packages: g++-8
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
- name: "GCC 7"
stage: test
- name: "GCC 8"
stage: check
os: linux
dist: bionic
addons:
apt:
packages:
- g++-7
packages: g++-8
env:
- MATRIX_EVAL="CC=gcc-8 && CXX=g++-8"
- name: "GCC 7"
stage: check
os: linux
dist: bionic
addons:
apt:
packages: g++-7
env:
- MATRIX_EVAL="CC=gcc-7 && CXX=g++-7"
- name: "GCC 6"
stage: test
stage: check
os: linux
dist: xenial
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-6
sources: ubuntu-toolchain-r-test
packages: g++-6
env:
- MATRIX_EVAL="CC=gcc-6 && CXX=g++-6"
- name: "GCC 5"
stage: test
stage: check
os: linux
dist: xenial
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-5
sources: ubuntu-toolchain-r-test
packages: g++-5
env:
- MATRIX_EVAL="CC=gcc-5 && CXX=g++-5"
- name: "GCC 4.9"
stage: test
stage: check
os: linux
dist: xenial
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-4.9
sources: ubuntu-toolchain-r-test
packages: g++-4.9
env:
- MATRIX_EVAL="CC=gcc-4.9 && CXX=g++-4.9"
- name: "GCC 4.8"
stage: test
stage: check
os: linux
dist: xenial
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-4.8
sources: ubuntu-toolchain-r-test
packages: g++-4.8
env:
- MATRIX_EVAL="CC=gcc-4.8 && CXX=g++-4.8"
- name: "GCC 4.7"
stage: test
stage: check
os: linux
dist: xenial
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-4.7
sources: ubuntu-toolchain-r-test
packages: g++-4.7
env:
- MATRIX_EVAL="CC=gcc-4.7 && CXX=g++-4.7"
- name: "GCC 4.6"
stage: test
stage: check
os: linux
dist: xenial
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-4.6
sources: ubuntu-toolchain-r-test
packages: g++-4.6
env:
- MATRIX_EVAL="CC=gcc-4.6 && CXX=g++-4.6"
@@ -238,25 +244,35 @@ jobs:
## Clang. ##
## ------- ##
- name: "Clang 7 -O3 and libc++"
stage: test
- name: "Clang 8 -O3"
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
dist: bionic
addons:
apt:
sources:
- llvm-toolchain-bionic-7
- ubuntu-toolchain-r-test
packages:
- clang-7
- libc++-7-dev
- libc++abi-7-dev
env:
- MATRIX_EVAL="CC=clang-7 && CXX='clang++-7 -stdlib=libc++'"
- CONFIGUREFLAGS='CPPFLAGS=-DNDEBUG CFLAGS=-O3 CXXFLAGS=-O3'
- name: "Clang 6 -O3 and libc++"
stage: test
- name: "Clang 6 and libc++"
stage: check
os: linux
dist: xenial
addons:
@@ -269,16 +285,14 @@ jobs:
- libc++-dev
env:
- MATRIX_EVAL="CC=clang-6.0 && CXX='clang++-6.0 -stdlib=libc++'"
- CONFIGUREFLAGS='CPPFLAGS=-DNDEBUG CFLAGS=-O3 CXXFLAGS=-O3'
- name: "Clang 5"
stage: test
stage: check
os: linux
dist: xenial
addons:
apt:
sources:
- llvm-toolchain-xenial-5.0
sources: llvm-toolchain-xenial-5.0
packages:
- clang-5.0
- libc++-dev
@@ -286,33 +300,29 @@ jobs:
- MATRIX_EVAL="CC='clang-5.0' CXX='clang++-5.0'"
- name: "Clang 4"
stage: test
stage: check
os: linux
dist: xenial
addons:
apt:
sources:
- llvm-toolchain-xenial-4.0
packages:
- clang-4.0
sources: llvm-toolchain-xenial-4.0
packages: clang-4.0
env:
- MATRIX_EVAL="CC=clang-4.0 && CXX=clang++-4.0"
- name: "Clang 3.9"
stage: test
stage: check
os: linux
dist: xenial
addons:
apt:
sources:
- llvm-toolchain-xenial-3.9
packages:
- clang-3.9
sources: llvm-toolchain-xenial-3.9
packages: clang-3.9
env:
- MATRIX_EVAL="CC=clang-3.9 && CXX=clang++-3.9"
- name: "Clang 3.8"
stage: test
stage: check
os: linux
dist: xenial
addons:
@@ -320,13 +330,12 @@ jobs:
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.8
packages:
- clang-3.8
packages: clang-3.8
env:
- MATRIX_EVAL="CC=clang-3.8 && CXX=clang++-3.8"
- name: "CLang 3.7"
stage: test
stage: check
os: linux
dist: xenial
addons:
@@ -334,13 +343,12 @@ jobs:
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.7
packages:
- clang-3.7
packages: clang-3.7
env:
- MATRIX_EVAL="CC=clang-3.7 && CXX=clang++-3.7"
- name: "Clang 3.6"
stage: test
stage: check
os: linux
dist: xenial
addons:
@@ -348,13 +356,12 @@ jobs:
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.6
packages:
- clang-3.6
packages: clang-3.6
env:
- MATRIX_EVAL="CC=clang-3.6 && CXX=clang++-3.6"
- name: "Clang 3.5"
stage: test
stage: check
os: linux
dist: xenial
addons:
@@ -362,34 +369,31 @@ jobs:
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.5
packages:
- clang-3.5
packages: clang-3.5
env:
- MATRIX_EVAL="CC=clang-3.5 && CXX=clang++-3.5"
- name: "Clang 3.4"
stage: test
stage: check
os: linux
# Not available on Xenial.
dist: trusty
addons:
apt:
packages:
- clang-3.4
packages: clang-3.4
env:
# No versioned name installed, but beware that Travis installs
# a more modern clang earlier in the default PATH.
- MATRIX_EVAL='CC=/usr/bin/clang && CXX=/usr/bin/clang++'
- name: "Clang 3.3"
stage: test
stage: check
os: linux
# Not available on Xenial.
dist: trusty
addons:
apt:
packages:
- clang-3.3
packages: clang-3.3
env:
# See comment for 3.4.
- 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
- 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:
- eval "$MATRIX_EVAL"
# Beware not too leak $SSH_PRIVATE_KEY.
+107 -3
View File
@@ -1,5 +1,109 @@
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]
** Bug fixes
@@ -900,10 +1004,10 @@ GNU Bison NEWS
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"
^^
/tmp/foo.yy:3.10-11: previous declaration
foo.yy:3.10-11: previous declaration
%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: XXLTYPE strictfp IDEs ffixit fdiagnostics parseable fixits
LocalWords: Wdeprecated yytext Variadic variadic yyrhs yyphrs RCS README
LocalWords: noexcept constexpr ispell american deprecations
LocalWords: noexcept constexpr ispell american deprecations backend
Local Variables:
ispell-dictionary: "american"
+17 -15
View File
@@ -1,25 +1,25 @@
This package contains the GNU Bison parser generator.
* Installation
** Build from git
# Installation
## Build from git
Here are basic installation instructions for a repository checkout:
$ git submodules update --init
$ git submodule update --init
$ ./bootstrap
then proceed with the usual 'configure && make' steps.
README-hacking contains more information about building and modifying the
software.
Be sure to read README-hacking, which contains all the needed information
about building, modifying and checking Bison.
** Build for tarball
## Build from tarball
See the file INSTALL for generic compilation and installation instructions.
Bison requires GNU m4 1.4.6 or later. See:
https://ftp.gnu.org/gnu/m4/m4-1.4.6.tar.gz
** Relocatability
## Relocatability
If you pass '--enable-relocatable' to 'configure', Bison is relocatable.
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.
** Internationalization
## Internationalization
Bison supports two catalogs: one for Bison itself (i.e., for the
maintainer-side parser generation), and one for the generated parsers (i.e.,
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
details.
* Questions
# Questions
See the section FAQ in the documentation (doc/bison.info) for frequently
asked questions. The documentation is also available in PDF and HTML,
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
answer them, please send mail to <[email protected]>.
* Bug reports
# Bug reports
Please send bug reports to <[email protected]>. Be sure to include the
version number from 'bison --version', and a complete, self-contained test
case in each bug report.
* Copyright statements
# Copyright statements
For any copyright year range specified as YYYY-ZZZZ in this package, note
that the range specifies every single year in that closed interval.
-----
<!--
Local Variables:
mode: outline
mode: markdown
fill-column: 76
ispell-dictionary: "american"
End:
@@ -83,5 +83,7 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
# LocalWords: parsers ngettext Texinfo pdf html YYYY ZZZZ ispell american
# LocalWords: MERCHANTABILITY
LocalWords: parsers ngettext Texinfo pdf html YYYY ZZZZ ispell american
LocalWords: MERCHANTABILITY
-->
+11 -4
View File
@@ -45,8 +45,8 @@ processes tabs in its input.
* Working from the repository
These notes intend to help people working on the checked-out sources.
These requirements do not apply when building from a distribution tarball.
These notes intend to help people working on the checked-out sources. These
requirements do not apply when building from a distribution tarball.
** 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.
** TESTSUITEFLAGS
To run just the testsuite (not the tests related to the examples), run `make
check-local`.
@@ -212,6 +211,10 @@ can be sped up in two ways:
Using -j, in a make-like fashion, for example:
$ 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
with AT_KEYWORDS([[category]]). Categories include:
- 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++'
Both can be combined.
$ make check-local TESTSUITEFLAGS='-j8 -k c++'
To rerun the tests that failed:
$ make recheck -j5
** Typical errors
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
cd /tmp/gnutest
./configure CC='gcc-mp-8 -fsanitize=undefined'
./configure -C CC='gcc-mp-8 -fsanitize=undefined' CFLAGS='-ggdb'
make check
* 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]
Alexandre Duret-Lutz [email protected]
Andre da Costa Barros [email protected]
Andreas Damm [email protected]
Andreas Schwab [email protected]
Andrew Suffield [email protected]
Angelo Borsotti [email protected]
@@ -94,8 +95,9 @@ Kees Zeelenberg [email protected]
Keith Browne [email protected]
Ken Moffat [email protected]
Kiyoshi Kanazawa [email protected]
Laurent Mascherpa [email protected]
Lars Maier [email protected]
László Várady [email protected]
Laurent Mascherpa [email protected]
Lie Yan [email protected]
Magnus Fromreide [email protected]
Marc Autret [email protected]
@@ -173,13 +175,16 @@ Sum Wu [email protected]
Théophile Ranquet [email protected]
Thiru Ramakrishnan [email protected]
Thomas Jahns [email protected]
Thomas Petazzoni [email protected]
Tim Josling [email protected]
Tim Landscheidt [email protected]
Tim Van Holder [email protected]
Tobias Frost [email protected]
Todd Freed [email protected]
Tom Kramer [email protected]
Tom Lane [email protected]
Tom Tromey [email protected]
Tomasz Kłoczko [email protected]
Tommy Nordgren [email protected]
Troy A. Johnson [email protected]
Tys Lefering [email protected]
@@ -198,6 +203,7 @@ Wolfgang Thaller [email protected]
Wolfram Wagner [email protected]
Wwp [email protected]
xolodho [email protected]
Yuichiro Kaneko [email protected]
Zack Weinberg [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
** doc
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
considered deprecated: %printer is superior.
** glr.cc
move glr.c into the yy namespace
** improve syntax errors (UTF-8, internationalization)
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
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
** Unit rules
** Unit rules / Injection rules (Akim Demaille)
Maybe we could expand unit rules (or "injections", see
https://homepages.cwi.nl/~daybuild/daily-books/syntax/2-sdf/sdf.html), i.e.,
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
have it?
** Injection rules
See above.
** clean up (Akim Demaille)
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
Introduce a goto struct, and use it in place of from_state/to_state.
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
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
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
* 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
token vs terminal
token vs terminal, variable vs non terminal.
** C++
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.
** C
Introduce state_type rather than spreading yytype_int16 everywhere?
** glr.c
yyspaceLeft should probably be a pointer diff.
Paul Eggert already covered most of this. But before publishing these
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
%require "3.5".
** Graphviz display code thoughts
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
of states from .output for the graphs, etc.
Also, the underscore in print_graph.[ch] isn't very fitting considering the
dashes in the other filenames.
Since graphviz dies on medium-to-big grammars, maybe consider an other tool?
** push-parser
@@ -233,11 +304,13 @@ since it is no longer bound to a particular parser, it's just a
(standalone symbol).
* 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
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.
Valentin Tolmer is working on this.
** YYERRCODE
Defined to 256, but not used, not documented. Probably the token
number for the error token, which POSIX wants to be 256, but which
@@ -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
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
The code bw glr.c and yacc.c is really alike, we can certainly factor
some parts.
This should be worked on when we also address the expected improvements for
error generation (e.g., i18n).
* Report
@@ -350,7 +434,26 @@ LORIA, INRIA Nancy - Grand Est, Nancy, France
* Extensions
** 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
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]>
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
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
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
There are couple of available extensions of Bison targeting some XML
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
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
Paul notes:
@@ -430,7 +546,7 @@ Paul notes:
tokens, either via escapes (e.g., "x\0y") or via a NUL byte in
the source code. This should get fixed.
* Broken options ?
* Broken options?
** %token-table
** Skeleton strategy
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
move to partial orders (sounds like series/parallel orders to me).
This is a prerequisite for modules.
* $undefined
From Hans:
+1 -1
View File
@@ -166,7 +166,7 @@ bootstrap_epilogue() { :; }
# specified directory. Fill in the first %s with the destination
# directory and the second with the domain name.
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/"
# 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
configmake
dirname
error extensions fdl fopen-safer
error extensions
fdl fopen-safer fstrcmp
getopt-gnu
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
ldexpl
libtextstyle-optional
malloc-gnu
mbswidth
mbfile mbswidth
non-recursive-gnulib-prefix-hack
obstack
obstack-printf
@@ -45,6 +46,8 @@ gnulib_modules='
unistd unistd-safer unlink unlocked-io
update-copyright unsetenv verify
warnings
winsz-ioctl
winsz-termios
xalloc
xalloc-die
xconcat-filename
@@ -87,6 +90,13 @@ bootstrap_epilogue()
touch src/parse-gram.[ch]
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
+12 -10
View File
@@ -12,7 +12,7 @@ while (<STDIN>)
{
if (/^\s* # Initial spaces.
(?:(-\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.
(?:=(\S+))? # $4: $arg: Possible argument name.
\s # Spaces.
@@ -32,7 +32,6 @@ while (<STDIN>)
# if $opt, $arg contains the closing ].
substr ($arg, -1) = ''
if $opt eq '[';
$arg =~ s/^=//;
$arg = lc ($arg);
my $dir_arg = $arg;
# If the argument is complete (e.g., for --define[=NAME[=VALUE]]),
@@ -72,12 +71,15 @@ while (<STDIN>)
my $sep = '';
foreach my $long (sort keys %option)
{
# Avoid trailing spaces.
print $sep;
$sep = "\n";
print '@item @option{', $long, "}\n\@tab";
print ' @option{', $option{$long}, '}' if $option{$long};
print "\n\@tab";
print ' @code{', $directive{$long}, '}' if $directive{$long};
print "\n";
# Couldn't find a means to escape @ in the format (for @item, @tab), so
# pass it as a literal to print.
format STDOUT =
@item @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @tab @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @tab @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
{
'@', '@option{' . $long . '}',
'@', $option{$long} ? ('@option{' . $option{$long} . '}') : '',
'@', $directive{$long} ? ('@code{' . $directive{$long} . '}') : ''
}
.
write;
}
+13 -12
View File
@@ -1,7 +1,7 @@
#! /usr/bin/env python
# usage:
# update-test _build/8d/tests/testsuite.dir/*.testsuite.log
# update-test _build/8d/tests/testsuite.dir/*/testsuite.log
import argparse
import os
@@ -11,8 +11,8 @@ import re
def getargs():
p = argparse.ArgumentParser(description='Update test cases.')
opt = p.add_argument
opt('tests', metavar='test', nargs='+', type=str, default=None,
help='test files to update')
opt('logs', metavar='log', nargs='+', type=str, default=None,
help='log files to process')
opt('-v', '--verbose', action='store_true',
help='Be verbose')
return p.parse_args()
@@ -21,14 +21,14 @@ args = getargs()
subst = dict()
def log(*args_):
def trace(*args_):
if args.verbose:
print(*args_)
def contents(file):
'''The contents of a file.'''
log(file)
trace(file)
f = open(file)
return f.read()
@@ -60,9 +60,9 @@ def diff_to_re(match):
def update(at_file, logfile):
test = contents(at_file)
if os.path.isfile(logfile):
log("LOG: ", logfile)
trace("LOG: ", logfile)
l = contents(logfile)
log("LOG: ", l)
trace("LOG: ", l)
global subst
subst = {}
re.sub(r'(?:^@@.*\n)((?:^[-+ ].*\n)+)',
@@ -71,7 +71,7 @@ def update(at_file, logfile):
if subst:
# Turn "subst{frm} -> to" into a large RE.
frm = '|'.join([re.escape(x) for x in subst])
log("FROM:", frm)
trace("FROM:", frm)
test = re.sub("(" + frm + ")",
lambda m: subst[m.group(1)],
test, flags=re.MULTILINE)
@@ -81,13 +81,14 @@ def update(at_file, logfile):
def process(logfile):
log = contents(logfile)
# 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:
trace("no diff found:", logfile)
return
at_file = 'tests/' + m.group(1)
print(at_file)
update(at_file, logfile)
for t in args.tests:
log("FILE:", t)
process(t)
for logfile in args.logs:
trace("FILE:", logfile)
process(logfile)
+3
View File
@@ -26,6 +26,9 @@ regen: _version
manual_title = The Yacc-compatible Parser Generator
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
# 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*
+12 -8
View File
@@ -36,6 +36,9 @@ AC_CONFIG_MACRO_DIR([m4])
# 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
# 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
@@ -94,9 +97,13 @@ AC_ARG_ENABLE([gcc-warnings],
[enable_gcc_warnings=no])
AM_CONDITIONAL([ENABLE_GCC_WARNINGS], [test "$enable_gcc_warnings" = yes])
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
-Wformat -Wimplicit-fallthrough -Wnull-dereference
-Wno-sign-compare -Wno-tautological-constant-out-of-range-compare
-Wpointer-arith -Wshadow
-Wwrite-strings'
warn_c='-Wbad-function-cast -Wstrict-prototypes'
@@ -112,6 +119,7 @@ if test "$enable_gcc_warnings" = yes; then
# details for lalr1.cc.
warn_tests='-Wundef -pedantic -Wconversion
-Wdeprecated -Wsign-compare -Wsign-conversion
-Wtautological-constant-out-of-range-compare
-fno-color-diagnostics
-Wno-keyword-macro'
@@ -192,7 +200,7 @@ BISON_CXX_COMPILER_POSIXLY_CORRECT
# D.
AC_CHECK_PROGS([DC], [dmd])
AC_CHECK_PROGS([DCFLAGS], [])
AC_CHECK_PROGS([DCFLAGS], [-g])
AM_CONDITIONAL([ENABLE_D], [test x"$DC" != x])
# Java.
@@ -211,10 +219,10 @@ AC_CONFIG_FILES([src/yacc], [chmod +x src/yacc])
# Checks for programs.
AM_MISSING_PROG([DOT], [dot])
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])
LEX=:
}
fi
AM_CONDITIONAL([FLEX_WORKS], [$LEX_IS_FLEX])
AM_CONDITIONAL([FLEX_CXX_WORKS],
[$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
supports -g, otherwise to "".])
AC_PATH_PROG([PERL], [perl])
if test -z "$PERL"; then
AC_MSG_ERROR([perl not found])
fi
AM_MISSING_PROG([HELP2MAN], [help2man])
AC_PATH_PROG([XSLTPROC], [xsltproc])
AC_SUBST([XSLTPROC])
@@ -244,7 +249,6 @@ gl_INIT
# Checks for library functions.
AC_CHECK_FUNCS_ONCE([setlocale])
AM_WITH_DMALLOC
# Gettext.
# 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
future. */
/* Diagnostics. */
.warning { color: purple; }
.error { color: red; }
.note { color: cyan; }
.fixit-insert { color: green; }
/* Semantic values in Bison's own parser traces. */
.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
_b4_symbol_case([$1])[]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
break;
@@ -535,7 +535,7 @@ m4_define([b4_token_format],
[b4_token_visible_if([$2],
[m4_quote(m4_format([$1],
[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_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([locations]) # Whether locations are tracked.
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],
[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.
static
const token_number_type
@@ -540,15 +542,15 @@ m4_define([b4_yytranslate_define],
{
]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[;
if (static_cast<int> (t) <= 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];
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)
# ---------------------
# Return the smallest int type able to handle numbers ranging from
# MIN to MAX (included).
# Return a narrow int type able to handle integers ranging from MIN
# to MAX (included) in portable C code. Assume MIN and MAX fall in
# 'int' range.
m4_define([b4_int_type],
[m4_if(b4_ints_in($@, [0], [255]), [1], [unsigned char],
b4_ints_in($@, [-128], [127]), [1], [signed char],
[m4_if(b4_ints_in($@, [-127], [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($@, [-32768], [32767]), [1], [short],
m4_eval([0 <= $1]), [1], [unsigned],
[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)
# ---------------------
# 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).
m4_define([b4_int_type_for],
[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
# 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_if(m4_eval($3 < m4_indir([b4_]$1[_min])
|| m4_indir([b4_]$1[_max]) < $3), [1],
[[0]],
[(!!(($2) == ($3)))])])
[(($2) == $4)])])
## ----------------- ##
@@ -210,22 +282,20 @@ m4_define([b4_table_value_equals],
# Provide portable compiler "attributes". If "noreturn" is passed, define
# _Noreturn.
m4_define([b4_attribute_define],
[[#ifndef YY_ATTRIBUTE
# if (defined __GNUC__ \
&& (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \
|| defined __SUNPRO_C && 0x5110 <= __SUNPRO_C
# define YY_ATTRIBUTE(Spec) __attribute__(Spec)
[[#ifndef YY_ATTRIBUTE_PURE
# if defined __GNUC__ && 2 < __GNUC__ + (96 <= __GNUC_MINOR__)
# define YY_ATTRIBUTE_PURE __attribute__ ((__pure__))
# else
# define YY_ATTRIBUTE(Spec) /* empty */
# define YY_ATTRIBUTE_PURE
# endif
#endif
#ifndef YY_ATTRIBUTE_PURE
# define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__))
#endif
#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
]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_sync_start(LINE, FILE)
# -------------------------
m4_define([b4_sync_start], [[#]line $1 $2])
# b4_list2(LIST1, LIST2)
# ----------------------
# 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_locations_if(TRUE, FALSE)
# ----------------------------
m4_define([b4_locations_if],
[m4_if(b4_locations_flag, 1, [$1], [$2])])
# 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_percent_code_get[]dnl
[#include <stdio.h>
[#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
]b4_c99_int_type_define[
#ifndef YY_
# if defined YYENABLE_NLS && YYENABLE_NLS
# if ENABLE_NLS
@@ -285,7 +289,7 @@ static YYLTYPE yyloc_default][]b4_yyloc_default;])[
# define YYREALLOC realloc
#endif
#define YYSIZEMAX ((size_t) -1)
#define YYSIZEMAX (PTRDIFF_MAX < SIZE_MAX ? PTRDIFF_MAX : (ptrdiff_t) SIZE_MAX)
#ifdef __cplusplus
typedef bool yybool;
@@ -293,7 +297,7 @@ static YYLTYPE yyloc_default][]b4_yyloc_default;])[
# define yyfalse false
#else
/* 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 yyfalse 0
#endif
@@ -346,15 +350,17 @@ static YYLTYPE yyloc_default][]b4_yyloc_default;])[
/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM
as returned by yylex, with out-of-bounds checking. */
#define YYTRANSLATE(YYX) \
((unsigned) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
]b4_api_token_raw_if(dnl
[[#define YYTRANSLATE(YYX) (YYX)]],
[[#define YYTRANSLATE(YYX) \
(0 <= (YYX) && (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
as returned by yylex. */
static const ]b4_int_type_for([b4_translate])[ yytranslate[] =
{
]b4_translate[
};
};]])[
#if ]b4_api_PREFIX[DEBUG
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
@@ -373,8 +379,8 @@ static const char *const yytname[] =
};
#endif
#define YYPACT_NINF ]b4_pact_ninf[
#define YYTABLE_NINF ]b4_table_ninf[
#define YYPACT_NINF (]b4_pact_ninf[)
#define YYTABLE_NINF (]b4_table_ninf[)
]b4_parser_tables_define[
@@ -488,7 +494,7 @@ typedef enum { yyok, yyaccept, yyabort, yyerr } YYRESULTTAG;
int yydebug;
struct yyGLRStack;
static void yypstack (struct yyGLRStack* yystackp, size_t yyk)
static void yypstack (struct yyGLRStack* yystackp, ptrdiff_t yyk)
YY_ATTRIBUTE_UNUSED;
static void yypdumpstack (struct yyGLRStack* yystackp)
YY_ATTRIBUTE_UNUSED;
@@ -572,12 +578,12 @@ yystpcpy (char *yydest, const char *yysrc)
backslash-backslash). YYSTR is taken from yytname. If YYRES is
null, do not copy; instead, return the length of what the result
would have been. */
static size_t
static ptrdiff_t
yytnamerr (char *yyres, const char *yystr)
{
if (*yystr == '"')
{
size_t yyn = 0;
ptrdiff_t yyn = 0;
char const *yyp = yystr;
for (;;)
@@ -608,25 +614,25 @@ yytnamerr (char *yyres, const char *yystr)
do_not_strip_quotes: ;
}
if (! yyres)
return strlen (yystr);
return (size_t) (yystpcpy (yyres, yystr) - yyres);
if (yyres)
return yystpcpy (yyres, yystr) - yyres;
else
return (ptrdiff_t) strlen (yystr);
}
# endif
#endif /* !YYERROR_VERBOSE */
/** State numbers, as in LALR(1) machine */
/** State numbers. */
typedef int yyStateNum;
/** Rule numbers, as in LALR(1) machine */
/** Rule numbers. */
typedef int yyRuleNum;
/** Grammar symbol */
/** Grammar symbol. */
typedef int yySymbol;
/** Item references, as in LALR(1) machine */
/** Item references. */
typedef short yyItemNum;
typedef struct yyGLRState yyGLRState;
@@ -646,7 +652,7 @@ struct yyGLRState {
/** Preceding state in this stack */
yyGLRState* yypred;
/** Source position of the last token produced by my symbol */
size_t yyposn;
ptrdiff_t yyposn;
union {
/** First in a chain of alternative reductions producing the
* nonterminal corresponding to this state, threaded through
@@ -666,7 +672,8 @@ struct yyGLRStateSet {
* operation, yylookaheadNeeds[0] is not maintained since it would merely
* duplicate yychar != YYEMPTY. */
yybool* yylookaheadNeeds;
size_t yysize, yycapacity;
ptrdiff_t yysize;
ptrdiff_t yycapacity;
};
struct yySemanticOption {
@@ -706,7 +713,7 @@ struct yyGLRStack {
YYJMP_BUF yyexception_buffer;
yyGLRStackItem* yyitems;
yyGLRStackItem* yynextFree;
size_t yyspaceLeft;
ptrdiff_t yyspaceLeft;
yyGLRState* yysplitPoint;
yyGLRState* yylastDeleted;
yyGLRStateSet yytops;
@@ -965,8 +972,8 @@ yylhsNonterm (yyRuleNum yyrule)
return yyr1[yyrule];
}
#define yypact_value_is_default(Yystate) \
]b4_table_value_equals([[pact]], [[Yystate]], [b4_pact_ninf])[
#define yypact_value_is_default(Yyn) \
]b4_table_value_equals([[pact]], [[Yyn]], [b4_pact_ninf], [YYPACT_NINF])[
/** True iff LR state YYSTATE has only a default reduction (regardless
* of token). */
@@ -983,8 +990,8 @@ yydefaultAction (yyStateNum yystate)
return yydefact[yystate];
}
#define yytable_value_is_error(Yytable_value) \
]b4_table_value_equals([[table]], [[Yytable_value]], [b4_table_ninf])[
#define yytable_value_is_error(Yyn) \
]b4_table_value_equals([[table]], [[Yyn]], [b4_table_ninf], [YYTABLE_NINF])[
/** The action to take in YYSTATE on seeing YYTOKEN.
* Result R means
@@ -1064,7 +1071,7 @@ yynewGLRStackItem (yyGLRStack* yystackp, yybool yyisState)
* alternative actions for YYSTATE. Assumes that YYRHS comes from
* stack #YYK of *YYSTACKP. */
static void
yyaddDeferredAction (yyGLRStack* yystackp, size_t yyk, yyGLRState* yystate,
yyaddDeferredAction (yyGLRStack* yystackp, ptrdiff_t yyk, yyGLRState* yystate,
yyGLRState* yyrhs, yyRuleNum yyrule)
{
yySemanticOption* yynewOption =
@@ -1095,19 +1102,21 @@ yyinitStateSet (yyGLRStateSet* yyset)
yyset->yysize = 1;
yyset->yycapacity = 16;
yyset->yystates
= (yyGLRState**) YYMALLOC (yyset->yycapacity * sizeof yyset->yystates[0]);
= (yyGLRState**) YYMALLOC ((size_t) yyset->yycapacity
* sizeof yyset->yystates[0]);
if (! yyset->yystates)
return yyfalse;
yyset->yystates[0] = YY_NULLPTR;
yyset->yylookaheadNeeds
= (yybool*) YYMALLOC (yyset->yycapacity * sizeof yyset->yylookaheadNeeds[0]);
= (yybool*) YYMALLOC ((size_t) yyset->yycapacity
* sizeof yyset->yylookaheadNeeds[0]);
if (! yyset->yylookaheadNeeds)
{
YYFREE (yyset->yystates);
return yyfalse;
}
memset (yyset->yylookaheadNeeds,
0, yyset->yycapacity * sizeof yyset->yylookaheadNeeds[0]);
0, (size_t) yyset->yycapacity * sizeof yyset->yylookaheadNeeds[0]);
return yytrue;
}
@@ -1120,13 +1129,14 @@ static void yyfreeStateSet (yyGLRStateSet* yyset)
/** Initialize *YYSTACKP to a single empty stack, with total maximum
* capacity for all stacks of YYSIZE. */
static yybool
yyinitGLRStack (yyGLRStack* yystackp, size_t yysize)
yyinitGLRStack (yyGLRStack* yystackp, ptrdiff_t yysize)
{
yystackp->yyerrState = 0;
yynerrs = 0;
yystackp->yyspaceLeft = yysize;
yystackp->yyitems =
(yyGLRStackItem*) YYMALLOC (yysize * sizeof yystackp->yynextFree[0]);
(yyGLRStackItem*) YYMALLOC ((size_t) yysize
* sizeof yystackp->yynextFree[0]);
if (!yystackp->yyitems)
return yyfalse;
yystackp->yynextFree = yystackp->yyitems;
@@ -1150,15 +1160,16 @@ yyexpandGLRStack (yyGLRStack* yystackp)
{
yyGLRStackItem* yynewItems;
yyGLRStackItem* yyp0, *yyp1;
size_t yynewSize;
size_t yyn;
size_t yysize = (size_t) (yystackp->yynextFree - yystackp->yyitems);
ptrdiff_t yynewSize;
ptrdiff_t yyn;
ptrdiff_t yysize = yystackp->yynextFree - yystackp->yyitems;
if (YYMAXDEPTH - YYHEADROOM < yysize)
yyMemoryExhausted (yystackp);
yynewSize = 2*yysize;
if (YYMAXDEPTH < yynewSize)
yynewSize = YYMAXDEPTH;
yynewItems = (yyGLRStackItem*) YYMALLOC (yynewSize * sizeof yynewItems[0]);
yynewItems = (yyGLRStackItem*) YYMALLOC ((size_t) yynewSize
* sizeof yynewItems[0]);
if (! yynewItems)
yyMemoryExhausted (yystackp);
for (yyp0 = yystackp->yyitems, yyp1 = yynewItems, yyn = yysize;
@@ -1222,7 +1233,7 @@ yyupdateSplit (yyGLRStack* yystackp, yyGLRState* yys)
/** Invalidate stack #YYK in *YYSTACKP. */
static inline void
yymarkStackDeleted (yyGLRStack* yystackp, size_t yyk)
yymarkStackDeleted (yyGLRStack* yystackp, ptrdiff_t yyk)
{
if (yystackp->yytops.yystates[yyk] != YY_NULLPTR)
yystackp->yylastDeleted = yystackp->yytops.yystates[yyk];
@@ -1246,7 +1257,7 @@ yyundeleteLastStack (yyGLRStack* yystackp)
static inline void
yyremoveDeletes (yyGLRStack* yystackp)
{
size_t yyi, yyj;
ptrdiff_t yyi, yyj;
yyi = yyj = 0;
while (yyj < yystackp->yytops.yysize)
{
@@ -1270,8 +1281,8 @@ yyremoveDeletes (yyGLRStack* yystackp)
yystackp->yytops.yylookaheadNeeds[yyi];
if (yyj != yyi)
{
YYDPRINTF ((stderr, "Rename stack %lu -> %lu.\n",
(unsigned long) yyi, (unsigned long) yyj));
YYDPRINTF ((stderr, "Rename stack %ld -> %ld.\n",
(long) yyi, (long) yyj));
}
yyj += 1;
}
@@ -1283,8 +1294,8 @@ yyremoveDeletes (yyGLRStack* yystackp)
* state YYLRSTATE, at input position YYPOSN, with (resolved) semantic
* value *YYVALP and source location *YYLOCP. */
static inline void
yyglrShift (yyGLRStack* yystackp, size_t yyk, yyStateNum yylrState,
size_t yyposn,
yyglrShift (yyGLRStack* yystackp, ptrdiff_t yyk, yyStateNum yylrState,
ptrdiff_t yyposn,
YYSTYPE* yyvalp]b4_locations_if([, YYLTYPE* yylocp])[)
{
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)
* semantic value of YYRHS under the action for YYRULE. */
static inline void
yyglrShiftDefer (yyGLRStack* yystackp, size_t yyk, yyStateNum yylrState,
size_t yyposn, yyGLRState* yyrhs, yyRuleNum yyrule)
yyglrShiftDefer (yyGLRStack* yystackp, ptrdiff_t yyk, yyStateNum yylrState,
ptrdiff_t yyposn, yyGLRState* yyrhs, yyRuleNum yyrule)
{
yyGLRState* yynewState = &yynewGLRStackItem (yystackp, yytrue)->yystate;
YYASSERT (yynewState->yyisState);
@@ -1335,15 +1346,14 @@ yyglrShiftDefer (yyGLRStack* yystackp, size_t yyk, yyStateNum yylrState,
`----------------------------------------------------------------------*/
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[)
{
int yynrhs = yyrhsLength (yyrule);]b4_locations_if([
int yylow = 1;])[
int yyi;
YYFPRINTF (stderr, "Reducing stack %lu by rule %d (line %lu):\n",
(unsigned long) yyk, yyrule - 1,
(unsigned long) yyrline[yyrule]);
YYFPRINTF (stderr, "Reducing stack %ld by rule %d (line %d):\n",
(long) yyk, yyrule - 1, yyrline[yyrule]);
if (! yynormal)
yyfillin (yyvsp, 1, -yynrhs);
/* 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
* for userAction. */
static inline YYRESULTTAG
yydoAction (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
yydoAction (yyGLRStack* yystackp, ptrdiff_t yyk, yyRuleNum yyrule,
YYSTYPE* yyvalp]b4_locuser_formals[)
{
int yynrhs = yyrhsLength (yyrule);
@@ -1380,7 +1390,7 @@ yydoAction (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
yyGLRStackItem* yyrhs = (yyGLRStackItem*) yystackp->yytops.yystates[yyk];
YYASSERT (yyk == 0);
yystackp->yynextFree -= yynrhs;
yystackp->yyspaceLeft += (size_t) yynrhs;
yystackp->yyspaceLeft += yynrhs;
yystackp->yytops.yystates[0] = & yystackp->yynextFree[-1].yystate;
YY_REDUCE_PRINT ((yytrue, yyrhs, yyk, yyrule]b4_user_args[));
return yyuserAction (yyrule, yynrhs, yyrhs, yystackp,
@@ -1388,11 +1398,10 @@ yydoAction (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
}
else
{
int yyi;
yyGLRState* yys;
yyGLRStackItem yyrhsVals[YYMAXRHS + YYMAXLEFT + 1];
yys = yyrhsVals[YYMAXRHS + YYMAXLEFT].yystate.yypred
= yystackp->yytops.yystates[yyk];]b4_locations_if([[
yyGLRState* yys = yyrhsVals[YYMAXRHS + YYMAXLEFT].yystate.yypred
= yystackp->yytops.yystates[yyk];
int yyi;]b4_locations_if([[
if (yynrhs == 0)
/* Set default location. */
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.
*/
static inline YYRESULTTAG
yyglrReduce (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
yyglrReduce (yyGLRStack* yystackp, ptrdiff_t yyk, yyRuleNum yyrule,
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)
{
@@ -1434,8 +1443,9 @@ yyglrReduce (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
YYRESULTTAG yyflag = yydoAction (yystackp, yyk, yyrule, &yysval]b4_locuser_args([&yyloc])[);
if (yyflag == yyerr && yystackp->yysplitPoint != YY_NULLPTR)
{
YYDPRINTF ((stderr, "Parse on stack %lu rejected by rule #%d.\n",
(unsigned long) yyk, yyrule - 1));
YYDPRINTF ((stderr,
"Parse on stack %ld rejected by rule %d (line %d).\n",
(long) yyk, yyrule - 1, yyrline[yyrule - 1]));
}
if (yyflag != yyok)
return yyflag;
@@ -1447,7 +1457,7 @@ yyglrReduce (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
}
else
{
size_t yyi;
ptrdiff_t yyi;
int yyn;
yyGLRState* yys, *yys0 = yystackp->yytops.yystates[yyk];
yyStateNum yynewLRState;
@@ -1461,9 +1471,9 @@ yyglrReduce (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
yyupdateSplit (yystackp, yys);
yynewLRState = yyLRgotoState (yys->yylrState, yylhsNonterm (yyrule));
YYDPRINTF ((stderr,
"Reduced stack %lu by rule #%d; action deferred. "
"Reduced stack %ld by rule %d (line %d); action deferred. "
"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)
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);
yymarkStackDeleted (yystackp, yyk);
YYDPRINTF ((stderr, "Merging stack %lu into stack %lu.\n",
(unsigned long) yyk,
(unsigned long) yyi));
YYDPRINTF ((stderr, "Merging stack %ld into stack %ld.\n",
(long) yyk, (long) yyi));
return yyok;
}
yyp = yyp->yypred;
@@ -1489,8 +1498,8 @@ yyglrReduce (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
return yyok;
}
static size_t
yysplitStack (yyGLRStack* yystackp, size_t yyk)
static ptrdiff_t
yysplitStack (yyGLRStack* yystackp, ptrdiff_t yyk)
{
if (yystackp->yysplitPoint == YY_NULLPTR)
{
@@ -1501,15 +1510,16 @@ yysplitStack (yyGLRStack* yystackp, size_t yyk)
{
yyGLRState** yynewStates = YY_NULLPTR;
yybool* yynewLookaheadNeeds;
ptrdiff_t state_size = sizeof yynewStates[0];
ptrdiff_t half_max_capacity = YYSIZEMAX / 2 / state_size;
if (yystackp->yytops.yycapacity
> (YYSIZEMAX / (2 * sizeof yynewStates[0])))
if (half_max_capacity < yystackp->yytops.yycapacity)
yyMemoryExhausted (yystackp);
yystackp->yytops.yycapacity *= 2;
yynewStates =
(yyGLRState**) YYREALLOC (yystackp->yytops.yystates,
(yystackp->yytops.yycapacity
((size_t) yystackp->yytops.yycapacity
* sizeof yynewStates[0]));
if (yynewStates == YY_NULLPTR)
yyMemoryExhausted (yystackp);
@@ -1517,7 +1527,7 @@ yysplitStack (yyGLRStack* yystackp, size_t yyk)
yynewLookaheadNeeds =
(yybool*) YYREALLOC (yystackp->yytops.yylookaheadNeeds,
(yystackp->yytops.yycapacity
((size_t) yystackp->yytops.yycapacity
* sizeof yynewLookaheadNeeds[0]));
if (yynewLookaheadNeeds == YY_NULLPTR)
yyMemoryExhausted (yystackp);
@@ -1719,10 +1729,10 @@ yyreportTree (yySemanticOption* yyx, int yyindent)
yyindent, "", yytokenName (yylhsNonterm (yyx->yyrule)),
yyx->yyrule - 1);
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)),
yyx->yyrule - 1, (unsigned long) (yys->yyposn + 1),
(unsigned long) yyx->yystate->yyposn);
yyx->yyrule - 1, (long) (yys->yyposn + 1),
(long) yyx->yystate->yyposn);
for (yyi = 1; yyi <= yynrhs; yyi += 1)
{
if (yystates[yyi]->yyresolved)
@@ -1731,10 +1741,10 @@ yyreportTree (yySemanticOption* yyx, int yyindent)
YYFPRINTF (stderr, "%*s%s <empty>\n", yyindent+2, "",
yytokenName (yystos[yystates[yyi]->yylrState]));
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]),
(unsigned long) (yystates[yyi-1]->yyposn + 1),
(unsigned long) yystates[yyi]->yyposn);
(long) (yystates[yyi-1]->yyposn + 1),
(long) yystates[yyi]->yyposn);
}
else
yyreportTree (yystates[yyi]->yysemantics.yyfirstVal, yyindent+2);
@@ -1929,9 +1939,9 @@ yycompressStack (yyGLRStack* yystackp)
yyr = yyp, yyp = yyq, yyq = yyp->yypred)
yyp->yypred = yyr;
yystackp->yyspaceLeft += (size_t) (yystackp->yynextFree - yystackp->yyitems);
yystackp->yyspaceLeft += yystackp->yynextFree - yystackp->yyitems;
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->yylastDeleted = YY_NULLPTR;
@@ -1947,14 +1957,13 @@ yycompressStack (yyGLRStack* yystackp)
}
static YYRESULTTAG
yyprocessOneStack (yyGLRStack* yystackp, size_t yyk,
size_t yyposn]b4_pure_formals[)
yyprocessOneStack (yyGLRStack* yystackp, ptrdiff_t yyk,
ptrdiff_t yyposn]b4_pure_formals[)
{
while (yystackp->yytops.yystates[yyk] != YY_NULLPTR)
{
yyStateNum yystate = yystackp->yytops.yystates[yyk]->yylrState;
YYDPRINTF ((stderr, "Stack %lu Entering state %d\n",
(unsigned long) yyk, yystate));
YYDPRINTF ((stderr, "Stack %ld Entering state %d\n", yyk, yystate));
YYASSERT (yystate != YYFINAL);
@@ -1964,8 +1973,7 @@ yyprocessOneStack (yyGLRStack* yystackp, size_t yyk,
yyRuleNum yyrule = yydefaultAction (yystate);
if (yyrule == 0)
{
YYDPRINTF ((stderr, "Stack %lu dies.\n",
(unsigned long) yyk));
YYDPRINTF ((stderr, "Stack %ld dies.\n", (long) yyk));
yymarkStackDeleted (yystackp, yyk);
return yyok;
}
@@ -1973,9 +1981,9 @@ yyprocessOneStack (yyGLRStack* yystackp, size_t yyk,
if (yyflag == yyerr)
{
YYDPRINTF ((stderr,
"Stack %lu dies "
"Stack %ld dies "
"(predicate failure or explicit user error).\n",
(unsigned long) yyk));
(long) yyk));
yymarkStackDeleted (yystackp, yyk);
return yyok;
}
@@ -1984,21 +1992,17 @@ yyprocessOneStack (yyGLRStack* yystackp, size_t yyk,
}
else
{
yySymbol yytoken;
int yyaction;
yySymbol yytoken = ]b4_yygetToken_call[;
const short* yyconflicts;
const int yyaction = yygetLRActions (yystate, yytoken, &yyconflicts);
yystackp->yytops.yylookaheadNeeds[yyk] = yytrue;
yytoken = ]b4_yygetToken_call[;
yyaction = yygetLRActions (yystate, yytoken, &yyconflicts);
while (*yyconflicts != 0)
{
YYRESULTTAG yyflag;
size_t yynewStack = yysplitStack (yystackp, yyk);
YYDPRINTF ((stderr, "Splitting off stack %lu from %lu.\n",
(unsigned long) yynewStack,
(unsigned long) yyk));
ptrdiff_t yynewStack = yysplitStack (yystackp, yyk);
YYDPRINTF ((stderr, "Splitting off stack %ld from %ld.\n",
(long) yynewStack, (long) yyk));
yyflag = yyglrReduce (yystackp, yynewStack,
*yyconflicts,
yyimmediate[*yyconflicts]]b4_user_args[);
@@ -2007,8 +2011,7 @@ yyprocessOneStack (yyGLRStack* yystackp, size_t yyk,
yyposn]b4_pure_args[));
else if (yyflag == yyerr)
{
YYDPRINTF ((stderr, "Stack %lu dies.\n",
(unsigned long) yynewStack));
YYDPRINTF ((stderr, "Stack %ld dies.\n", (long) yynewStack));
yymarkStackDeleted (yystackp, yynewStack);
}
else
@@ -2020,8 +2023,7 @@ yyprocessOneStack (yyGLRStack* yystackp, size_t yyk,
break;
else if (yyisErrorAction (yyaction))
{
YYDPRINTF ((stderr, "Stack %lu dies.\n",
(unsigned long) yyk));
YYDPRINTF ((stderr, "Stack %ld dies.\n", (long) yyk));
yymarkStackDeleted (yystackp, yyk);
break;
}
@@ -2032,9 +2034,9 @@ yyprocessOneStack (yyGLRStack* yystackp, size_t yyk,
if (yyflag == yyerr)
{
YYDPRINTF ((stderr,
"Stack %lu dies "
"Stack %ld dies "
"(predicate failure or explicit user error).\n",
(unsigned long) yyk));
(long) yyk));
yymarkStackDeleted (yystackp, yyk);
break;
}
@@ -2056,8 +2058,8 @@ yyreportSyntaxError (yyGLRStack* yystackp]b4_user_formals[)
#else
{
yySymbol yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
size_t yysize0 = yytnamerr (YY_NULLPTR, yytokenName (yytoken));
size_t yysize = yysize0;
ptrdiff_t yysize0 = yytnamerr (YY_NULLPTR, yytokenName (yytoken));
ptrdiff_t yysize = yysize0;
yybool yysize_overflow = yyfalse;
char* yymsg = YY_NULLPTR;
enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
@@ -2118,10 +2120,11 @@ yyreportSyntaxError (yyGLRStack* yystackp]b4_user_formals[)
}
yyarg[yycount++] = yytokenName (yyx);
{
size_t yysz = yysize + yytnamerr (YY_NULLPTR, yytokenName (yyx));
if (yysz < yysize)
ptrdiff_t yysz = yytnamerr (YY_NULLPTR, yytokenName (yyx));
if (YYSIZEMAX - yysize < yysz)
yysize_overflow = yytrue;
yysize = yysz;
else
yysize += yysz;
}
}
}
@@ -2144,14 +2147,15 @@ yyreportSyntaxError (yyGLRStack* yystackp]b4_user_formals[)
}
{
size_t yysz = yysize + strlen (yyformat);
if (yysz < yysize)
ptrdiff_t yysz = (ptrdiff_t) strlen (yyformat);
if (YYSIZEMAX - yysize < yysz)
yysize_overflow = yytrue;
yysize = yysz;
else
yysize += yysz;
}
if (!yysize_overflow)
yymsg = (char *) YYMALLOC (yysize);
yymsg = (char *) YYMALLOC ((size_t) yysize);
if (yymsg)
{
@@ -2228,7 +2232,7 @@ yyrecoverSyntaxError (yyGLRStack* yystackp]b4_user_formals[)
/* Reduce to one stack. */
{
size_t yyk;
ptrdiff_t yyk;
for (yyk = 0; yyk < yystackp->yytops.yysize; yyk += 1)
if (yystackp->yytops.yystates[yyk] != YY_NULLPTR)
break;
@@ -2252,14 +2256,15 @@ yyrecoverSyntaxError (yyGLRStack* yystackp]b4_user_formals[)
if (0 <= yyj && yyj <= YYLAST && yycheck[yyj] == YYTERROR
&& 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.*/
YYLTYPE yyerrloc;
yystackp->yyerror_range[2].yystate.yyloc = yylloc;
YYLLOC_DEFAULT (yyerrloc, (yystackp->yyerror_range), 2);]])[
YY_SYMBOL_PRINT ("Shifting", yystos[yytable[yyj]],
YY_SYMBOL_PRINT ("Shifting", yystos[yyaction],
&yylval, &yyerrloc);
yyglrShift (yystackp, 0, yytable[yyj],
yyglrShift (yystackp, 0, yyaction,
yys->yyposn, &yylval]b4_locations_if([, &yyerrloc])[);
yys = yystackp->yytops.yystates[0];
break;
@@ -2301,7 +2306,7 @@ yyrecoverSyntaxError (yyGLRStack* yystackp]b4_user_formals[)
int yyresult;
yyGLRStack yystack;
yyGLRStack* const yystackp = &yystack;
size_t yyposn;
ptrdiff_t yyposn;
YYDPRINTF ((stderr, "Starting parse\n"));
@@ -2381,7 +2386,7 @@ b4_dollar_popdef])[]dnl
while (yytrue)
{
yySymbol yytoken_to_shift;
size_t yys;
ptrdiff_t yys;
for (yys = 0; yys < yystack.yytops.yysize; yys += 1)
yystackp->yytops.yylookaheadNeeds[yys] = (yybool) (yychar != YYEMPTY);
@@ -2435,12 +2440,12 @@ b4_dollar_popdef])[]dnl
int yyaction = yygetLRActions (yystate, yytoken_to_shift,
&yyconflicts);
/* 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);
yyglrShift (&yystack, yys, yyaction, yyposn,
&yylval]b4_locations_if([, &yylloc])[);
YYDPRINTF ((stderr, "Stack %lu now in state #%d\n",
(unsigned long) yys,
YYDPRINTF ((stderr, "Stack %ld now in state #%d\n",
(long) yys,
yystack.yytops.yystates[yys]->yylrState));
}
@@ -2488,8 +2493,8 @@ b4_dollar_popdef])[]dnl
yyGLRState** yystates = yystack.yytops.yystates;
if (yystates)
{
size_t yysize = yystack.yytops.yysize;
size_t yyk;
ptrdiff_t yysize = yystack.yytops.yysize;
ptrdiff_t yyk;
for (yyk = 0; yyk < yysize; yyk += 1)
if (yystates[yyk])
{
@@ -2522,8 +2527,7 @@ yy_yypstack (yyGLRState* yys)
yy_yypstack (yys->yypred);
YYFPRINTF (stderr, " -> ");
}
YYFPRINTF (stderr, "%d@@%lu", yys->yylrState,
(unsigned long) yys->yyposn);
YYFPRINTF (stderr, "%d@@%ld", yys->yylrState, (long) yys->yyposn);
}
static void
@@ -2537,7 +2541,7 @@ yypstates (yyGLRState* yyst)
}
static void
yypstack (yyGLRStack* yystackp, size_t yyk)
yypstack (yyGLRStack* yystackp, ptrdiff_t yyk)
{
yypstates (yystackp->yytops.yystates[yyk]);
}
@@ -2550,18 +2554,18 @@ static void
yypdumpstack (yyGLRStack* yystackp)
{
yyGLRStackItem* yyp;
size_t yyi;
ptrdiff_t yyi;
for (yyp = yystackp->yyitems; yyp < yystackp->yynextFree; yyp += 1)
{
YYFPRINTF (stderr, "%3lu. ",
(unsigned long) (yyp - yystackp->yyitems));
YYFPRINTF (stderr, "%3ld. ",
(long) (yyp - yystackp->yyitems));
if (*(yybool *) yyp)
{
YYASSERT (yyp->yystate.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,
(unsigned long) yyp->yystate.yyposn,
(long) yyp->yystate.yyposn,
(long) YYINDEX (yyp->yystate.yypred));
if (! yyp->yystate.yyresolved)
YYFPRINTF (stderr, ", firstVal: %ld",
@@ -2581,7 +2585,7 @@ yypdumpstack (yyGLRStack* yystackp)
}
YYFPRINTF (stderr, "Tops:");
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]));
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]])])
b4_percent_define_default([[api.value.type]], [[Object]])
# %name-prefix
m4_define_default([b4_prefix], [[YY]])
# b4_api_prefix, b4_api_PREFIX
# ----------------------------
# 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])
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.
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)
# --------------------------------------------------------------
# Declare "parser::yy<TABLE-NAME>_" whose contents is CONTENT.
m4_define([b4_integral_parser_table_declare],
[m4_ifval([$3], [b4_comment([$3], [ ])
[m4_ifval([$3], [b4_comment([$3], [ ])
])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)
@@ -220,10 +228,21 @@ m4_define([b4_shared_declarations],
private:
/// This class is not copyable.
]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.
typedef int state_type;
/// Check the lookahead yytoken.
/// \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.
/// \param yystate the state where the error occurred.
@@ -234,7 +253,7 @@ m4_define([b4_shared_declarations],
/// Compute post-reduction state.
/// \param yystate the current state
/// \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.
/// \param yyvalue the value to check
@@ -335,6 +354,10 @@ m4_define([b4_shared_declarations],
/// Assignment, needed by push_back by some old implementations.
/// Moves the contents of 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
};
@@ -344,7 +367,16 @@ m4_define([b4_shared_declarations],
typedef stack<stack_symbol_type> stack_type;
/// 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.
/// \param m a debug message to display
@@ -548,12 +580,14 @@ m4_if(b4_prefix, [yy], [],
]])[
/// 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
]m4_ifset([b4_parse_param], [ ], [ :])[yydebug_ (false),
yycdebug_ (&std::cerr)]m4_ifset([b4_parse_param], [,])[
#endif]b4_parse_param_cons[
: yydebug_ (false),
yycdebug_ (&std::cerr)]b4_lac_if([,], [m4_ifset([b4_parse_param], [,])])[
#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[ ()
@@ -627,6 +661,17 @@ m4_if(b4_prefix, [yy], [],
}
#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::operator= (stack_symbol_type& that)
{
@@ -758,7 +803,6 @@ m4_if(b4_prefix, [yy], [],
int
]b4_parser_class[::parse ()
{
// State.
int yyn;
/// Length of the RHS of the rule being reduced.
int yylen = 0;
@@ -774,7 +818,11 @@ m4_if(b4_prefix, [yy], [],
stack_symbol_type yyerror_range[3];]])[
/// 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
try
@@ -798,7 +846,7 @@ b4_dollar_popdef])[]dnl
| yynewstate -- push a new symbol on the stack. |
`-----------------------------------------------*/
yynewstate:
YYCDEBUG << "Entering state " << yystack_[0].state << '\n';
YYCDEBUG << "Entering state " << int (yystack_[0].state) << '\n';
// Accept?
if (yystack_[0].state == yyfinal_)
@@ -843,14 +891,21 @@ b4_dollar_popdef])[]dnl
to detect an error, take that action. */
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.
yyn = yytable_[yyn];
if (yyn <= 0)
{
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;
goto yyreduce;
}
@@ -860,7 +915,8 @@ b4_dollar_popdef])[]dnl
--yyerrstatus_;
// 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;
@@ -1020,8 +1076,9 @@ b4_dollar_popdef])[]dnl
yyerror_range[2].location = yyla.location;
YYLLOC_DEFAULT (error_token.location, yyerror_range, 2);]])[
// Shift the error token.
error_token.state = yyn;
// Shift the error token.]b4_lac_if([[
yy_lac_discard_ ("error recovery");]])[
error_token.state = static_cast<state_type> (yyn);
yypush_ ("Shifting", YY_MOVE (error_token));
}
goto yynewstate;
@@ -1085,8 +1142,147 @@ b4_dollar_popdef])[]dnl
{
error (]b4_join(b4_locations_if([yyexc.location]),
[[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.
std::string
]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([[
// Number of reported tokens (one for the "unexpected", one per
// "expected").
size_t yycount = 0;
std::ptrdiff_t yycount = 0;
// Its maximum.
enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
// 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
been a previous inconsistent state, consistent state with a
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
correct lookahead information, and it depends on the parser not
to perform extra reductions after fetching a lookahead from the
scanner and before detecting a syntax error. Thus, state
merging (from LALR or IELR) and default reductions corrupt the
expected token list. However, the list is correct for
canonical LR with one exception: it will still contain any
token that will not be accepted due to an error action in a
later state.
scanner and before detecting a syntax error. Thus, state merging
(from LALR or IELR) and default reductions corrupt the expected
token list. However, the list is correct for canonical LR with
one exception: it will still contain any token that will not be
accepted due to an error action in a later state.]])[
*/
if (!yyla.empty ())
{
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];
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
YYCHECK. In other words, skip the first -YYN actions for
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)
if (yycheck_[yyx + yyn] == yyx && yyx != yyterror_
&& !yy_table_value_is_error_ (yytable_[yyx + yyn]))
{
{]])[
if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
{
yycount = 1;
@@ -1174,7 +1386,7 @@ b4_error_verbose_if([state_type yystate, const symbol_type& yyla],
std::string yyres;
// Argument number.
size_t yyi = 0;
std::ptrdiff_t yyi = 0;
for (char const* yyp = yyformat; *yyp; ++yyp)
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_end = yystack_.end ();
i != i_end; ++i)
*yycdebug_ << ' ' << i->state;
*yycdebug_ << ' ' << int (i->state);
*yycdebug_ << '\n';
}
@@ -1223,7 +1435,7 @@ b4_error_verbose_if([state_type yystate, const symbol_type& yyla],
void
]b4_parser_class[::yy_reduce_print_ (int yyrule)
{
unsigned yylno = yyrline_[yyrule];
int yylno = yyrline_[yyrule];
int yynrhs = yyr2_[yyrule];
// Print the symbols being reduced, and their result.
*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
# it under the terms of the GNU General Public License as published by
@@ -18,12 +18,11 @@
m4_include(b4_skeletonsdir/[d.m4])
m4_divert_push(0)dnl
@output(b4_parser_file_name@)@
b4_output_begin([b4_parser_file_name])
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) {
} else {
@@ -81,68 +80,14 @@ public interface Lexer
void yyerror (]b4_locations_if([b4_location_type[ loc, ]])[string s);
}
private final struct YYStackElement{
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([[[
]b4_locations_if([b4_position_type_if([[
static assert(__traits(compiles,
(new ]b4_position_type[[1])[0]=(new ]b4_position_type[[1])[0]),
"struct/class ]b4_position_type[ must be default-constructible "
"and assignable");
static assert(__traits(compiles, (new string[1])[0]=(new ]b4_position_type[).toString()),
"error: struct/class ]b4_position_type[ must have toString method");
]]], [[
]], [[
/**
* A struct denoting a point in the input.*/
public struct ]b4_position_type[ {
@@ -152,15 +97,18 @@ public struct ]b4_position_type[ {
/** The line number within an input file. */
public int line = 1;
/** 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 {
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]))) &&
__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 "
@@ -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()),
"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
* <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;
}
public this () {
}
/**
* Create a <code>]b4_location_type[</code> from the endpoints of 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>
* method. */
public const string toString () const {
if (begin==end)
return begin.toString ();
else
return begin.toString () ~ "-" ~ end.toString ();
public override string toString () const {
auto end_col = 0 < end.column ? end.column - 1 : 0;
auto res = begin.toString ();
if (end.filename && begin.filename != end.filename)
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;
]]))m4_ifdef([b4_user_union_members], [private union YYSemanticType
]])])m4_ifdef([b4_user_union_members], [private union YYSemanticType
{
b4_user_union_members
};],
@@ -261,29 +217,27 @@ b4_user_union_members
]b4_lexer_if([[
/**
* Instantiates the Bison-generated parser.
* Instantiate the Bison-generated parser.
*/
public this] (b4_parse_param_decl([b4_lex_param_decl])[) {
this.yylexer = new YYLexer(]b4_lex_param_call[);
this.yyDebugStream = stderr;
]b4_parse_param_cons[
this (new YYLexer(]b4_lex_param_call[));
}
]])[
/**
* Instantiates the Bison-generated parser.
* Instantiate the Bison-generated parser.
* @@param yylexer The scanner that will supply tokens to the parser.
*/
]b4_lexer_if([[protected]], [[public]]) [this (]b4_parse_param_decl([[Lexer yylexer]])[) {
this.yylexer = yylexer;
this.yyDebugStream = stderr;
this.yylexer = yylexer;]b4_parse_trace_if([[
this.yyDebugStream = stderr;]])[
]b4_parse_param_cons[
}
]b4_parse_trace_if([[
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.
*/
public File getDebugStream () { return yyDebugStream; }
@@ -309,16 +263,17 @@ b4_user_union_members
*/
public final void setDebugLevel(int level) { yydebug = level; }
protected final void yycdebug (string s) {
if (0 < yydebug)
yyDebugStream.writeln (s);
}
]])[
private final int yylex () {
return yylexer.yylex ();
}
protected final void yyerror (]b4_locations_if(ref [b4_location_type[ loc, ]])[string 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 YYRETURN = 8;
]b4_locations_if([
private static immutable YYSemanticType yy_semantic_null = cast(YYSemanticType)null;])[
private static immutable YYSemanticType yy_semantic_null;])[
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
* operation. */
public final bool recovering ()
@@ -373,7 +328,8 @@ b4_user_union_members
else
yyval = yystack.valueAt (0);
yy_reduce_print (yyn, yystack);
]b4_parse_trace_if([[
yy_reduce_print (yyn, yystack);]])[
switch (yyn)
{
@@ -381,7 +337,8 @@ b4_user_union_members
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);
yylen = 0;
@@ -429,12 +386,12 @@ b4_user_union_members
return yyr;
}
}
else if (yystr=="$end")
else if (yystr == "$end")
return "end of input";
return yystr;
}
]b4_parse_trace_if([[
/*--------------------------------.
| Print this symbol on YYOUTPUT. |
`--------------------------------*/
@@ -443,11 +400,11 @@ b4_user_union_members
ref ]b4_yystype[ yyvaluep]dnl
b4_locations_if([, ref ]b4_location_type[ yylocationp])[)
{
if (yydebug > 0) {
if (0 < yydebug) {
string message = s ~ (yytype < yyntokens_ ? " token " : " nterm ")
~ yytname_[yytype] ~ " ("]b4_locations_if([
~ yylocationp.toString() ~ ": "])[;
static if (__traits(compiles, message~=yyvaluep.toString ()))
static if (__traits(compiles, message ~= yyvaluep.toString ()))
message ~= yyvaluep.toString ();
else
message ~= format ("%s", &yyvaluep);
@@ -455,7 +412,7 @@ b4_locations_if([, ref ]b4_location_type[ yylocationp])[)
yycdebug (message);
}
}
]])[
/**
* Parse input from the scanner that was specified at object construction
* 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.
]b4_yystype[ yylval;
int yyresult;
int yyresult;]b4_parse_trace_if([[
yycdebug ("Starting parse\n");
yycdebug ("Starting parse\n");]])[
yyerrstatus_ = 0;
]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
pushed when we come here. */
case YYNEWSTATE:
case YYNEWSTATE:]b4_parse_trace_if([[
yycdebug (format("Entering state %d\n", yystate));
if (yydebug > 0)
yystack.print (yyDebugStream);
if (0 < yydebug)
yystack.print (yyDebugStream);]])[
/* Accept? */
if (yystate == yyfinal_)
@@ -531,8 +488,8 @@ m4_popdef([b4_at_dollar])])dnl
/* Read a lookahead token. */
if (yychar == yyempty_)
{
yycdebug ("Reading a token: ");
{]b4_parse_trace_if([[
yycdebug ("Reading a token: ");]])[
yychar = yylex ();]b4_locations_if([[
static if (yy_location_is_class) {
yylloc = new ]b4_location_type[(yylexer.startPos, yylexer.endPos);
@@ -543,17 +500,9 @@ m4_popdef([b4_at_dollar])])dnl
}
/* Convert token to internal form. */
if (yychar <= YYTokenType.EOF)
{
yychar = yytoken = YYTokenType.EOF;
yycdebug ("Now at end of input.\n");
}
else
{
yytoken = yytranslate_ (yychar);
yy_symbol_print ("Next token is",
yytoken, yylval]b4_locations_if([, yylloc])[);
}
yytoken = yytranslate_ (yychar);]b4_parse_trace_if([[
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
detect an error, take that action. */
@@ -574,9 +523,9 @@ m4_popdef([b4_at_dollar])])dnl
}
else
{
/* Shift the lookahead token. */
/* Shift the lookahead token. */]b4_parse_trace_if([[
yy_symbol_print ("Shifting", yytoken,
yylval]b4_locations_if([, yylloc])[);
yylval]b4_locations_if([, yylloc])[);]])[
/* Discard the token being shifted. */
yychar = yyempty_;
@@ -685,9 +634,9 @@ m4_popdef([b4_at_dollar])])dnl
]b4_locations_if([ yyerrloc = yystack.locationAt (0);])[
yystack.pop ();
yystate = yystack.stateAt (0);
if (yydebug > 0)
yystack.print (yyDebugStream);
yystate = yystack.stateAt (0);]b4_parse_trace_if([[
if (0 < yydebug)
yystack.print (yyDebugStream);]])[
}
]b4_locations_if([
@@ -697,9 +646,9 @@ m4_popdef([b4_at_dollar])])dnl
yyloc = yylloc_from_stack (yystack, 2);
yystack.pop (2);])[
/* Shift the error token. */
/* Shift the error token. */]b4_parse_trace_if([[
yy_symbol_print ("Shifting", yystos_[yyn],
yylval]b4_locations_if([, yyloc])[);
yylval]b4_locations_if([, yyloc])[);]])[
yystate = yyn;
yystack.push (yyn, yylval]b4_locations_if([, yyloc])[);
@@ -837,6 +786,7 @@ m4_popdef([b4_at_dollar])])dnl
]b4_tname[
@};
]b4_parse_trace_if([[
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
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_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)
{
if (t >= 0 && t <= yyuser_token_number_max_)
return yytranslate_table_[t];
]b4_api_token_raw_if(
[[ 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
return yyundef_token_;
return yyundef_token_;]])[
}
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 yyundef_token_ = ]b4_undef_token_number[;
]/* User implementation code. */
b4_percent_code_get[]dnl
private final struct YYStackElement {
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
m4_divert_pop(0)dnl
]b4_epilogue[]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.
@@ -19,10 +19,6 @@ m4_include(b4_skeletonsdir/[java.m4])
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],
[b4_symbol_if([$1], [has_destructor],
[b4_complain_at(m4_unquote(b4_symbol([$1], [destructor_loc])),
@@ -70,19 +66,19 @@ m4_define([b4_define_state],[[
/* Error handling. */
int yynerrs_ = 0;
]b4_locations_if([/* The location where the error started. */
b4_location_type yyerrloc = null;
]b4_locations_if([[/* The location where the error started. */
]b4_location_type[ yyerrloc = null;
/* Location. */
b4_location_type yylloc = new b4_location_type (null, null);])[
]b4_location_type[ yylloc = new ]b4_location_type[ (null, null);]])[
/* Semantic value of the lookahead. */
]b4_yystype[ yylval = null;
]])
]])[
b4_output_begin([b4_parser_file_name])[
]b4_output_begin([b4_parser_file_name])[
]b4_copyright([Skeleton implementation for Bison LALR(1) parsers in Java],
[2007-2015, 2018])[
[2007-2015, 2018-2019])[
]b4_percent_define_ifdef([package], [package b4_percent_define_get([package]);[
]])[
]b4_user_pre_prologue[
@@ -103,7 +99,7 @@ b4_output_begin([b4_parser_file_name])[
private boolean yyErrorVerbose = true;
/**
* Return whether verbose error messages are enabled.
* Whether verbose error messages are enabled.
*/
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)
{
if (n > 0)
if (0 < n)
return new ]b4_location_type[ (rhs.locationAt (n-1).begin, rhs.locationAt (0).end);
else
return new ]b4_location_type[ (rhs.locationAt (0).end);
@@ -220,10 +216,11 @@ b4_locations_if([[
* error message is related]])[
* @@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]])[
}
@@ -231,10 +228,10 @@ b4_locations_if([[
* The object doing lexical analysis for us.
*/
private Lexer yylexer;
]
b4_parse_param_vars
b4_lexer_if([[
]b4_parse_param_vars[
]b4_lexer_if([[
/**
* Instantiates the Bison-generated parser.
*/
@@ -244,24 +241,24 @@ b4_lexer_if([[
this.yylexer = new YYLexer(]b4_lex_param_call[);
]b4_parse_param_cons[
}
]])
]])[
/**
* Instantiates the Bison-generated parser.
* @@param yylexer The scanner that will supply tokens to the parser.
*/
b4_lexer_if([[protected]], [[public]]) b4_parser_class[ (]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]])[
this.yylexer = yylexer;
]b4_parse_param_cons[
}
]b4_parse_trace_if([[
private java.io.PrintStream yyDebugStream = System.err;
/**
* Return the <tt>PrintStream</tt> on which the debugging output is
* printed.
* The <tt>PrintStream</tt> on which the debugging output is printed.
*/
public final java.io.PrintStream getDebugStream () { return yyDebugStream; }
@@ -285,6 +282,7 @@ b4_lexer_if([[
* @@param level The verbosity level for debugging output.
*/
public final void setDebugLevel(int level) { yydebug = level; }
]])[
/**
* Print an error message via the lexer.
@@ -314,12 +312,12 @@ b4_lexer_if([[
public final void yyerror (]b4_position_type[ pos, String msg)
{
yylexer.yyerror (new ]b4_location_type[ (pos), msg);
}]])
[protected final void yycdebug (String s) {
if (yydebug > 0)
}]])[
]b4_parse_trace_if([[
protected final void yycdebug (String s) {
if (0 < yydebug)
yyDebugStream.println (s);
}
}]])[
private final class YYStack {
private int[] stateStack = new int[16];
@@ -360,7 +358,7 @@ b4_lexer_if([[
public final void pop (int num) {
// 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);
]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;
]b4_push_if([dnl
b4_define_state])[
]b4_push_if([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
* operation.
*/
@@ -446,7 +443,7 @@ b4_define_state])[
* @@param yystate the current state
* @@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;
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])[
{
]b4_yystype[ yyval;
]b4_locations_if([b4_location_type[ yyloc = yylloc (yystack, yylen);]])[
/* If YYLEN is nonzero, implement the default value of the action:
'$$ = $1'. Otherwise, use the top of the stack.
Otherwise, the following line sets YYVAL to garbage.
This behavior is undocumented and Bison
users should not rely upon it. */
if (yylen > 0)
yyval = yystack.valueAt (yylen - 1);
else
yyval = yystack.valueAt (0);
]b4_yystype[ yyval = (0 < yylen) ? yystack.valueAt (yylen - 1) : yystack.valueAt (0);
]b4_locations_if([b4_location_type[ yyloc = yylloc (yystack, yylen);]])[]b4_parse_trace_if([[
yy_reduce_print (yyn, yystack);
yyReducePrint (yyn, yystack);]])[
switch (yyn)
{
]b4_user_actions[
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);
yylen = 0;
/* 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])[);
return YYNEWSTATE;
}
@@ -526,21 +518,20 @@ b4_define_state])[
return yystr;
}
]])[
]b4_parse_trace_if([[
/*--------------------------------.
| Print this symbol on YYOUTPUT. |
`--------------------------------*/
private void yy_symbol_print (String s, int yytype,
]b4_yystype[ yyvaluep]dnl
b4_locations_if([, Object yylocationp])[)
private void yySymbolPrint (String s, int yytype,
]b4_yystype[ yyvaluep]dnl
b4_locations_if([, Object yylocationp])[)
{
if (yydebug > 0)
yycdebug (s + (yytype < yyntokens_ ? " token " : " nterm ")
+ yytname_[yytype] + " ("]b4_locations_if([
+ yylocationp + ": "])[
+ (yyvaluep == null ? "(null)" : yyvaluep.toString ()) + ")");
}
}]])[
]b4_push_if([],[[
/**
@@ -550,7 +541,7 @@ b4_define_state])[
* @@return <tt>true</tt> if the parsing succeeds. Note that this does not
* imply that there were no syntax errors.
*/
public boolean parse () ]b4_maybe_throws([b4_list2([b4_lex_throws], [b4_throws])])[]])[
public boolean parse () ]b4_maybe_throws([b4_list2([b4_lex_throws], [b4_throws])])[]])[
]b4_push_if([
/**
* Push Parse input from external lexer
@@ -567,8 +558,8 @@ b4_define_state])[
]b4_locations_if([/* @@$. */
b4_location_type yyloc;])[
]b4_push_if([],[[
]b4_define_state[
yycdebug ("Starting parse\n");
]b4_define_state[]b4_parse_trace_if([[
yycdebug ("Starting parse\n");]])[
yyerrstatus_ = 0;
/* Initialize the stack. */
@@ -587,8 +578,8 @@ b4_dollar_popdef[]dnl
b4_dollar_pushdef([yylval], [], [], [yylloc])dnl
b4_user_initial_action
b4_dollar_popdef[]dnl
])[
yycdebug ("Starting parse\n");
])[]b4_parse_trace_if([[
yycdebug ("Starting parse\n");]])[
yyerrstatus_ = 0;
} else
label = YYGETTOKEN;
@@ -600,10 +591,10 @@ b4_dollar_popdef[]dnl
{
/* New state. Unlike in the C/C++ skeletons, the state is already
pushed when we come here. */
case YYNEWSTATE:
case YYNEWSTATE:]b4_parse_trace_if([[
yycdebug ("Entering state " + yystate + "\n");
if (yydebug > 0)
yystack.print (yyDebugStream);
if (0 < yydebug)
yystack.print (yyDebugStream);]])[
/* Accept? */
if (yystate == yyfinal_)
@@ -612,7 +603,7 @@ b4_dollar_popdef[]dnl
/* Take a decision. First try without lookahead. */
yyn = yypact_[yystate];
if (yy_pact_value_is_default_ (yyn))
if (yyPactValueIsDefault (yyn))
{
label = YYDEFAULT;
break;
@@ -625,14 +616,13 @@ b4_dollar_popdef[]dnl
{
]b4_push_if([[
if (!push_token_consumed)
return YYPUSH_MORE;
yycdebug ("Reading a token: ");
return YYPUSH_MORE;]b4_parse_trace_if([[
yycdebug ("Reading a token: ");]])[
yychar = yylextoken;
yylval = yylexval;]b4_locations_if([
yylloc = yylexloc;])[
push_token_consumed = false;]])[
]b4_push_if([],[[
yycdebug ("Reading a token: ");
push_token_consumed = false;]], [b4_parse_trace_if([[
yycdebug ("Reading a token: ");]])[
yychar = yylexer.yylex ();
yylval = yylexer.getLVal ();]b4_locations_if([
yylloc = new b4_location_type (yylexer.getStartPos (),
@@ -641,17 +631,9 @@ b4_dollar_popdef[]dnl
}
/* Convert token to internal form. */
if (yychar <= Lexer.EOF)
{
yychar = yytoken = Lexer.EOF;
yycdebug ("Now at end of input.\n");
}
else
{
yytoken = yytranslate_ (yychar);
yy_symbol_print ("Next token is", yytoken,
yylval]b4_locations_if([, yylloc])[);
}
yytoken = yytranslate_ (yychar);]b4_parse_trace_if([[
yySymbolPrint ("Next token is", yytoken,
yylval]b4_locations_if([, yylloc])[);]])[
/* If the proper action on seeing token YYTOKEN is to reduce or to
detect an error, take that action. */
@@ -662,7 +644,7 @@ b4_dollar_popdef[]dnl
/* <= 0 means reduce or error. */
else if ((yyn = yytable_[yyn]) <= 0)
{
if (yy_table_value_is_error_ (yyn))
if (yyTableValueIsError (yyn))
label = YYERRLAB;
else
{
@@ -673,10 +655,10 @@ b4_dollar_popdef[]dnl
else
{
/* Shift the lookahead token. */
yy_symbol_print ("Shifting", yytoken,
yylval]b4_locations_if([, yylloc])[);
/* Shift the lookahead token. */]b4_parse_trace_if([[
yySymbolPrint ("Shifting", yytoken,
yylval]b4_locations_if([, yylloc])[);
]])[
/* Discard the token being shifted. */
yychar = yyempty_;
@@ -727,17 +709,17 @@ b4_dollar_popdef[]dnl
]b4_locations_if([yyerrloc = yylloc;])[
if (yyerrstatus_ == 3)
{
/* If just tried and failed to reuse lookahead token after an
error, discard it. */
/* If just tried and failed to reuse lookahead token after an
error, discard it. */
if (yychar <= Lexer.EOF)
{
/* Return failure if at end of input. */
if (yychar == Lexer.EOF)
]b4_push_if([{label = YYABORT; break;}],[return false;])[
}
else
yychar = yyempty_;
if (yychar <= Lexer.EOF)
{
/* Return failure if at end of input. */
if (yychar == Lexer.EOF)
]b4_push_if([{label = YYABORT; break;}], [return false;])[
}
else
yychar = yyempty_;
}
/* 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. |
`-------------------------------------------------*/
case YYERROR:
]b4_locations_if([yyerrloc = yystack.locationAt (yylen - 1);])[
/* Do not reclaim the symbols of the rule which action triggered
this YYERROR. */
@@ -768,7 +749,7 @@ b4_dollar_popdef[]dnl
for (;;)
{
yyn = yypact_[yystate];
if (!yy_pact_value_is_default_ (yyn))
if (!yyPactValueIsDefault (yyn))
{
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);])[
yystack.pop ();
yystate = yystack.stateAt (0);
if (yydebug > 0)
yystack.print (yyDebugStream);
yystate = yystack.stateAt (0);]b4_parse_trace_if([[
if (0 < yydebug)
yystack.print (yyDebugStream);]])[
}
if (label == YYABORT)
@@ -802,9 +783,9 @@ b4_dollar_popdef[]dnl
yyloc = yylloc (yystack, 2);
yystack.pop (2);])[
/* Shift the error token. */
yy_symbol_print ("Shifting", yystos_[yyn],
yylval]b4_locations_if([, yyloc])[);
/* Shift the error token. */]b4_parse_trace_if([[
yySymbolPrint ("Shifting", yystos_[yyn],
yylval]b4_locations_if([, yyloc])[);]])[
yystate = yyn;
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));
}
])[]])
])[]])[
b4_both_if([[
]b4_both_if([[
/**
* Parse input from the scanner that was specified at object construction
* time. Return whether the end of the input was reached successfully.
@@ -881,21 +862,21 @@ b4_both_if([[
* @@return <tt>true</tt> if the parsing succeeds. Note that this does not
* imply that there were no syntax errors.
*/
public boolean parse () ]b4_maybe_throws([b4_list2([b4_lex_throws], [b4_throws])])[
{
if (yylexer == null)
throw new NullPointerException("Null Lexer");
int status;
do {
int token = yylexer.yylex();
]b4_yystype[ lval = yylexer.getLVal();
public boolean parse () ]b4_maybe_throws([b4_list2([b4_lex_throws], [b4_throws])])[
{
if (yylexer == null)
throw new NullPointerException("Null Lexer");
int status;
do {
int token = yylexer.yylex();
]b4_yystype[ lval = yylexer.getLVal();
]b4_locations_if([dnl
b4_location_type yyloc = new b4_location_type (yylexer.getStartPos (),
yylexer.getEndPos ());])[
]b4_locations_if([status = push_parse(token,lval,yyloc);],[
status = push_parse(token,lval);])[
} while (status == YYPUSH_MORE);
return (status == YYACCEPT);
b4_location_type yyloc = new b4_location_type (yylexer.getStartPos (),
yylexer.getEndPos ());])[
]b4_locations_if([status = push_parse(token,lval,yyloc);],[
status = push_parse(token,lval);])[
} while (status == YYPUSH_MORE);
return (status == YYACCEPT);
}
]])[
@@ -938,7 +919,7 @@ b4_both_if([[
new StringBuffer ("syntax error, unexpected ");
res.append (yytnamerr_ (yytname_[tok]));
int yyn = yypact_[yystate];
if (!yy_pact_value_is_default_ (yyn))
if (!yyPactValueIsDefault (yyn))
{
/* Start YYX at -YYN if negative to avoid negative
indexes in YYCHECK. In other words, skip the first
@@ -951,14 +932,14 @@ b4_both_if([[
int count = 0;
for (int x = yyxbegin; x < yyxend; ++x)
if (yycheck_[x + yyn] == x && x != yyterror_
&& !yy_table_value_is_error_ (yytable_[x + yyn]))
&& !yyTableValueIsError (yytable_[x + yyn]))
++count;
if (count < 5)
{
count = 0;
for (int x = yyxbegin; x < yyxend; ++x)
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 (yytnamerr_ (yytname_[x]));
@@ -976,7 +957,7 @@ b4_both_if([[
* Whether the given <code>yypact_</code> value indicates a defaulted state.
* @@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_;
}
@@ -986,7 +967,7 @@ b4_both_if([[
* value indicates a syntax error.
* @@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_;
}
@@ -1003,12 +984,13 @@ b4_both_if([[
First, the terminals, then, starting at \a yyntokens_, nonterminals. */
]b4_typed_parser_table_define([String], [tname], [b4_tname])[
]b4_parse_trace_if([[
]b4_integral_parser_table_define([rline], [b4_rline],
[[YYRLINE[YYN] -- Source line where rule number YYN was defined.]])[
// Report on the debug stream that the rule yyrule is going to be reduced.
private void yy_reduce_print (int yyrule, YYStack yystack)
private void yyReducePrint (int yyrule, YYStack yystack)
{
if (yydebug == 0)
return;
@@ -1021,23 +1003,30 @@ b4_both_if([[
/* The symbols being reduced. */
for (int yyi = 0; yyi < yynrhs; yyi++)
yy_symbol_print (" $" + (yyi + 1) + " =",
yystos_[yystack.stateAt(yynrhs - (yyi + 1))],
]b4_rhs_data(yynrhs, yyi + 1)b4_locations_if([,
b4_rhs_location(yynrhs, yyi + 1)])[);
}
yySymbolPrint (" $" + (yyi + 1) + " =",
yystos_[yystack.stateAt(yynrhs - (yyi + 1))],
]b4_rhs_data(yynrhs, yyi + 1)b4_locations_if([,
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. */
]b4_integral_parser_table_define([translate_table], [b4_translate])[
private static final ]b4_int_type_for([b4_translate])[ yytranslate_ (int t)
{
if (t >= 0 && t <= yyuser_token_number_max_)
]b4_api_token_raw_if(dnl
[[ {
return t;
}
]],
[[ {
if (t <= 0)
return Lexer.EOF;
else if (t <= yyuser_token_number_max_)
return yytranslate_table_[t];
else
return yyundef_token_;
}
]b4_integral_parser_table_define([translate_table], [b4_translate])[
]])[
private static final int yylast_ = ]b4_last[;
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 yyundef_token_ = ]b4_undef_token_number[;
]/* User implementation code. */
b4_percent_code_get[]dnl
/* User implementation code. */
]b4_percent_code_get[]dnl
}
+15 -17
View File
@@ -65,8 +65,8 @@ m4_define([b4_location_define],
public:]m4_ifdef([b4_location_constructors], [[
/// Construct a position.
explicit position (]b4_percent_define_get([[filename_type]])[* f = YY_NULLPTR,
unsigned l = ]b4_location_initial_line[u,
unsigned c = ]b4_location_initial_column[u)
int l = ]b4_location_initial_line[,
int c = ]b4_location_initial_column[)
: filename (f)
, line (l)
, column (c)
@@ -75,8 +75,8 @@ m4_define([b4_location_define],
]])[
/// Initialization.
void initialize (]b4_percent_define_get([[filename_type]])[* fn = YY_NULLPTR,
unsigned l = ]b4_location_initial_line[u,
unsigned c = ]b4_location_initial_column[u)
int l = ]b4_location_initial_line[,
int c = ]b4_location_initial_column[)
{
filename = fn;
line = l;
@@ -90,7 +90,7 @@ m4_define([b4_location_define],
{
if (count)
{
column = ]b4_location_initial_column[u;
column = ]b4_location_initial_column[;
line = add_ (line, count, ]b4_location_initial_line[);
}
}
@@ -105,16 +105,15 @@ m4_define([b4_location_define],
/// File name to which this position refers.
]b4_percent_define_get([[filename_type]])[* filename;
/// Current line number.
unsigned line;
int line;
/// Current column number.
unsigned column;
int column;
private:
/// 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,
static_cast<int> (lhs) + rhs));
return lhs + rhs < min ? min : lhs + rhs;
}
};
@@ -197,8 +196,8 @@ m4_define([b4_location_define],
/// Construct a 0-width location in \a f, \a l, \a c.
explicit location (]b4_percent_define_get([[filename_type]])[* f,
unsigned l = ]b4_location_initial_line[u,
unsigned c = ]b4_location_initial_column[u)
int l = ]b4_location_initial_line[,
int c = ]b4_location_initial_column[)
: begin (f, l, c)
, end (f, l, c)
{}
@@ -206,8 +205,8 @@ m4_define([b4_location_define],
])[
/// Initialization.
void initialize (]b4_percent_define_get([[filename_type]])[* f = YY_NULLPTR,
unsigned l = ]b4_location_initial_line[u,
unsigned c = ]b4_location_initial_column[u)
int l = ]b4_location_initial_line[,
int c = ]b4_location_initial_column[)
{
begin.initialize (f, l, c);
end = begin;
@@ -305,7 +304,7 @@ m4_define([b4_location_define],
std::basic_ostream<YYChar>&
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;
if (loc.end.filename
&& (!loc.begin.filename
@@ -327,7 +326,7 @@ m4_ifdef([b4_position_file], [[
// used to define is now defined in "]b4_location_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
// 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])[
# include <algorithm> // std::max
# include <iostream>
# include <string>
+18 -30
View File
@@ -35,6 +35,7 @@ m4_define([b4_stack_define],
typedef typename S::reverse_iterator iterator;
typedef typename S::const_reverse_iterator const_iterator;
typedef typename S::size_type size_type;
typedef typename std::ptrdiff_t index_type;
stack (size_type n = 200)
: seq_ (n)
@@ -43,37 +44,19 @@ m4_define([b4_stack_define],
/// Random access.
///
/// Index 0 returns the topmost element.
T&
operator[] (size_type i)
const T&
operator[] (index_type i) const
{
return seq_[size () - 1 - i];
return seq_[size_type (size () - 1 - i)];
}
/// Random access.
///
/// Index 0 returns the topmost element.
T&
operator[] (int i)
operator[] (index_type i)
{
return operator[] (size_type (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));
return seq_[size_type (size () - 1 - i)];
}
/// Steal the contents of \a t.
@@ -88,7 +71,7 @@ m4_define([b4_stack_define],
/// Pop elements from the stack.
void
pop (int n = 1) YY_NOEXCEPT
pop (std::ptrdiff_t n = 1) YY_NOEXCEPT
{
for (; 0 < n; --n)
seq_.pop_back ();
@@ -102,10 +85,15 @@ m4_define([b4_stack_define],
}
/// Number of elements on the stack.
size_type
index_type
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).
@@ -126,20 +114,20 @@ m4_define([b4_stack_define],
class slice
{
public:
slice (const stack& stack, int range)
slice (const stack& stack, index_type range)
: stack_ (stack)
, range_ (range)
{}
const T&
operator[] (int i) const
operator[] (index_type i) const
{
return stack_[range_ - i];
}
private:
const stack& stack_;
int range_;
index_type range_;
};
private:
@@ -157,7 +145,7 @@ m4_ifdef([b4_stack_file],
// used to define is now defined with the parser itself.
//
// 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.
]b4_output_end[
]])
+182 -190
View File
@@ -1,4 +1,4 @@
-*- C -*-
# -*- C -*-
# Yacc compatible skeleton for Bison
# 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
# 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])
## ---------------- ##
## Default values. ##
## ---------------- ##
# Stack parameters.
m4_define_default([b4_stack_depth_max], [10000])
m4_define_default([b4_stack_depth_init], [200])
## ------------------------ ##
## Pure/impure interfaces. ##
## ------------------------ ##
## ---------- ##
## api.pure. ##
## ---------- ##
b4_percent_define_default([[api.pure]], [[false]])
b4_percent_define_check_values([[[[api.pure]],
@@ -84,6 +44,51 @@ m4_define([b4_pure_if],
[2], [$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)
# --------------------------
# 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. ##
## ----------------- ##
@@ -199,7 +182,7 @@ m4_define([b4_declare_parser_state_variables], [b4_pure_if([[
/* Number of syntax errors so far. */
int yynerrs;
]])[
int yystate;
yy_state_fast_t yystate;
/* Number of tokens to shift before error messages enabled. */
int yyerrstatus;
@@ -212,9 +195,9 @@ m4_define([b4_declare_parser_state_variables], [b4_pure_if([[
to reallocate them elsewhere. */
/* The state stack. */
yytype_int16 yyssa[YYINITDEPTH];
yytype_int16 *yyss;
yytype_int16 *yyssp;
yy_state_t yyssa[YYINITDEPTH];
yy_state_t *yyss;
yy_state_t *yyssp;
/* The semantic value stack. */
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. */
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]])[@};
yytype_int16 *yyes;
YYSIZE_T yyes_capacity;]])])
yy_state_t yyesa@{]b4_percent_define_get([[parse.lac.es-capacity-initial]])[@};
yy_state_t *yyes;
YYPTRDIFF_T yyes_capacity;]])])
# _b4_declare_yyparse_push
@@ -386,28 +369,22 @@ m4_if(b4_api_prefix, [yy], [],
# undef short
#endif
#ifdef YYTYPE_UINT8
typedef YYTYPE_UINT8 yytype_uint8;
#else
typedef unsigned char yytype_uint8;
#endif
]b4_c99_int_type_define[
#ifdef YYTYPE_INT8
typedef YYTYPE_INT8 yytype_int8;
#else
typedef signed char yytype_int8;
#endif
#ifdef YYTYPE_UINT16
typedef YYTYPE_UINT16 yytype_uint16;
#else
typedef unsigned short yytype_uint16;
#endif
#ifdef YYTYPE_INT16
typedef YYTYPE_INT16 yytype_int16;
#else
typedef short yytype_int16;
#ifndef YYPTRDIFF_T
# if defined __PTRDIFF_TYPE__ && defined __PTRDIFF_MAX__
# define YYPTRDIFF_T __PTRDIFF_TYPE__
# define YYPTRDIFF_MAXIMUM __PTRDIFF_MAX__
# elif defined PTRDIFF_MAX
# ifndef ptrdiff_t
# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
# endif
# define YYPTRDIFF_T ptrdiff_t
# define YYPTRDIFF_MAXIMUM PTRDIFF_MAX
# else
# define YYPTRDIFF_T long
# define YYPTRDIFF_MAXIMUM LONG_MAX
# endif
#endif
#ifndef YYSIZE_T
@@ -415,7 +392,7 @@ typedef short yytype_int16;
# define YYSIZE_T __SIZE_TYPE__
# elif defined 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 */
# define YYSIZE_T size_t
# else
@@ -423,7 +400,16 @@ typedef short yytype_int16;
# 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_
# 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. */
union yyalloc
{
yytype_int16 yyss_alloc;
yy_state_t yyss_alloc;
YYSTYPE yyvs_alloc;]b4_locations_if([
YYLTYPE yyls_alloc;])[
};
/* 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
N elements. */
]b4_locations_if(
[# 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)],
[# define YYSTACK_BYTES(N) \
((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
((N) * (YYSIZEOF (yy_state_t) + YYSIZEOF (YYSTYPE)) \
+ YYSTACK_GAP_MAXIMUM)])[
# define YYCOPY_NEEDED 1
@@ -554,11 +541,11 @@ union yyalloc
# define YYSTACK_RELOCATE(Stack_alloc, Stack) \
do \
{ \
YYSIZE_T yynewbytes; \
YYPTRDIFF_T yynewbytes; \
YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
Stack = &yyptr->Stack_alloc; \
yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
yyptr += yynewbytes / sizeof (*yyptr); \
yynewbytes = yystacksize * YYSIZEOF (*Stack) + YYSTACK_GAP_MAXIMUM; \
yyptr += yynewbytes / YYSIZEOF (*yyptr); \
} \
while (0)
@@ -570,12 +557,12 @@ union yyalloc
# ifndef YYCOPY
# if defined __GNUC__ && 1 < __GNUC__
# define YYCOPY(Dst, Src, Count) \
__builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src)))
__builtin_memcpy (Dst, Src, (YYSIZE_T) (Count) * sizeof (*(Src)))
# else
# define YYCOPY(Dst, Src, Count) \
do \
{ \
YYSIZE_T yyi; \
YYPTRDIFF_T yyi; \
for (yyi = 0; yyi < (Count); yyi++) \
(Dst)[yyi] = (Src)[yyi]; \
} \
@@ -601,17 +588,20 @@ union yyalloc
#define YYUNDEFTOK ]b4_undef_token_number[
#define YYMAXUTOK ]b4_user_token_number_max[
/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM
as returned by yylex, with out-of-bounds checking. */
#define YYTRANSLATE(YYX) \
((unsigned) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
]b4_api_token_raw_if(dnl
[[#define YYTRANSLATE(YYX) (YYX)]],
[[#define YYTRANSLATE(YYX) \
(0 <= (YYX) && (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
as returned by yylex. */
static const ]b4_int_type_for([b4_translate])[ yytranslate[] =
{
]b4_translate[
};
};]])[
#if ]b4_api_PREFIX[DEBUG
]b4_integral_parser_table_define([rline], [b4_rline],
@@ -636,15 +626,15 @@ static const ]b4_int_type_for([b4_toknum])[ yytoknum[] =
};
# endif
#define YYPACT_NINF ]b4_pact_ninf[
#define YYPACT_NINF (]b4_pact_ninf[)
#define yypact_value_is_default(Yystate) \
]b4_table_value_equals([[pact]], [[Yystate]], [b4_pact_ninf])[
#define yypact_value_is_default(Yyn) \
]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) \
]b4_table_value_equals([[table]], [[Yytable_value]], [b4_table_ninf])[
#define yytable_value_is_error(Yyn) \
]b4_table_value_equals([[table]], [[Yyn]], [b4_table_ninf], [YYTABLE_NINF])[
]b4_parser_tables_define[
@@ -722,8 +712,8 @@ do { \
`------------------------------------------------------------------*/
]b4_function_define([yy_stack_print], [static void],
[[yytype_int16 *yybottom], [yybottom]],
[[yytype_int16 *yytop], [yytop]])[
[[yy_state_t *yybottom], [yybottom]],
[[yy_state_t *yytop], [yytop]])[
{
YYFPRINTF (stderr, "Stack now");
for (; yybottom <= yytop; yybottom++)
@@ -746,16 +736,16 @@ do { \
`------------------------------------------------*/
]b4_function_define([yy_reduce_print], [static void],
[[yytype_int16 *yyssp], [yyssp]],
[[yy_state_t *yyssp], [yyssp]],
[[YYSTYPE *yyvsp], [yyvsp]],
b4_locations_if([[[YYLTYPE *yylsp], [yylsp]],
])[[int yyrule], [yyrule]]m4_ifset([b4_parse_param], [,
b4_parse_param]))[
{
unsigned long yylno = yyrline[yyrule];
int yylno = yyrline[yyrule];
int yynrhs = yyr2[yyrule];
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);
/* The symbols being reduced. */
for (yyi = 0; yyi < yynrhs; yyi++)
@@ -814,22 +804,22 @@ int yydebug;
using YYSTACK_FREE. Return 0 if successful or if no reallocation is
required. Return 1 if memory is exhausted. */
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
char const *yydebug_prefix,
char const *yydebug_suffix,
#endif
yytype_int16 **yybottom,
yytype_int16 *yybottom_no_free,
yytype_int16 **yytop, yytype_int16 *yytop_empty)
yy_state_t **yybottom,
yy_state_t *yybottom_no_free,
yy_state_t **yytop, yy_state_t *yytop_empty)
{
YYSIZE_T yysize_old =
(YYSIZE_T) (*yytop == yytop_empty ? 0 : *yytop - *yybottom + 1);
YYSIZE_T yysize_new = yysize_old + yyadd;
YYPTRDIFF_T yysize_old =
*yytop == yytop_empty ? 0 : *yytop - *yybottom + 1;
YYPTRDIFF_T yysize_new = yysize_old + yyadd;
if (*yycapacity < yysize_new)
{
YYSIZE_T yyalloc = 2 * yysize_new;
yytype_int16 *yybottom_new;
YYPTRDIFF_T yyalloc = 2 * yysize_new;
yy_state_t *yybottom_new;
/* Use YYMAXDEPTH for maximum stack size given that the stack
should never need to grow larger than the main state stack
needs to grow without LAC. */
@@ -842,7 +832,8 @@ yy_lac_stack_realloc (YYSIZE_T *yycapacity, YYSIZE_T yyadd,
if (YYMAXDEPTH < yyalloc)
yyalloc = YYMAXDEPTH;
yybottom_new =
(yytype_int16*) YYSTACK_ALLOC (yyalloc * sizeof *yybottom_new);
(yy_state_t *) YYSTACK_ALLOC ((YYSIZE_T)
(yyalloc * YYSIZEOF (*yybottom_new)));
if (!yybottom_new)
{
YYDPRINTF ((stderr, "%srealloc failed%s", yydebug_prefix,
@@ -859,8 +850,8 @@ yy_lac_stack_realloc (YYSIZE_T *yycapacity, YYSIZE_T yyadd,
*yybottom = yybottom_new;
*yycapacity = yyalloc;]m4_if(b4_percent_define_get([[parse.lac.memory-trace]]),
[full], [[
YYDPRINTF ((stderr, "%srealloc to %lu%s", yydebug_prefix,
(unsigned long) yyalloc, yydebug_suffix));]])[
YYDPRINTF ((stderr, "%srealloc to %ld%s", yydebug_prefix,
(long) yyalloc, yydebug_suffix));]])[
}
return 0;
}
@@ -945,11 +936,11 @@ do { \
contents of either array, alter *YYES and *YYES_CAPACITY, and free
any old *YYES other than YYESA. */
static int
yy_lac (yytype_int16 *yyesa, yytype_int16 **yyes,
YYSIZE_T *yyes_capacity, yytype_int16 *yyssp, int yytoken)
yy_lac (yy_state_t *yyesa, yy_state_t **yyes,
YYPTRDIFF_T *yyes_capacity, yy_state_t *yyssp, int yytoken)
{
yytype_int16 *yyes_prev = yyssp;
yytype_int16 *yyesp = yyes_prev;
yy_state_t *yyes_prev = yyssp;
yy_state_t *yyesp = yyes_prev;
YYDPRINTF ((stderr, "LAC: checking lookahead %s:", yytname[yytoken]));
if (yytoken == YYUNDEFTOK)
{
@@ -986,11 +977,11 @@ yy_lac (yytype_int16 *yyesa, yytype_int16 **yyes,
yyrule = -yyrule;
}
{
YYSIZE_T yylen = yyr2[yyrule];
YYPTRDIFF_T yylen = yyr2[yyrule];
YYDPRINTF ((stderr, " R%d", yyrule - 1));
if (yyesp != yyes_prev)
{
YYSIZE_T yysize = (YYSIZE_T) (yyesp - *yyes + 1);
YYPTRDIFF_T yysize = yyesp - *yyes + 1;
if (yylen < yysize)
{
yyesp -= yylen;
@@ -1006,19 +997,18 @@ yy_lac (yytype_int16 *yyesa, yytype_int16 **yyes,
yyesp = yyes_prev -= yylen;
}
{
yytype_int16 yystate;
yy_state_fast_t yystate;
{
const int yylhs = yyr1[yyrule] - YYNTOKENS;
const int yyi = yypgoto[yylhs] + *yyesp;
yystate = ((yytype_int16)
(0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yyesp
? yytable[yyi]
: yydefgoto[yylhs]));
yystate = (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yyesp
? yytable[yyi]
: yydefgoto[yylhs]);
}
if (yyesp == yyes_prev)
{
yyesp = *yyes;
*yyesp = yystate;
*yyesp = (yy_state_t) yystate;
}
else
{
@@ -1031,9 +1021,9 @@ yy_lac (yytype_int16 *yyesa, yytype_int16 **yyes,
YYDPRINTF ((stderr, "\n"));
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
# if defined __GLIBC__ && defined _STRING_H
# define yystrlen strlen
# define yystrlen(S) ((YYPTRDIFF_T) strlen (S))
# else
/* Return the length of YYSTR. */
]b4_function_define([yystrlen], [static YYSIZE_T],
]b4_function_define([yystrlen], [static YYPTRDIFF_T],
[[const char *yystr], [yystr]])[
{
YYSIZE_T yylen;
YYPTRDIFF_T yylen;
for (yylen = 0; yystr[yylen]; yylen++)
continue;
return yylen;
@@ -1085,12 +1075,12 @@ yy_lac (yytype_int16 *yyesa, yytype_int16 **yyes,
backslash-backslash). YYSTR is taken from yytname. If YYRES is
null, do not copy; instead, return the length of what the result
would have been. */
static YYSIZE_T
static YYPTRDIFF_T
yytnamerr (char *yyres, const char *yystr)
{
if (*yystr == '"')
{
YYSIZE_T yyn = 0;
YYPTRDIFF_T yyn = 0;
char const *yyp = yystr;
for (;;)
@@ -1121,10 +1111,10 @@ yytnamerr (char *yyres, const char *yystr)
do_not_strip_quotes: ;
}
if (! yyres)
if (yyres)
return yystpcpy (yyres, yystr) - yyres;
else
return yystrlen (yystr);
return (YYSIZE_T) (yystpcpy (yyres, yystr) - yyres);
}
# 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
yy_lac returned 2]])[. */
static int
yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
]b4_lac_if([[yytype_int16 *yyesa, yytype_int16 **yyes,
YYSIZE_T *yyes_capacity, ]])[yytype_int16 *yyssp, int yytoken)
yysyntax_error (YYPTRDIFF_T *yymsg_alloc, char **yymsg,
]b4_lac_if([[yy_state_t *yyesa, yy_state_t **yyes,
YYPTRDIFF_T *yyes_capacity, ]])[yy_state_t *yyssp, int yytoken)
{
YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]);
YYSIZE_T yysize = yysize0;
YYPTRDIFF_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]);
YYPTRDIFF_T yysize = yysize0;
enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
/* Internationalized format string. */
const char *yyformat = YY_NULLPTR;
@@ -1188,15 +1178,8 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
YYDPRINTF ((stderr, "Constructing syntax error message\n"));]])[
yyarg[yycount++] = yytname[yytoken];
if (!yypact_value_is_default (yyn))
{]b4_lac_if([], [[
/* 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;]b4_lac_if([[
{]b4_lac_if([[
int yyx;
for (yyx = 0; yyx < YYNTOKENS; ++yyx)
if (yyx != YYTERROR && yyx != YYUNDEFTOK)
@@ -1209,6 +1192,14 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
if (yy_lac_status == 1)
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)
if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
@@ -1222,7 +1213,8 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
}
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)
yysize = yysize1;
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)
yysize = yysize1;
else
@@ -1434,7 +1426,7 @@ b4_function_define([[yyparse]], [[int]], b4_parse_param)[
/* Buffer for error messages, and its allocated size. */
char yymsgbuf[128];
char *yymsg = yymsgbuf;
YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
YYPTRDIFF_T yymsg_alloc = sizeof yymsgbuf;
#endif
#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([[
yyes = yyesa;
yyes_capacity = sizeof yyesa / sizeof *yyes;
yyes_capacity = ]b4_percent_define_get([[parse.lac.es-capacity-initial]])[;
if (YYMAXDEPTH < yyes_capacity)
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:
YYDPRINTF ((stderr, "Entering state %d\n", yystate));
YY_ASSERT (0 <= yystate && yystate < YYNSTATES);
*yyssp = (yytype_int16) yystate;
*yyssp = (yy_state_t) yystate;
if (yyss + yystacksize - 1 <= yyssp)
#if !defined yyoverflow && !defined YYSTACK_RELOCATE
@@ -1500,15 +1492,15 @@ yysetstate:
#else
{
/* 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
{
/* Give user a chance to reallocate the stack. Use copies of
these so that the &'s don't force the real ones into
memory. */
YYSTYPE *yyvs1 = yyvs;
yytype_int16 *yyss1 = yyss;]b4_locations_if([
yy_state_t *yyss1 = yyss;
YYSTYPE *yyvs1 = yyvs;]b4_locations_if([
YYLTYPE *yyls1 = yyls;])[
/* 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
be undefined if yyoverflow is a macro. */
yyoverflow (YY_("memory exhausted"),
&yyss1, yysize * sizeof (*yyssp),
&yyvs1, yysize * sizeof (*yyvsp),]b4_locations_if([
&yyls1, yysize * sizeof (*yylsp),])[
&yyss1, yysize * YYSIZEOF (*yyssp),
&yyvs1, yysize * YYSIZEOF (*yyvsp),]b4_locations_if([
&yyls1, yysize * YYSIZEOF (*yylsp),])[
&yystacksize);
yyss = yyss1;
yyvs = yyvs1;]b4_locations_if([
@@ -1533,9 +1525,10 @@ yysetstate:
yystacksize = YYMAXDEPTH;
{
yytype_int16 *yyss1 = yyss;
yy_state_t *yyss1 = yyss;
union yyalloc *yyptr =
(union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
(union yyalloc *) YYSTACK_ALLOC ((YYSIZE_T)
YYSTACK_BYTES (yystacksize));
if (! yyptr)
goto yyexhaustedlab;
YYSTACK_RELOCATE (yyss_alloc, yyss);
@@ -1551,8 +1544,8 @@ yysetstate:
yyvsp = yyvs + yysize - 1;]b4_locations_if([
yylsp = yyls + yysize - 1;])[
YYDPRINTF ((stderr, "Stack size increased to %lu\n",
(unsigned long) yystacksize));
YYDPRINTF ((stderr, "Stack size increased to %ld\n",
(long) yystacksize));
if (yyss + yystacksize - 1 <= yyssp)
YYABORT;
@@ -1642,16 +1635,15 @@ yyread_pushed_token:]])[
/* Shift the lookahead token. */
YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
/* Discard the shifted token. */
yychar = YYEMPTY;]b4_lac_if([[
YY_LAC_DISCARD ("shift");]])[
yystate = yyn;
YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
*++yyvsp = yylval;
YY_IGNORE_MAYBE_UNINITIALIZED_END]b4_locations_if([
*++yylsp = yylloc;])[
/* Discard the shifted token. */
yychar = YYEMPTY;]b4_lac_if([[
YY_LAC_DISCARD ("shift");]])[
goto yynewstate;
@@ -1766,7 +1758,7 @@ yyerrlab:
{
if (yymsg != yymsgbuf)
YYSTACK_FREE (yymsg);
yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
yymsg = (char *) YYSTACK_ALLOC ((YYSIZE_T) yymsg_alloc);
if (!yymsg)
{
yymsg = yymsgbuf;
+2
View File
@@ -31,3 +31,5 @@
/version.texi
/yacc.1
/relocatable.texi
/figs/*.eps
/figs/*.svg
+304 -223
View File
@@ -377,6 +377,13 @@ Invoking Bison
* Option Cross Key:: Alphabetical list of long options.
* 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
* C++ Parsers:: The interface to generate C++ parser classes
@@ -455,20 +462,17 @@ Copying This Manual
@unnumbered Introduction
@cindex introduction
@dfn{Bison} is a general-purpose parser generator that converts an
annotated context-free grammar into a deterministic LR or generalized
LR (GLR) parser employing LALR(1) parser tables. As an experimental
feature, Bison can also generate IELR(1) or canonical LR(1) parser
tables. Once you are proficient with Bison, you can use it to develop
a wide range of language parsers, from those used in simple desk
calculators to complex programming languages.
@dfn{Bison} is a general-purpose parser generator that converts an annotated
context-free grammar into a deterministic LR or generalized LR (GLR) parser
employing LALR(1), IELR(1) or canonical LR(1) parser tables. Once you are
proficient with Bison, you can use it to develop a wide range of language
parsers, from those used in simple desk calculators to complex programming
languages.
Bison is upward compatible with Yacc: all properly-written Yacc
grammars ought to work with Bison with no change. Anyone familiar
with Yacc should be able to use Bison with little trouble. You need
to be fluent in C or C++ programming in order to use Bison or to
understand this manual. Java is also supported as an experimental
feature.
Bison is upward compatible with Yacc: all properly-written Yacc grammars
ought to work with Bison with no change. Anyone familiar with Yacc should
be able to use Bison with little trouble. You need to be fluent in C, C++
or Java programming in order to use Bison or to understand this manual.
We begin with tutorial chapters that explain the basic concepts of
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
of lookahead. For historical reasons, Bison by default is limited by the
additional restrictions of LALR(1), which is hard to explain simply.
@xref{Mysterious Conflicts}, for more information on this. As an
experimental feature, you can escape these additional restrictions by
requesting IELR(1) or canonical LR(1) parser tables. @xref{LR Table
Construction}, to learn how.
@xref{Mysterious Conflicts}, for more information on this. You can escape
these additional restrictions by requesting IELR(1) or canonical LR(1)
parser tables. @xref{LR Table Construction}, to learn how.
@cindex GLR parsing
@cindex generalized LR (GLR) parsing
@@ -1280,8 +1283,7 @@ In addition to the @code{%dprec} and @code{%merge} directives,
GLR parsers
allow you to reject parses on the basis of arbitrary computations executed
in user code, without having Bison treat this rejection as an error
if there are alternative parses. (This feature is experimental and may
evolve. We welcome user feedback.) For example,
if there are alternative parses. For example,
@example
widget:
@@ -1445,13 +1447,13 @@ anything other than their usual meanings.
In some cases the Bison parser implementation file includes system
headers, and in those cases your code should respect the identifiers
reserved by those headers. On some non-GNU hosts, @code{<alloca.h>},
@code{<malloc.h>}, @code{<stddef.h>}, and @code{<stdlib.h>} are
included as needed to declare memory allocators and related types.
reserved by those headers. On some non-GNU hosts, @code{<limits.h>},
@code{<stddef.h>}, @code{<stdint.h>} (if available), and @code{<stdlib.h>}
are included to declare memory allocators and integer types and constants.
@code{<libintl.h>} is included if message translation is in use
(@pxref{Internationalization}). Other system headers may be included
if you define @code{YYDEBUG} to a nonzero value (@pxref{Tracing,
,Tracing Your Parser}).
if you define @code{YYDEBUG} (@pxref{Tracing, ,Tracing Your Parser}) or
@code{YYSTACK_USE_ALLOCA} (@pxref{Table of Symbols}) to a nonzero value.
@node Stages
@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
@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. */
@end group
@group
symrec *
@@ -2710,16 +2718,17 @@ operators in @code{yylex}.
@comment file: mfcalc.y: 3
@example
#include <ctype.h>
#include <stddef.h>
@group
int
yylex (void)
@{
int c;
int c = getchar ();
/* Ignore white space, get first nonwhite character. */
while ((c = getchar ()) == ' ' || c == '\t')
continue;
while (c == ' ' || c == '\t')
c = getchar ();
if (c == EOF)
return 0;
@@ -2746,23 +2755,18 @@ Bison generated a definition of @code{YYSTYPE} with a member named
/* Char starts an identifier => read the name. */
if (isalpha (c))
@{
/* Initially make the buffer long enough
for a 40-character symbol name. */
static size_t length = 40;
static ptrdiff_t bufsize = 0;
static char *symbuf = 0;
@end group
if (!symbuf)
symbuf = malloc (length + 1);
int i = 0;
ptrdiff_t i = 0;
do
@group
@{
/* If buffer is full, make it bigger. */
if (i == length)
if (bufsize <= i)
@{
length *= 2;
symbuf = realloc (symbuf, length + 1);
bufsize = 2 * bufsize + 40;
symbuf = realloc (symbuf, bufsize);
@}
/* Add this character to the buffer. */
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
@samp{$[name.suffix]} must be used.
The named references feature is experimental. More user feedback will help
to stabilize it.
@node Declarations
@section Bison Declarations
@cindex declarations, Bison
@@ -5247,7 +5248,6 @@ Decl, , Freeing Discarded Symbols}).
@deffn {Directive} %printer @{ @var{code} @} @var{symbols}
@findex %printer
@vindex yyo
@vindex yyoutput
@c This is the same text as for %destructor.
Invoke the braced @var{code} whenever the parser displays one of the
@var{symbols}. Within @var{code}, @code{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
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
@@ -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).
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
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 Default Value: @code{yy}
@item Default Value: @code{YY} for Java, @code{yy} otherwise.
@item History: introduced in Bison 2.6
@end itemize
@@ -6213,6 +6213,42 @@ introduced in Bison 3.0
@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
@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 Purpose: Specify the kind of states that are permitted to
contain default reductions. @xref{Default Reductions}. (The ability to
specify where default reductions should be used is experimental. More user
feedback will help to stabilize it.)
contain default reductions. @xref{Default Reductions}.
@item Accepted Values: @code{most}, @code{consistent}, @code{accepting}
@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
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
@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
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
details. (Bison's IELR(1) and canonical LR(1) implementations are
experimental. More user feedback will help to stabilize them.)
details.
If you instead wish to work around LALR(1)'s limitations, you
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.
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
* LR Table Construction:: Choose a different construction algorithm.
* Default Reductions:: Disable default reductions.
@@ -8669,9 +8699,6 @@ The accepted values of @var{where} are:
@item @code{consistent}
@item @code{accepting} (default for canonical LR)
@end itemize
(The ability to specify where default reductions are permitted is
experimental. More user feedback will help to stabilize it.)
@end deffn
@node LAC
@@ -8707,9 +8734,7 @@ Enable LAC to improve syntax error handling.
@item @code{none} (default)
@item @code{full}
@end itemize
(This feature is experimental. More user feedback will help to stabilize
it. Moreover, it is currently only available for deterministic parsers in
C.)
This feature is currently only available for deterministic parsers in C and C++.
@end deffn
Conceptually, the LAC mechanism is straight-forward. Whenever the parser
@@ -9983,7 +10008,7 @@ compatibility with previous versions of Bison.
@findex %define parse.trace
Add the @samp{%define parse.trace} directive (@pxref{%define
Summary,,parse.trace}), or pass the @option{-Dparse.trace} option
(@pxref{Bison Options}). This is a Bison extension, which is especially
(@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
portability matter to you, this is the preferred solution.
@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{=}.
Here is a list of options that can be used with Bison, alphabetized by
short option. It is followed by a cross key alphabetized by long
option.
Here is a list of options that can be used with Bison. It is followed by a
cross key alphabetized by long 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'.
@noindent
Operations modes:
@table @option
@item -h
@itemx --help
@@ -10364,29 +10398,140 @@ exp:;
See the documentation of @option{--feature=fixit} below for more details.
@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:
@item -f [@var{feature}]
@itemx --feature[=@var{feature}]
Activate miscellaneous @var{feature}s. @var{Feature} can be one of:
@table @code
@item caret
@itemx diagnostics-show-caret
Show caret errors, in a manner similar to GCC's
@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
#! /bin/sh
bison -y "$@@"
%type <ival> exp
%%
exp: exp '+' exp @{ $exp = $1 + $2; @};
@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.
When invoked with @option{-fcaret} (or nothing), Bison will report:
@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}]
@itemx --warnings[=@var{category}]
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
itself won't be disabled, or enabled, by this option.
@item -f [@var{feature}]
@itemx --feature[=@var{feature}]
Activate miscellaneous @var{feature}. @var{feature} can be one of:
@item --color
Equivalent to @option{--color=always}.
@item --color=@var{when}
Control whether diagnostics are colorized, depending on @var{when}:
@table @code
@item caret
@itemx diagnostics-show-caret
Show caret errors, in a manner similar to GCC's
@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}:
@item always
@itemx yes
Enable colorized diagnostics.
@example
%type <ival> exp
%%
exp: exp '+' exp @{ $exp = $1 + $2; @};
@end example
@item never
@itemx no
Disable colorized diagnostics.
When invoked with @option{-fcaret} (or nothing), Bison will report:
@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
@item auto @r{(default)}
@itemx tty
Diagnostics will be colorized if the output device is a tty, i.e. when the
output goes directly to a text screen or terminal emulator window.
@end table
@noindent
Tuning the parser:
@item --style=@var{file}
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
@item -t
@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 -F @var{name}[=@var{value}]
@itemx --force-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
for the same @var{name} as follows:
Each of these is equivalent to @samp{%define @var{name} @var{value}}
(@pxref{%define Summary}). Note that the delimiters are part of
@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
@item
@@ -10751,11 +10805,37 @@ This is similar to how most shells resolve commands.
@item -k
@itemx --token-table
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
@noindent
Adjust the output:
@node Output Files
@subsection Output Files
Options controlling the output.
@c Please, keep this ordered as in 'bison --help'.
@table @option
@item --defines[=@var{file}]
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
@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
not reclaimed when the @code{position} is destroyed: memory managed must be
handled elsewhere.
@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.
@end deftypemethod
@@ -11414,7 +11494,7 @@ change it to @samp{@var{type}*} using @samp{%define filename_type
"@var{type}"}.
@end deftypeivar
@deftypeivar {position} {unsigned} line
@deftypeivar {position} {int} line
The line, starting at 1.
@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.
@end deftypemethod
@deftypeivar {position} {unsigned} column
@deftypeivar {position} {int} column
The column, starting at 1.
@end deftypeivar
@@ -11458,11 +11538,11 @@ Create a @code{Location} from the endpoints of the range.
@end deftypeop
@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.
@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.
@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,
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
[0-9]+ @{
@@ -14129,7 +14209,8 @@ is recovering from a syntax error, and 0 otherwise.
@deffn {Macro} YYSTACK_USE_ALLOCA
Macro used to control the use of @code{alloca} when the
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
reserved for future Bison extensions. If not defined,
@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: YYEMPTY YYEOF YYRECOVERING yyclearin GE def UMINUS maybeword loc
@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: ypp yxx itemx tex leaderfill Troubleshouting sqrt Graphviz
@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: setcolor rgbError colorError rgbNotice colorNotice derror
@c LocalWords: colorOff maincolor inlineraw darkviolet darkcyan dwarning
@c LocalWords: dnotice copyable
@c LocalWords: dnotice copyable stdint ptrdiff bufsize
@c Local Variables:
@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;
const int stage = 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)
return parser::make_TEXT (make_string_uptr ("I have numbers for you."), std::move (loc));
else if (stage < max)
+1 -1
View File
@@ -117,7 +117,7 @@ namespace yy
static int count = 0;
const int stage = count;
++count;
parser::location_type loc (NULLPTR, unsigned (stage + 1), unsigned (stage + 1));
parser::location_type loc (NULLPTR, stage + 1, stage + 1);
switch (stage)
{
case 0:
+3 -3
View File
@@ -15,9 +15,9 @@
lexcalcdir = $(docdir)/%D%
## ------ ##
## Calc. ##
## ------ ##
## --------- ##
## LexCalc. ##
## --------- ##
if FLEX_WORKS
check_PROGRAMS += %D%/lexcalc
+1
View File
@@ -4,6 +4,7 @@
%option nodefault noinput nounput noyywrap
%{
#include <errno.h> /* errno, ERANGE */
#include <limits.h> /* INT_MIN */
#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%
## ------ ##
## Calc. ##
## ------ ##
## --------- ##
## RecCalc. ##
## --------- ##
if FLEX_WORKS
check_PROGRAMS += %D%/reccalc
@@ -36,16 +36,40 @@ endif FLEX_WORKS
# additional dependency.
DASH = -
%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
@test -f $@ || rm -f %D%/scan.stamp
@test -f $@ || $(MAKE) $(AM_MAKEFLAGS) %D%/scan.stamp
## Recover from the removal of $@
@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
$(AM_V_LEX)rm -f $@ $@.tmp
$(AM_V_at)$(MKDIR_P) %D%
$(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 $@
+1 -8
View File
@@ -3,11 +3,6 @@
%define api.parser.class {Calc}
%define parse.error verbose
%code imports {
import std.ascii;
import std.stdio;
}
%union {
int ival;
}
@@ -102,16 +97,14 @@ class CalcLexer(R) : Lexer
// 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)
if (input.front.isNumber)
{
import std.conv : parse;
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.resetSyntax ();
st.eolIsSignificant (true);
st.whitespaceChars (9, 9);
st.whitespaceChars (32, 32);
st.wordChars (48, 57);
st.whitespaceChars ('\t', '\t');
st.whitespaceChars (' ', ' ');
st.wordChars ('0', '9');
}
+1 -1
Submodule gnulib updated: 672663aca3...56ca994d47
+2
View File
@@ -15,4 +15,6 @@
/[email protected]
/insert-header.sin
/quot.sed
/remove-potcdate.sed
/remove-potcdate.sin
/stamp-po
+30 -7
View File
@@ -16,6 +16,7 @@
/argmatch.c
/argmatch.h
/asnprintf.c
/assure.h
/basename-lgpl.c
/basename.c
/binary-io.c
@@ -38,6 +39,7 @@
/canonicalize-lgpl.c
/careadlinkat.c
/careadlinkat.h
/cdefs.h
/charset.alias
/cloexec.c
/cloexec.h
@@ -51,6 +53,7 @@
/config.h
/config.in.h
/configmake.h
/diffseq.h
/dirname-lgpl.c
/dirname.c
/dirname.h
@@ -89,9 +92,13 @@
/fseterr.c
/fseterr.h
/fstat.c
/fstrcmp.c
/fstrcmp.h
/fsync.c
/getdtablesize.c
/gethrxtime.c
/gethrxtime.h
/getopt-cdefs.h
/getopt-cdefs.in.h
/getopt-core.h
/getopt-ext.h
@@ -129,8 +136,10 @@
/isnanf.c
/isnanl-nolibm.h
/isnanl.c
/iswblank.c
/itold.c
/ldexpl.c
/libc-config.h
/limits.h
/limits.in.h
/localcharset.c
@@ -144,6 +153,10 @@
/math.c
/math.h
/math.in.h
/mbchar.c
/mbchar.h
/mbfile.c
/mbfile.h
/mbrtowc.c
/mbsinit.c
/mbswidth.c
@@ -189,6 +202,9 @@
/relocatable.c
/relocatable.h
/relocwrapper.c
/rename.c
/rmdir.c
/same-inode.h
/sched.h
/sched.in.h
/setenv.c
@@ -264,6 +280,8 @@
/sys_types.in.h
/sys_wait.in.h
/sysexits.in.h
/textstyle.h
/textstyle.in.h
/time.h
/time.in.h
/timespec.c
@@ -300,10 +318,22 @@
/wctype.h
/wctype.in.h
/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-oversized.h
/xalloc.h
/xconcat-filename.c
/xhash.c
/xmalloc.c
/xmemdup0.c
/xmemdup0.h
@@ -315,10 +345,3 @@
/xstrndup.h
/xtime.c
/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.h
/threadlib.c
/tls.c
/tls.h
+8 -18
View File
@@ -1,5 +1,6 @@
/*~
/00gnulib.m4
/__inline.m4
/absolute-header.m4
/alloca.m4
/asm-underscore.m4
@@ -7,9 +8,7 @@
/calloc.m4
/canonicalize.m4
/clock_time.m4
/close-stream.m4
/close.m4
/closeout.m4
/codeset.m4
/config-h.m4
/configmake.m4
@@ -44,23 +43,14 @@
/getopt.m4
/getprogname.m4
/getrusage.m4
/gettext.m4
/gettime.m4
/gettimeofday.m4
/glibc2.m4
/glibc21.m4
/gnulib-cache.m4
/gnulib-common.m4
/gnulib-comp.m4
/gnulib-tool.m4
/host-cpu-c-abi.m4
/iconv.m4
/include_next.m4
/intdiv0.m4
/intl.m4
/intldir.m4
/intlmacosx.m4
/intmax.m4
/intmax_t.m4
/inttypes-pri.m4
/inttypes.m4
@@ -69,10 +59,12 @@
/isnand.m4
/isnanf.m4
/isnanl.m4
/iswblank.m4
/javacomp.m4
/javaexec.m4
/jm-winsz1.m4
/jm-winsz2.m4
/largefile.m4
/lcmessage.m4
/ldexp.m4
/ldexpl.m4
/lib-ld.m4
@@ -93,6 +85,8 @@
/malloc.m4
/malloca.m4
/math_h.m4
/mbchar.m4
/mbfile.m4
/mbrtowc.m4
/mbsinit.m4
/mbstate_t.m4
@@ -104,25 +98,22 @@
/msvc-inval.m4
/msvc-nothrow.m4
/multiarch.m4
/nls.m4
/nocrash.m4
/non-recursive-gnulib-prefix-hack.m4
/obstack-printf.m4
/obstack.m4
/off_t.m4
/open-cloexec.m4
/open-slash.m4
/open.m4
/pathmax.m4
/perror.m4
/pipe2.m4
/po.m4
/posix_spawn.m4
/printf-frexp.m4
/printf-frexpl.m4
/printf-posix-rpl.m4
/printf-posix.m4
/printf.m4
/progtest.m4
/pthread_rwlock_rdlock.m4
/quote.m4
/quotearg.m4
@@ -177,14 +168,13 @@
/threadlib.m4
/time_h.m4
/timespec.m4
/uintmax_t.m4
/tls.m4
/unistd-safer.m4
/unistd_h.m4
/unlink.m4
/unlocked-io.m4
/vasnprintf.m4
/vfprintf-posix.m4
/visibility.m4
/vsnprintf-posix.m4
/vsnprintf.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], [:])
if test "x$LEX" != "x:"; then
_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
@@ -37,8 +40,6 @@ else
ac_cv_prog_lex_is_flex=no
fi
])
AC_SUBST([LEX_IS_FLEX],
[`test "$ac_cv_prog_lex_is_flex" = yes && echo true || echo false`])dnl
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]
- 2]))
{
unsigned rulei;
int rulei;
for (rulei = s->items[self_item];
!item_number_is_rule_number (ritem[rulei]);
++rulei)
+1 -1
View File
@@ -25,7 +25,7 @@
# include "InadequacyList.h"
# include "state.h"
typedef unsigned AnnotationIndex;
typedef int AnnotationIndex;
/**
* 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 <intprops.h>
ContributionIndex const ContributionIndex__none = -1;
ContributionIndex const ContributionIndex__error_action = -2;
@@ -31,8 +33,11 @@ InadequacyList__new_conflict (state *manifesting_state, symbol *token,
InadequacyListNodeCount *node_count)
{
InadequacyList *result = xmalloc (sizeof *result);
result->id = (*node_count)++;
aver (*node_count != 0);
result->id = *node_count;
IGNORE_TYPE_LIMITS_BEGIN
if (INT_ADD_WRAPV (*node_count, 1, node_count))
aver (false);
IGNORE_TYPE_LIMITS_END
result->next = NULL;
result->manifestingState = manifesting_state;
result->contributionCount = bitset_count (actions);
+1 -4
View File
@@ -27,11 +27,8 @@
/**
* 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
+1 -1
View File
@@ -170,7 +170,7 @@ set_fderives (void)
void
closure_new (unsigned n)
closure_new (int n)
{
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
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
+75 -55
View File
@@ -107,46 +107,59 @@ flush (FILE *out)
| --warnings's handling. |
`------------------------*/
static const char * const warnings_args[] =
ARGMATCH_DEFINE_GROUP (warning, warnings)
static const argmatch_warning_doc argmatch_warning_docs[] =
{
"none",
"midrule-values",
"yacc",
"conflicts-sr",
"conflicts-rr",
"deprecated",
"empty-rule",
"precedence",
"other",
"all",
"error",
"everything",
0
{ "conflicts-sr", N_("S/R conflicts (enabled by default)") },
{ "conflicts-rr", N_("R/R conflicts (enabled by default)") },
{ "deprecated", N_("obsolete constructs") },
{ "empty-rule", N_("empty rules without %empty") },
{ "midrule-values", N_("unset or unused midrule values") },
{ "precedence", N_("useless precedence and associativity") },
{ "yacc", N_("incompatibilities with POSIX Yacc") },
{ "other", N_("all other warnings (enabled by default)") },
{ "all", N_("all the warnings except 'yacc'") },
{ "no-CATEGORY", N_("turn off warnings in CATEGORY") },
{ "none", N_("turn off all the warnings") },
{ "error[=CATEGORY]", N_("treat warnings as errors") },
{ NULL, NULL }
};
static const warnings warnings_types[] =
static const argmatch_warning_arg argmatch_warning_args[] =
{
Wnone,
Wmidrule_values,
Wyacc,
Wconflicts_sr,
Wconflicts_rr,
Wdeprecated,
Wempty_rule,
Wprecedence,
Wother,
Wall,
Werror,
Weverything
{ "none", Wnone },
{ "midrule-values", Wmidrule_values },
{ "yacc", Wyacc },
{ "conflicts-sr", Wconflicts_sr },
{ "conflicts-rr", Wconflicts_rr },
{ "deprecated", Wdeprecated },
{ "empty-rule", Wempty_rule },
{ "precedence", Wprecedence },
{ "other", Wother },
{ "all", Wall },
{ "everything", 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
warning_argmatch (char const *arg, size_t no, size_t err)
{
int value = XARGMATCH ("--warning", arg + no + err,
warnings_args, warnings_types);
int value = *argmatch_warning_value ("--warning", arg + no + err);
/* -Wnone == -Wno-everything, and -Wno-none == -Weverything. */
if (!value)
@@ -185,7 +198,14 @@ warning_argmatch (char const *arg, size_t no, size_t err)
void
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, ","))
if (STREQ (args, "error"))
warnings_are_errors = true;
@@ -201,8 +221,6 @@ warnings_argmatch (char *args)
warning_argmatch (args, no, err);
}
else
warning_argmatch ("all", 0, 0);
}
static const char*
@@ -290,6 +308,8 @@ complain_init_color (void)
void
complain_init (void)
{
caret_init ();
warnings warnings_default =
Wconflicts_sr | Wconflicts_rr | Wdeprecated | Wother;
@@ -363,16 +383,17 @@ warning_is_enabled (warnings flags)
static void
warnings_print_categories (warnings warn_flags, FILE *out)
{
for (size_t i = 0; warnings_args[i]; ++i)
if (warn_flags & warnings_types[i])
for (int wbit = 0; wbit < warnings_size; ++wbit)
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);
fputs (" [", out);
begin_use_class (style, out);
fprintf (out, "-W%s%s",
s == severity_error ? "error=" : "",
warnings_args[i]);
argmatch_warning_argument (&w));
end_use_class (style, out);
fputc (']', out);
/* Display only the first match, the second is "-Wall". */
@@ -396,15 +417,15 @@ warnings_print_categories (warnings warn_flags, FILE *out)
*/
static
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)
{
unsigned pos = 0;
int pos = 0;
if (loc)
pos += location_print (*loc, stderr);
else
pos += fprintf (stderr, "%s", current_file ? current_file : program_name);
pos += fprintf (stderr, "%s", grammar_file ? grammar_file : program_name);
pos += fprintf (stderr, ": ");
if (indent)
@@ -449,7 +470,7 @@ error_message (const location *loc, unsigned *indent, warnings flags,
/** Raise a complaint (fatal error, error or just warning). */
static void
complains (const location *loc, unsigned *indent, warnings flags,
complains (const location *loc, int *indent, warnings flags,
const char *message, va_list args)
{
severity s = warning_severity (flags);
@@ -477,7 +498,7 @@ complain (location const *loc, warnings flags, const char *message, ...)
}
void
complain_indent (location const *loc, warnings flags, unsigned *indent,
complain_indent (location const *loc, warnings flags, int *indent,
const char *message, ...)
{
va_list args;
@@ -487,7 +508,7 @@ complain_indent (location const *loc, warnings flags, unsigned *indent,
}
void
complain_args (location const *loc, warnings w, unsigned *indent,
complain_args (location const *loc, warnings w, int *indent,
int argc, char *argv[])
{
switch (argc)
@@ -525,24 +546,23 @@ bison_directive (location const *loc, char const *directive)
void
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))
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
duplicate_directive (char const *directive,
location first, location second)
{
unsigned i = 0;
int i = 0;
if (feature_flag & feature_caret)
complain_indent (&second, Wother, &i, _("duplicate directive"));
else
@@ -556,7 +576,7 @@ void
duplicate_rule_directive (char const *directive,
location first, location second)
{
unsigned i = 0;
int i = 0;
complain_indent (&second, complaint, &i,
_("only one %s allowed per rule"), directive);
i += SUB_INDENT;
+15 -15
View File
@@ -45,14 +45,14 @@ void flush (FILE *out);
/** The bits assigned to each warning type. */
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_conflicts_sr, /**< S/R conflicts. */
warning_conflicts_rr, /**< R/R conflicts. */
warning_empty_rule, /**< Implicitly empty rules. */
warning_deprecated, /**< Obsolete constructs. */
warning_precedence, /**< Useless precedence and associativity. */
warning_other, /**< All other warnings. */
warnings_size /**< The number of warnings. Must be last. */
} warning_bit;
@@ -60,6 +60,8 @@ typedef enum
/** Whether -Werror was set. */
extern bool warnings_are_errors;
void warning_usage (FILE *out);
/** Decode a single argument from -W.
*
* \param arg the subarguments to decode.
@@ -100,16 +102,14 @@ typedef enum
{
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_sr = 1 << warning_conflicts_sr,
Wdeprecated = 1 << warning_deprecated,
Wempty_rule = 1 << warning_empty_rule,
Wprecedence = 1 << warning_precedence,
Wmidrule_values = 1 << warning_midrule_values,
Wother = 1 << warning_other,
Werror = 1 << 10, /** This bit is no longer used. */
Wprecedence = 1 << warning_precedence,
Wyacc = 1 << warning_yacc,
complaint = 1 << 11, /**< All complaints. */
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)));
/** 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[]);
/** 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, ...)
__attribute__ ((__format__ (__printf__, 4, 5)));
+29 -25
View File
@@ -38,7 +38,10 @@
/* -1 stands for not specified. */
int expected_sr_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_xml_obstack;
@@ -73,8 +76,9 @@ log_resolution (rule *r, symbol_number token,
{
case shift_resolution:
case right_resolution:
obstack_sgrow (&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"),
r->number,
symbols[token]->tag);
@@ -82,16 +86,18 @@ log_resolution (rule *r, symbol_number token,
case reduce_resolution:
case left_resolution:
obstack_sgrow (&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"),
r->number,
symbols[token]->tag);
break;
case nonassoc_resolution:
obstack_sgrow (&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"),
r->number,
symbols[token]->tag);
@@ -376,7 +382,7 @@ set_conflicts (state *s, symbol **errors)
for (int i = 0; i < reds->num; ++i)
{
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]);
}
}
@@ -428,7 +434,7 @@ conflicts_update_state_numbers (state_number old_to_new[],
`---------------------------------------------*/
static size_t
count_state_sr_conflicts (state *s)
count_state_sr_conflicts (const state *s)
{
transitions *trans = s->transitions;
reductions *reds = s->reductions;
@@ -476,7 +482,7 @@ count_sr_conflicts (void)
`-----------------------------------------------------------------*/
static size_t
count_state_rr_conflicts (state *s)
count_state_rr_conflicts (const state *s)
{
reductions *reds = s->reductions;
size_t res = 0;
@@ -588,24 +594,22 @@ conflicts_output (FILE *out)
{
bool printed_sth = false;
for (state_number i = 0; i < nstates; ++i)
{
state *s = states[i];
if (conflicts[i])
{
int src = count_state_sr_conflicts (s);
int rrc = count_state_rr_conflicts (s);
fprintf (out, _("State %d "), i);
if (src && rrc)
fprintf (out,
_("conflicts: %d shift/reduce, %d reduce/reduce\n"),
src, rrc);
else if (src)
fprintf (out, _("conflicts: %d shift/reduce\n"), src);
else if (rrc)
fprintf (out, _("conflicts: %d reduce/reduce\n"), rrc);
printed_sth = true;
}
}
if (conflicts[i])
{
const state *s = states[i];
int src = count_state_sr_conflicts (s);
int rrc = count_state_rr_conflicts (s);
fprintf (out, _("State %d "), i);
if (src && rrc)
fprintf (out,
_("conflicts: %d shift/reduce, %d reduce/reduce\n"),
src, rrc);
else if (src)
fprintf (out, _("conflicts: %d shift/reduce\n"), src);
else if (rrc)
fprintf (out, _("conflicts: %d reduce/reduce\n"), rrc);
printed_sth = true;
}
if (printed_sth)
fputs ("\n\n", out);
}
+7 -6
View File
@@ -40,11 +40,9 @@ rule ***derives;
static void
print_derives (void)
{
int i;
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);
for (rule **rp = derives[i - ntokens]; *rp; ++rp)
@@ -88,7 +86,7 @@ derives_compute (void)
/* Q is the storage for DERIVES[...] (DERIVES[0] = 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];
derives[i - ntokens] = q;
@@ -111,6 +109,9 @@ derives_compute (void)
void
derives_free (void)
{
free (derives[0]);
free (derives);
if (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;
uniqstr grammar_file = NULL;
uniqstr current_file = NULL;
/* If --output=dir/foo.c was specified,
DIR_PREFIX is 'dir/' and ALL_BUT_EXT and ALL_BUT_TAB_EXT are 'dir/foo'.
-3
View File
@@ -58,9 +58,6 @@ extern char *dir_prefix;
and therefore GCC warns about a name clash. */
extern uniqstr grammar_file;
/* The current file name. Might change with #line. */
extern uniqstr current_file;
/* The computed base for output file names. */
extern char *all_but_ext;
+1 -1
View File
@@ -91,7 +91,7 @@ fixits_register (location const *loc, char const* fix)
true);
fixit *f = fixit_new (loc, fix);
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);
}
+263 -211
View File
@@ -68,28 +68,28 @@ const char *skeleton = NULL;
int language_prio = default_prio;
struct bison_language const *language = &valid_languages[0];
typedef int* (xargmatch_fn) (const char *context, const char *arg);
/** Decode an option's key.
*
* \param opt option being decoded.
* \param keys array of valid subarguments.
* \param values array of corresponding (int) values.
* \param all the all value.
* \param flags the flags to update
* \param arg the subarguments to decode.
* If null, then activate all the flags.
* \param no length of the potential "no-" prefix.
* Can be 0 or 3. If 3, negate the action of the subargument.
* \param opt option being decoded.
* \param xargmatch matching function.
* \param all the value of the argument 'all'.
* \param flags the flags to update
* \param arg the subarguments to decode.
* If null, then activate all the flags.
* \param no length of the potential "no-" prefix.
* Can be 0 or 3. If 3, negate the action of the subargument.
*
* If VALUE != 0 then KEY sets flags and no-KEY clears them.
* If VALUE == 0 then KEY clears all flags from \c all and no-KEY sets all
* flags from \c all. Thus no-none = all and no-all = none.
*/
static void
flag_argmatch (const char *opt,
const char *const keys[], const int values[],
flag_argmatch (const char *opt, xargmatch_fn xargmatch,
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. */
if (!value)
@@ -104,30 +104,38 @@ flag_argmatch (const char *opt,
*flags |= value;
}
typedef void (usage_fn) (FILE *out);
/** Decode an option's set of keys.
*
* \param opt option being decoded (e.g., --report).
* \param keys array of valid subarguments.
* \param values array of corresponding (int) values.
* \param all the all value.
* \param flags the flags to update
* \param args comma separated list of effective subarguments to decode.
* If 0, then activate all the flags.
* \param opt option being decoded (e.g., --report).
* \param xargmatch matching function.
* \param usage function that implement --help for this option.
* \param all the value of the argument 'all'.
* \param flags the flags to update
* \param args comma separated list of effective subarguments to decode.
* If 0, then activate all the flags.
*/
static void
flags_argmatch (const char *opt,
const char * const keys[], const int values[],
xargmatch_fn xargmatch,
usage_fn usage,
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, ","))
{
size_t no = STRPREFIX_LIT ("no-", args) ? 3 : 0;
flag_argmatch (opt, keys,
values, all, flags, args, no);
flag_argmatch (opt, xargmatch,
all, flags, args, no);
}
else
*flags |= all;
}
@@ -142,116 +150,188 @@ flags_argmatch (const char *opt,
* \arg FlagName_flag the flag to update.
*/
#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)
/*---------------------.
| --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. |
`----------------------*/
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
that argmatch_valid be more readable. */
"none",
"state", "states",
"itemset", "itemsets",
"lookahead", "lookaheads", "look-ahead",
"solved",
"all",
0
{ "states", N_("describe the states") },
{ "itemsets", N_("complete the core item sets with their closure") },
{ "lookaheads", N_("explicitly associate lookahead tokens to items") },
{ "solved", N_("describe shift/reduce conflicts solving") },
{ "all", N_("include all the above information") },
{ "none", N_("disable the report") },
{ NULL, NULL },
};
static const int report_types[] =
static const argmatch_report_arg argmatch_report_args[] =
{
report_none,
report_states, report_states,
report_states | report_itemsets, report_states | report_itemsets,
report_states | report_lookahead_tokens,
report_states | report_lookahead_tokens,
report_states | report_lookahead_tokens,
report_states | report_solved_conflicts,
report_all
{ "none", report_none },
{ "states", report_states },
{ "itemsets", report_states | report_itemsets },
{ "lookaheads", report_states | report_lookahead_tokens },
{ "solved", report_states | report_solved_conflicts },
{ "all", report_all },
{ NULL, report_none },
};
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. |
`---------------------*/
static const char * const trace_args[] =
ARGMATCH_DEFINE_GROUP (trace, enum trace)
static const argmatch_trace_doc argmatch_trace_docs[] =
{
"none - no traces",
"locations - full display of the locations",
"scan - grammar scanner traces",
"parse - grammar parser traces",
"automaton - construction of the automaton",
"bitsets - use of bitsets",
"closure - input/output of closure",
"grammar - reading, reducing the grammar",
"resource - memory consumption (where available)",
"sets - grammar sets: firsts, nullable etc.",
"muscles - m4 definitions passed to the skeleton",
"tools - m4 invocation",
"m4 - m4 traces",
"skeleton - skeleton postprocessing",
"time - time consumption",
"ielr - IELR conversion",
"all - all of the above",
0
/* Meant for developers only, don't translate them. */
{ "none", "no traces" },
{ "locations", "full display of the locations" },
{ "scan", "grammar scanner traces" },
{ "parse", "grammar parser traces" },
{ "automaton", "construction of the automaton" },
{ "bitsets", "use of bitsets" },
{ "closure", "input/output of closure" },
{ "grammar", "reading, reducing the grammar" },
{ "resource", "memory consumption (where available)" },
{ "sets", "grammar sets: firsts, nullable etc." },
{ "muscles", "m4 definitions passed to the skeleton" },
{ "tools", "m4 invocation" },
{ "m4", "m4 traces" },
{ "skeleton", "skeleton postprocessing" },
{ "time", "time consumption" },
{ "ielr", "IELR conversion" },
{ "all", "all of the above" },
{ NULL, NULL},
};
static const int trace_types[] =
static const argmatch_trace_arg argmatch_trace_args[] =
{
trace_none,
trace_locations,
trace_scan,
trace_parse,
trace_automaton,
trace_bitsets,
trace_closure,
trace_grammar,
trace_resource,
trace_sets,
trace_muscles,
trace_tools,
trace_m4,
trace_skeleton,
trace_time,
trace_ielr,
trace_all
{ "none", trace_none },
{ "locations", trace_locations },
{ "scan", trace_scan },
{ "parse", trace_parse },
{ "automaton", trace_automaton },
{ "bitsets", trace_bitsets },
{ "closure", trace_closure },
{ "grammar", trace_grammar },
{ "resource", trace_resource },
{ "sets", trace_sets },
{ "muscles", trace_muscles },
{ "tools", trace_tools },
{ "m4", trace_m4 },
{ "skeleton", trace_skeleton },
{ "time", trace_time },
{ "ielr", trace_ielr },
{ "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. |
`-----------------------*/
static const char * const feature_args[] =
ARGMATCH_DEFINE_GROUP (feature, enum feature)
static const argmatch_feature_doc argmatch_feature_docs[] =
{
"none",
"caret", "diagnostics-show-caret",
"fixit", "diagnostics-parseable-fixits",
"syntax-only",
"all",
0
{ "caret", N_("show errors with carets") },
{ "fixit", N_("show machine-readable fixes") },
{ "syntax-only", N_("do not generate any file") },
{ "all", N_("all of the above") },
{ "none", N_("disable all of the above") },
{ NULL, NULL }
};
static const int feature_types[] =
static const argmatch_feature_arg argmatch_feature_args[] =
{
feature_none,
feature_caret, feature_caret,
feature_fixit_parsable, feature_fixit_parsable,
feature_syntax_only,
feature_all
{ "none", feature_none },
{ "caret", feature_caret },
{ "diagnostics-show-caret", feature_caret },
{ "fixit", feature_fixit },
{ "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. |
@@ -275,8 +355,7 @@ usage (int status)
printf (_("Usage: %s [OPTION]... FILE\n"), program_name);
fputs (_("\
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\
canonical LR(1) support is experimental.\n\
LALR(1), IELR(1), or canonical LR(1) parser tables.\n\
\n\
"), stdout);
@@ -286,10 +365,10 @@ Mandatory arguments to long options are mandatory for short options too.\n\
fputs (_("\
The same is true for optional arguments.\n\
"), stdout);
putc ('\n', stdout);
fputs (_("\
\n\
Operation modes:\n\
Operation Modes:\n\
-h, --help display this help and exit\n\
-V, --version output version information and exit\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\
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\
\n\
"), stdout);
argmatch_feature_usage (stdout);
putc ('\n', stdout);
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\
-S, --skeleton=FILE specify the skeleton to use\n\
-t, --debug instrument the parser for tracing\n\
same as '-Dparse.trace'\n\
--locations enable location support\n\
-D, --define=NAME[=VALUE] similar to '%define NAME \"VALUE\"'\n\
-F, --force-define=NAME[=VALUE] override '%define NAME \"VALUE\"'\n\
-D, --define=NAME[=VALUE] similar to '%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\
deprecated by '-Dapi.prefix=PREFIX'\n\
deprecated by '-Dapi.prefix={PREFIX}'\n\
-l, --no-lines don't generate '#line' directives\n\
-k, --token-table include a table of token names\n\
-y, --yacc emulate POSIX Yacc\n\
"), stdout);
putc ('\n', stdout);
/* Keep -d and --defines separate so that ../build-aux/cross-options.pl
* won't assume that -d also takes an argument. */
fputs (_("\
Output:\n\
Output Files:\n\
--defines[=FILE] also produce a header file\n\
-d likewise but cannot specify FILE (for POSIX Yacc)\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\
-g, --graph[=FILE] also output a graph of the automaton\n\
-x, --xml[=FILE] also output an XML report of the automaton\n\
(the XML schema is experimental)\n\
"), stdout);
putc ('\n', stdout);
fputs (_("\
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);
argmatch_report_usage (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 (_("%s home page: <%s>.\n"), PACKAGE_NAME, PACKAGE_URL);
fputs (_("General help using GNU software: "
@@ -452,7 +506,7 @@ skeleton_arg (char const *arg, int prio, location loc)
void
language_argmatch (char const *arg, int prio, location loc)
{
char const *msg;
char const *msg = NULL;
if (prio < language_prio)
{
@@ -467,10 +521,9 @@ language_argmatch (char const *arg, int prio, location loc)
}
else if (language_prio == prio)
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
{
COLOR_OPTION = CHAR_MAX + 1,
FIXED_OUTPUT_FILES_OPTION,
LOCATIONS_OPTION,
PRINT_DATADIR_OPTION,
PRINT_LOCALEDIR_OPTION,
@@ -515,6 +569,7 @@ enum
STYLE_OPTION
};
/* In the same order as in usage(), and in the documentation. */
static struct option const long_options[] =
{
/* Operation modes. */
@@ -523,55 +578,43 @@ static struct option const long_options[] =
{ "print-localedir", no_argument, 0, PRINT_LOCALEDIR_OPTION },
{ "print-datadir", no_argument, 0, PRINT_DATADIR_OPTION },
{ "update", no_argument, 0, 'u' },
{ "warnings", optional_argument, 0, 'W' },
{ "feature", optional_argument, 0, 'f' },
/* Parser. */
{ "name-prefix", required_argument, 0, 'p' },
/* Diagnostics. */
{ "warnings", optional_argument, 0, 'W' },
{ "color", optional_argument, 0, COLOR_OPTION },
{ "style", optional_argument, 0, STYLE_OPTION },
/* Output. */
{ "file-prefix", required_argument, 0, 'b' },
{ "output", required_argument, 0, 'o' },
{ "output-file", required_argument, 0, 'o' },
{ "graph", optional_argument, 0, 'g' },
{ "xml", optional_argument, 0, 'x' },
/* Tuning the Parser. */
{ "language", required_argument, 0, 'L' },
{ "skeleton", required_argument, 0, 'S' },
{ "debug", no_argument, 0, 't' },
{ "locations", no_argument, 0, LOCATIONS_OPTION },
{ "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-file", required_argument, 0, REPORT_FILE_OPTION },
{ "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. */
{ "trace", optional_argument, 0, 'T' },
{ "color", optional_argument, 0, COLOR_OPTION },
{ "style", optional_argument, 0, STYLE_OPTION },
/* 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' },
{ "fixed-output-files", no_argument, 0, FIXED_OUTPUT_FILES_OPTION },
{ "output-file", required_argument, 0, 'o' },
{ "trace", optional_argument, 0, 'T' },
{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. */
static
location
@@ -603,6 +646,8 @@ getargs_colors (int argc, char *argv[])
else
handle_color_option (color);
}
else if (STREQ ("--color", arg))
handle_color_option (NULL);
else if (STRPREFIX_LIT ("--style=", arg))
{
const char *style = arg + strlen ("--style=");
@@ -621,6 +666,8 @@ getargs (int argc, char *argv[])
int c;
while ((c = getopt_long (argc, argv, short_options, long_options, NULL))
!= -1)
{
location loc = command_line_location ();
switch (c)
{
/* ASCII Sorting for short options (i.e., upper case then
@@ -653,7 +700,7 @@ getargs (int argc, char *argv[])
*end = 0;
}
}
muscle_percent_define_insert (name, command_line_location (),
muscle_percent_define_insert (name, loc,
kind, value ? value : "",
c == 'D' ? MUSCLE_PERCENT_DEFINE_D
: MUSCLE_PERCENT_DEFINE_F);
@@ -661,13 +708,11 @@ getargs (int argc, char *argv[])
break;
case 'L':
language_argmatch (optarg, command_line_prio,
command_line_location ());
language_argmatch (optarg, command_line_prio, loc);
break;
case 'S':
skeleton_arg (AS_FILE_NAME (optarg), command_line_prio,
command_line_location ());
skeleton_arg (optarg, command_line_prio, loc);
break;
case 'T':
@@ -687,7 +732,7 @@ getargs (int argc, char *argv[])
break;
case 'b':
spec_file_prefix = AS_FILE_NAME (optarg);
spec_file_prefix = optarg;
break;
case 'd':
@@ -696,7 +741,7 @@ getargs (int argc, char *argv[])
if (optarg)
{
free (spec_header_file);
spec_header_file = xstrdup (AS_FILE_NAME (optarg));
spec_header_file = xstrdup (optarg);
}
break;
@@ -705,7 +750,7 @@ getargs (int argc, char *argv[])
if (optarg)
{
free (spec_graph_file);
spec_graph_file = xstrdup (AS_FILE_NAME (optarg));
spec_graph_file = xstrdup (optarg);
}
break;
@@ -721,7 +766,7 @@ getargs (int argc, char *argv[])
break;
case 'o':
spec_outfile = AS_FILE_NAME (optarg);
spec_outfile = optarg;
break;
case 'p':
@@ -734,7 +779,7 @@ getargs (int argc, char *argv[])
case 't':
muscle_percent_define_insert ("parse.trace",
command_line_location (),
loc,
muscle_keyword, "",
MUSCLE_PERCENT_DEFINE_D);
break;
@@ -753,22 +798,28 @@ getargs (int argc, char *argv[])
if (optarg)
{
free (spec_xml_file);
spec_xml_file = xstrdup (AS_FILE_NAME (optarg));
spec_xml_file = xstrdup (optarg);
}
break;
case 'y':
warning_argmatch ("yacc", 0, 0);
yacc_loc = command_line_location ();
yacc_loc = loc;
break;
case COLOR_OPTION:
/* Handled in getargs_colors. */
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:
muscle_percent_define_ensure ("locations",
command_line_location (), true);
muscle_percent_define_ensure ("locations", loc, true);
break;
case PRINT_LOCALEDIR_OPTION:
@@ -781,7 +832,7 @@ getargs (int argc, char *argv[])
case REPORT_FILE_OPTION:
free (spec_verbose_file);
spec_verbose_file = xstrdup (AS_FILE_NAME (optarg));
spec_verbose_file = xstrdup (optarg);
break;
case STYLE_OPTION:
@@ -791,6 +842,7 @@ getargs (int argc, char *argv[])
default:
usage (EXIT_FAILURE);
}
}
if (argc - optind != 1)
{
@@ -801,7 +853,7 @@ getargs (int argc, char *argv[])
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);
}
+1 -1
View File
@@ -118,7 +118,7 @@ enum feature
{
feature_none = 0, /**< No additional feature. */
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_all = ~0 /**< All above features. */
};
+4 -4
View File
@@ -32,7 +32,7 @@
/* Comments for these variables are in gram.h. */
item_number *ritem = NULL;
unsigned nritems = 0;
int nritems = 0;
rule *rules = NULL;
rule_number nrules = 0;
@@ -165,7 +165,7 @@ void
ritem_print (FILE *out)
{
fputs ("RITEM\n", out);
for (unsigned i = 0; i < nritems; ++i)
for (int i = 0; i < nritems; ++i)
if (ritem[i] >= 0)
fprintf (out, " %s", symbols[ritem[i]]->tag);
else
@@ -280,8 +280,8 @@ grammar_dump (FILE *out, const char *title)
for (rule_number i = 0; i < nrules + nuseless_productions; ++i)
{
rule const *rule_i = &rules[i];
unsigned const rhs_itemno = rule_i->rhs - ritem;
unsigned length = rule_rhs_length (rule_i);
int const rhs_itemno = rule_i->rhs - ritem;
int length = rule_rhs_length (rule_i);
aver (item_number_as_rule_number (rule_i->rhs[length] == i));
fprintf (out, "%3d (%2d, %2d, %2s, %2s) %2d -> (%2u-%2u)",
i,
+1 -1
View File
@@ -115,7 +115,7 @@ extern int nvars;
typedef int item_number;
# define ITEM_NUMBER_MAX INT_MAX
extern item_number *ritem;
extern unsigned nritems;
extern int nritems;
/* There is weird relationship between OT1H item_number and OTOH
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)
{
bitset result = bitset_create (nritems, BITSET_FIXED);
unsigned i = nritems-1;
int i = nritems-1;
while (0 < i)
{
--i;
@@ -418,7 +418,7 @@ ielr_item_has_lookahead (state *s, symbol_number lhs, size_t item,
top-level invocation), go get it. */
if (!lhs)
{
unsigned i;
int i;
for (i = s->items[item];
!item_number_is_rule_number (ritem[i]);
++i)
@@ -496,7 +496,7 @@ ielr_compute_annotation_lists (bitsetv follow_kernel_items,
AnnotationIndex *annotation_counts =
xnmalloc (nstates, sizeof *annotation_counts);
ContributionIndex max_contributions = 0;
unsigned total_annotations = 0;
int total_annotations = 0;
*inadequacy_listsp = xnmalloc (nstates, sizeof **inadequacy_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]))
{
unsigned rule_item;
int rule_item;
for (rule_item = t->items[t_item];
!item_number_is_rule_number (ritem[rule_item]);
++rule_item)
+15
View File
@@ -550,6 +550,14 @@ lookahead_tokens_print (FILE *out)
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 ();
set_goto_map ();
initialize_goto_follows ();
@@ -560,6 +568,13 @@ lalr (void)
if (trace_flag & trace_sets)
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 "system.h"
#include <mbfile.h>
#include <mbswidth.h>
#include <quotearg.h>
#include <stdio.h> /* fileno */
#include <sys/ioctl.h>
#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 "getargs.h"
@@ -32,6 +40,49 @@
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
INT_MAX) to COLUMN; otherwise, add mbsnwidth (BUF, BUFSIZE, 0) to
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;
}
/* 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)
static void
boundary_compute (boundary *cur, char const *token, size_t size)
{
int line = cur->line;
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 *lim = token + size;
loc->start = *cur;
for (p = token; p < lim; ++p)
switch (*p)
{
@@ -82,22 +128,34 @@ location_compute (location *loc, boundary *cur, char const *token, size_t size)
byte += byte < INT_MAX;
break;
}
column = add_column_width (column, p0, p - p0);
cur->line = line;
cur->column = column = add_column_width (column, p0, p - p0);
cur->column = column;
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;
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"));
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"));
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"));
}
static unsigned
static int
boundary_print (boundary const *b, FILE *out)
{
return fprintf (out, "%s:%d.%d@%d",
@@ -105,10 +163,10 @@ boundary_print (boundary const *b, FILE *out)
b->line, b->column, b->byte);
}
unsigned
int
location_print (location loc, FILE *out)
{
unsigned res = 0;
int res = 0;
if (trace_flag & trace_locations)
{
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;
res += fprintf (out, "%s",
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);
if (0 <= loc.start.column)
if (0 < loc.start.column)
res += fprintf (out, ".%d", loc.start.column);
}
if (loc.start.file != loc.end.file)
@@ -131,14 +189,14 @@ location_print (location loc, FILE *out)
res += fprintf (out, "-%s",
quotearg_n_style (3, escape_quoting_style,
loc.end.file));
if (0 <= loc.end.line)
if (0 < loc.end.line)
{
res += fprintf (out, ":%d", loc.end.line);
if (0 <= 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)
{
@@ -159,137 +217,264 @@ location_print (location loc, FILE *out)
same file all over for each error. */
static struct
{
FILE *source;
/* The last file we tried to open. If non NULL, but SOURCE is NULL,
it means this file is special and should not be quoted. */
uniqstr file;
size_t line;
/* Offset in SOURCE where line LINE starts. */
/* Raw input file. */
FILE *file;
/* Input file as a stream of multibyte characters. */
mb_file_t mbfile;
/* The position within the last file we quoted. If POS.FILE is non
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;
/* 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;
void
caret_free ()
void caret_init (void)
{
if (caret_info.source)
{
fclose (caret_info.source);
caret_info.source = NULL;
}
screen_width = columns ();
/* TRANSLATORS: This is used when a line is too long, and is
displayed truncated. Use an ellipsis appropriate for your
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
location_caret (location loc, const char *style, FILE *out)
caret_free (void)
{
if (loc.start.column == -1 || loc.start.line == -1)
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)
if (caret_info.file)
{
caret_free ();
fclose (caret_info.file);
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;
if ((caret_info.source = fopen (caret_info.file, "r")))
caret_free ();
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"
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
open it again, but leave caret_info.source NULL so that
we don't try to quote it. */
file. Keep caret_info.file set so that we don't try to
open it again, but leave caret_info.file NULL so that we
don't try to quote it. */
struct stat buf;
if (fstat (fileno (caret_info.source), &buf) == 0
if (fstat (fileno (caret_info.file), &buf) == 0
&& buf.st_mode & S_IFREG)
{
caret_info.line = 1;
caret_info.offset = 0;
caret_info.pos.line = 1;
mbf_init (caret_info.mbfile, caret_info.file);
}
else
caret_free ();
}
}
if (!caret_info.source)
return;
return !!caret_info.file;
}
/* 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
location), just seek it. If it was a previous line, we lost track of it,
so return to the start of file. */
if (caret_info.line <= loc.start.line)
fseek (caret_info.source, caret_info.offset, SEEK_SET);
else
if (line < caret_info.pos.line)
{
caret_info.line = 1;
caret_info.pos.line = 1;
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. */
while (caret_info.line < loc.start.line)
while (caret_info.pos.line < line)
{
int c = getc (caret_info.source);
if (c == EOF)
mbchar_t c;
caret_getc (c);
if (mb_iseof (c))
/* Something is wrong, that line number does not exist. */
return;
caret_info.line += c == '\n';
return false;
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
to the start of the line. */
{
int c = getc (caret_info.source);
if (c != EOF)
mbchar_t c;
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
multiline locations). */
{
fprintf (out, "%5d | ", loc.start.line);
/* 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;
fprintf (out, "%5d | %s", loc.start.line, skip ? ellipsis : "");
/* Whether we opened the style. If the line is not as
expected (maybe the file was changed since the scanner
ran), we might reach the end before we actually saw the
opening column. */
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);
opened = true;
}
fputc (c, out);
c = getc (caret_info.source);
++byte;
if (skip < caret_info.pos.column)
mb_putc (c, out);
boundary_compute (&caret_info.pos, mb_ptr (c), mb_len (c));
caret_getc (c);
if (opened
&& (single_line
? byte == byte_end
: c == '\n' || c == EOF))
end_use_class (style, out);
&& (caret_info.pos.column == col_end
|| width < caret_info.pos.column - skip))
{
end_use_class (style, out);
opened = false;
}
if (width < caret_info.pos.column - skip)
{
fputs (ellipsis, out);
break;
}
}
putc ('\n', out);
}
/* 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);
putc ('^', out);
/* Underlining a multiline location ends with the first
line. */
int len = single_line
? loc.end.column
: ftell (caret_info.source) - caret_info.offset;
for (int i = loc.start.column + 1; i < len; ++i)
for (int i = loc.start.column - 1 - skip + 1,
i_end = min_int (col_end - 1 - skip, width);
i < i_end; ++i)
putc ('~', out);
end_use_class (style, 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
location_empty (location loc)
{
+22 -9
View File
@@ -33,25 +33,25 @@ typedef struct
/* The name of the file that contains the boundary. */
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.
Meaningless and not displayed if negative.
Meaningless and not displayed if nonpositive.
*/
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
column count. If this is INT_MAX, the column number has
overflowed.
Meaningless and not displayed if negative.
Meaningless and not displayed if nonpositive.
*/
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
know where colors start and ends. */
know where colors start and end. */
int byte;
} boundary;
@@ -71,7 +71,12 @@ boundary_set (boundary *p, const char *f, int l, int c, int b)
static inline int
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)
res = a.line - b.line;
if (!res)
@@ -112,15 +117,23 @@ void location_compute (location *loc,
/* Print location to file.
Return number of actually printed characters.
Warning: uses quotearg's slot 3. */
unsigned location_print (location loc, FILE *out);
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
left-over by the usage of location_caret. */
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);
/* 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
after b. */
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
allocate_storage (void)
{
@@ -209,9 +217,21 @@ new_itemsets (state *s)
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)
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]]);
bitset_set (shift_symbol, sym);
kernel_base[sym][kernel_size[sym]] = itemset[i] + 1;
@@ -220,9 +240,11 @@ new_itemsets (state *s)
if (trace_flag & trace_automaton)
{
fprintf (stderr, "final kernel:\n");
kernel_print (stderr);
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. */
state_reductions_set (s, count, redset);
}
+4 -4
View File
@@ -101,7 +101,7 @@ main (int argc, char *argv[])
the grammar; see gram.h. */
timevar_push (tv_reader);
reader ();
reader (grammar_file);
timevar_pop (tv_reader);
if (complaint_status == status_complaint)
@@ -207,6 +207,8 @@ main (int argc, char *argv[])
timevar_pop (tv_parser);
}
finish:
timevar_push (tv_free);
nullable_free ();
derives_free ();
@@ -223,14 +225,11 @@ main (int argc, char *argv[])
muscle_free ();
code_scanner_free ();
skel_scanner_free ();
quotearg_free ();
timevar_pop (tv_free);
if (trace_flag & trace_bitsets)
bitset_stats_dump (stderr);
finish:
/* Stop timing and print the times. */
timevar_stop (tv_total);
timevar_print (stderr);
@@ -249,6 +248,7 @@ main (int argc, char *argv[])
uniqstrs_free ();
complain_free ();
quotearg_free ();
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));
if (how_old == MUSCLE_PERCENT_DEFINE_F)
goto end;
unsigned i = 0;
int i = 0;
/* If assigning the same value, make it a warning. */
warnings warn = STREQ (value, current_value) ? Wother : complaint;
complain_indent (&variable_loc, warn, &i,
@@ -739,7 +739,7 @@ muscle_percent_define_check_values (char const * const *values)
if (!*values)
{
location loc = muscle_percent_define_get_loc (*variablep);
unsigned i = 0;
int i = 0;
complain_indent (&loc, complaint, &i,
_("invalid value for %%define variable %s: %s"),
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); \
}
GENERATE_MUSCLE_INSERT_TABLE (muscle_insert_unsigned_table, unsigned)
GENERATE_MUSCLE_INSERT_TABLE (muscle_insert_int_table, int)
GENERATE_MUSCLE_INSERT_TABLE (muscle_insert_base_table, base_number)
GENERATE_MUSCLE_INSERT_TABLE (muscle_insert_rule_number_table, rule_number)
@@ -214,17 +213,17 @@ prepare_symbols (void)
static void
prepare_rules (void)
{
unsigned *prhs = xnmalloc (nrules, sizeof *prhs);
int *prhs = xnmalloc (nrules, sizeof *prhs);
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);
unsigned *r2 = xnmalloc (nrules, sizeof *r2);
int *r2 = xnmalloc (nrules, sizeof *r2);
int *dprec = xnmalloc (nrules, sizeof *dprec);
int *merger = xnmalloc (nrules, sizeof *merger);
int *immediate = xnmalloc (nrules, sizeof *immediate);
/* Index in RHS. */
unsigned i = 0;
int i = 0;
for (rule_number r = 0; r < nrules; ++r)
{
/* Index of rule R in RHS. */
@@ -251,10 +250,10 @@ prepare_rules (void)
aver (i == nritems);
muscle_insert_item_number_table ("rhs", rhs, ritem[0], 1, nritems);
muscle_insert_unsigned_table ("prhs", prhs, 0, 0, nrules);
muscle_insert_unsigned_table ("rline", rline, 0, 0, nrules);
muscle_insert_int_table ("prhs", prhs, 0, 0, nrules);
muscle_insert_int_table ("rline", rline, 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 ("merger", merger, 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
user_actions_output (FILE *out)
@@ -370,11 +369,20 @@ user_actions_output (FILE *out)
for (rule_number r = 0; r < nrules; ++r)
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",
r + 1, rules[r].action_loc.start.line);
string_output (out, rules[r].action_loc.start.file);
fprintf (out, ")dnl\n[ %s]])\n\n", rules[r].action);
r + 1);
if (!no_lines_flag)
{
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);
}
@@ -482,7 +490,9 @@ prepare_symbol_definitions (void)
muscle_location_grow (key, p->location);
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
@@ -532,10 +542,10 @@ prepare_actions (void)
parser, so we could avoid accidents by not writing them out in
that case. Nevertheless, it seems even better to be able to use
the GLR skeletons even without the non-deterministic tables. */
muscle_insert_unsigned_table ("conflict_list_heads", conflict_table,
conflict_table[0], 1, high + 1);
muscle_insert_unsigned_table ("conflicting_rules", conflict_list,
0, 1, conflict_list_cnt);
muscle_insert_int_table ("conflict_list_heads", conflict_table,
conflict_table[0], 1, high + 1);
muscle_insert_int_table ("conflicting_rules", conflict_list,
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
@@ -78,63 +78,63 @@ extern int gram_debug;
enum gram_tokentype
{
GRAM_EOF = 0,
STRING = 258,
PERCENT_TOKEN = 259,
PERCENT_NTERM = 260,
PERCENT_TYPE = 261,
PERCENT_DESTRUCTOR = 262,
PERCENT_PRINTER = 263,
PERCENT_LEFT = 264,
PERCENT_RIGHT = 265,
PERCENT_NONASSOC = 266,
PERCENT_PRECEDENCE = 267,
PERCENT_PREC = 268,
PERCENT_DPREC = 269,
PERCENT_MERGE = 270,
PERCENT_CODE = 271,
PERCENT_DEFAULT_PREC = 272,
PERCENT_DEFINE = 273,
PERCENT_DEFINES = 274,
PERCENT_ERROR_VERBOSE = 275,
PERCENT_EXPECT = 276,
PERCENT_EXPECT_RR = 277,
PERCENT_FLAG = 278,
PERCENT_FILE_PREFIX = 279,
PERCENT_GLR_PARSER = 280,
PERCENT_INITIAL_ACTION = 281,
PERCENT_LANGUAGE = 282,
PERCENT_NAME_PREFIX = 283,
PERCENT_NO_DEFAULT_PREC = 284,
PERCENT_NO_LINES = 285,
PERCENT_NONDETERMINISTIC_PARSER = 286,
PERCENT_OUTPUT = 287,
PERCENT_PURE_PARSER = 288,
PERCENT_REQUIRE = 289,
PERCENT_SKELETON = 290,
PERCENT_START = 291,
PERCENT_TOKEN_TABLE = 292,
PERCENT_VERBOSE = 293,
PERCENT_YACC = 294,
BRACED_CODE = 295,
BRACED_PREDICATE = 296,
BRACKETED_ID = 297,
CHAR = 298,
COLON = 299,
EPILOGUE = 300,
EQUAL = 301,
ID = 302,
ID_COLON = 303,
PERCENT_PERCENT = 304,
PIPE = 305,
PROLOGUE = 306,
SEMICOLON = 307,
TAG = 308,
TAG_ANY = 309,
TAG_NONE = 310,
INT = 311,
PERCENT_PARAM = 312,
PERCENT_UNION = 313,
PERCENT_EMPTY = 314
STRING = 3,
PERCENT_TOKEN = 4,
PERCENT_NTERM = 5,
PERCENT_TYPE = 6,
PERCENT_DESTRUCTOR = 7,
PERCENT_PRINTER = 8,
PERCENT_LEFT = 9,
PERCENT_RIGHT = 10,
PERCENT_NONASSOC = 11,
PERCENT_PRECEDENCE = 12,
PERCENT_PREC = 13,
PERCENT_DPREC = 14,
PERCENT_MERGE = 15,
PERCENT_CODE = 16,
PERCENT_DEFAULT_PREC = 17,
PERCENT_DEFINE = 18,
PERCENT_DEFINES = 19,
PERCENT_ERROR_VERBOSE = 20,
PERCENT_EXPECT = 21,
PERCENT_EXPECT_RR = 22,
PERCENT_FLAG = 23,
PERCENT_FILE_PREFIX = 24,
PERCENT_GLR_PARSER = 25,
PERCENT_INITIAL_ACTION = 26,
PERCENT_LANGUAGE = 27,
PERCENT_NAME_PREFIX = 28,
PERCENT_NO_DEFAULT_PREC = 29,
PERCENT_NO_LINES = 30,
PERCENT_NONDETERMINISTIC_PARSER = 31,
PERCENT_OUTPUT = 32,
PERCENT_PURE_PARSER = 33,
PERCENT_REQUIRE = 34,
PERCENT_SKELETON = 35,
PERCENT_START = 36,
PERCENT_TOKEN_TABLE = 37,
PERCENT_VERBOSE = 38,
PERCENT_YACC = 39,
BRACED_CODE = 40,
BRACED_PREDICATE = 41,
BRACKETED_ID = 42,
CHAR = 43,
COLON = 44,
EPILOGUE = 45,
EQUAL = 46,
ID = 47,
ID_COLON = 48,
PERCENT_PERCENT = 49,
PIPE = 50,
PROLOGUE = 51,
SEMICOLON = 52,
TAG = 53,
TAG_ANY = 54,
TAG_NONE = 55,
INT = 56,
PERCENT_PARAM = 57,
PERCENT_UNION = 58,
PERCENT_EMPTY = 59
};
#endif
@@ -207,8 +207,6 @@ union GRAM_STYPE
uniqstr PERCENT_NAME_PREFIX;
/* "%pure-parser" */
uniqstr PERCENT_PURE_PARSER;
/* "%yacc" */
uniqstr PERCENT_YACC;
/* "[identifier]" */
uniqstr BRACKETED_ID;
/* "identifier" */
@@ -223,7 +221,7 @@ union GRAM_STYPE
uniqstr tag;
/* variable */
uniqstr variable;
/* "char" */
/* "character literal" */
unsigned char CHAR;
/* value */
value_type value;
+72 -51
View File
@@ -32,21 +32,23 @@
%code
{
#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 "conflicts.h"
#include "files.h"
#include "getargs.h"
#include "gram.h"
#include "named-ref.h"
#include "quotearg.h"
#include "reader.h"
#include "scan-code.h"
#include "scan-gram.h"
#include "vasnprintf.h"
#include "xmemdup0.h"
static int current_prec = 0;
static location current_lhs_loc;
@@ -104,18 +106,14 @@
static void handle_skeleton (location const *loc, char const *skel);
/* 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 *);
/* A string that describes a char (e.g., 'a' -> "'a'"). */
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. */
static void tron (FILE *yyo);
static void troff (FILE *yyo);
@@ -124,6 +122,7 @@
%define api.header.include {"parse-gram.h"}
%define api.prefix {gram_}
%define api.pure full
%define api.token.raw
%define api.value.type union
%define locations
%define parse.error verbose
@@ -137,8 +136,8 @@
{
/* Bison's grammar can initial empty locations, hence a default
location is needed. */
boundary_set (&@$.start, current_file, 1, 1, 1);
boundary_set (&@$.end, current_file, 1, 1, 1);
boundary_set (&@$.start, grammar_file, 1, 1, 1);
boundary_set (&@$.end, grammar_file, 1, 1, 1);
}
/* Define the tokens together with their human representation. */
@@ -196,7 +195,7 @@
%token BRACED_CODE "{...}"
%token BRACED_PREDICATE "%?{...}"
%token BRACKETED_ID "[identifier]"
%token CHAR "char"
%token CHAR "character literal"
%token COLON ":"
%token EPILOGUE "epilogue"
%token EQUAL "="
@@ -223,7 +222,7 @@
%type <uniqstr>
BRACKETED_ID ID ID_COLON
PERCENT_ERROR_VERBOSE PERCENT_FILE_PREFIX PERCENT_FLAG PERCENT_NAME_PREFIX
PERCENT_PURE_PARSER PERCENT_YACC
PERCENT_PURE_PARSER
TAG tag tag.opt variable
%printer { fputs ($$, yyo); } <uniqstr>
%printer { fprintf (yyo, "[%s]", $$); } BRACKETED_ID
@@ -352,7 +351,7 @@ prologue_declaration:
| "%skeleton" STRING { handle_skeleton (&@2, $2); }
| "%token-table" { token_table_flag = true; }
| "%verbose" { report_flag |= report_states; }
| "%yacc" { handle_yacc (&@$, $1); }
| "%yacc" { handle_yacc (&@$); }
| error ";" { current_class = unknown_sym; yyerrok; }
| /*FIXME: Err? What is this horror doing here? */ ";"
;
@@ -732,12 +731,24 @@ id:
{ $$ = symbol_from_uniqstr ($1, @1); }
| CHAR
{
const char *var = "api.token.raw";
if (current_class == nterm_sym)
{
gram_error (&@1,
_("character literals cannot be nonterminals"));
complain (&@1, complaint,
_("character literals cannot be nonterminals"));
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_class_set ($$, token_sym, @1, false);
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
handle_require (location const *loc, char const *version)
{
/* Changes of behavior are only on minor version changes, so "3.0.5"
is the same as "3.0". */
errno = 0;
char* cp = NULL;
unsigned long major = strtoul (version, &cp, 10);
if (errno || *cp != '.')
required_version = str_to_version (version);
if (required_version == -1)
{
complain (loc, complaint, _("invalid version requirement: %s"),
version);
required_version = 0;
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
while developping it. */
const char* api_version = "3.4";
const char* package_version =
strverscmp (api_version, PACKAGE_VERSION) > 0
0 < strverscmp (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"),
version, package_version);
@@ -1003,16 +1033,16 @@ handle_skeleton (location const *loc, char const *skel)
char const *skeleton_user = skel;
if (strchr (skeleton_user, '/'))
{
size_t dir_length = strlen (current_file);
while (dir_length && current_file[dir_length - 1] != '/')
size_t dir_length = strlen (grammar_file);
while (dir_length && grammar_file[dir_length - 1] != '/')
--dir_length;
while (dir_length && current_file[dir_length - 1] == '/')
while (dir_length && grammar_file[dir_length - 1] == '/')
--dir_length;
char *skeleton_build =
xmalloc (dir_length + 1 + strlen (skeleton_user) + 1);
if (dir_length > 0)
{
memcpy (skeleton_build, current_file, dir_length);
memcpy (skeleton_build, grammar_file, dir_length);
skeleton_build[dir_length++] = '/';
}
strcpy (skeleton_build + dir_length, skeleton_user);
@@ -1024,23 +1054,14 @@ handle_skeleton (location const *loc, char const *skel)
static void
handle_yacc (location const *loc, char const *directive)
handle_yacc (location const *loc)
{
const char *directive = "%yacc";
bison_directive (loc, directive);
bool warned = false;
if (location_empty (yacc_loc))
yacc_loc = *loc;
else
{
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");
duplicate_directive (directive, yacc_loc, *loc);
}
+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);
if (merge_function->type != NULL && !UNIQSTR_EQ (merge_function->type, type))
{
unsigned indent = 0;
int indent = 0;
complain_indent (&declaration_loc, complaint, &indent,
_("result type clash on merge function %s: "
"<%s> != <%s>"),
@@ -358,6 +358,8 @@ grammar_rule_check_and_complete (symbol_list *r)
&& warning_is_enabled (Wempty_rule))
{
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;
loc.end = loc.start;
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 |
| RITEM. |
`---------------------------------------------------------------*/
/*---------------------------------------------.
| Build RULES and RITEM from what was parsed. |
`---------------------------------------------*/
static void
packgram (void)
{
unsigned itemno = 0;
int itemno = 0;
ritem = xnmalloc (nritems + 1, sizeof *ritem);
/* This sentinel is used by build_relations in gram.c. */
*ritem++ = 0;
@@ -699,7 +700,8 @@ packgram (void)
if (trace_flag & trace_sets)
ritem_print (stderr);
}
/*------------------------------------------------------------------.
| Read in the grammar specification and record it in the format |
| described in gram.h. All actions are copied into ACTION_OBSTACK, |
@@ -708,39 +710,20 @@ packgram (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 ();
/* 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++;
gram_in = xfopen (grammar_file, "r");
gram__flex_debug = trace_flag & trace_scan;
gram_debug = trace_flag & trace_parse;
gram_scanner_initialize ();
gram_scanner_open (gram);
gram_parse ();
gram_scanner_close ();
prepare_percent_define_front_end_variables ();
if (complaint_status < status_complaint)
check_and_convert_grammar ();
xfclose (gram_in);
}
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);
/* Attach a PREDICATE to the current rule. */
void grammar_current_rule_predicate_append (const char *predicate, location loc);
void reader (void);
void reader (const char *gram);
void free_merger_functions (void);
extern merger_list *merge_functions;
+4 -4
View File
@@ -52,8 +52,8 @@ static bitset V;
'useless', but no warning should be issued). */
static bitset V1;
unsigned nuseless_productions;
unsigned nuseless_nonterminals;
int nuseless_productions;
int nuseless_nonterminals;
#define bitset_swap(Lhs, Rhs) \
do { \
@@ -195,10 +195,10 @@ inaccessable_symbols (void)
bitset_free (P);
P = Pp;
unsigned nuseful_productions = bitset_count (P);
int nuseful_productions = bitset_count (P);
nuseless_productions = nrules - nuseful_productions;
unsigned nuseful_nonterminals = 0;
int nuseful_nonterminals = 0;
for (symbol_number i = ntokens; i < nsyms; ++i)
nuseful_nonterminals += bitset_test (V, i);
nuseless_nonterminals = nvars - nuseful_nonterminals;
+2 -2
View File
@@ -36,7 +36,7 @@ void reduce_free (void);
* reduce_grammar. Size nvars + nuseless_nonterminals. */
extern symbol_number *nterm_map;
extern unsigned nuseless_nonterminals;
extern unsigned nuseless_productions;
extern int nuseless_nonterminals;
extern int nuseless_productions;
#endif /* !REDUCE_H_ */
+3 -3
View File
@@ -33,14 +33,14 @@ relation_print (const char *title,
{
if (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])
{
fputs (" ", out);
if (print)
print (i, out);
else
fprintf (out, "%3lu", (unsigned long) i);
fprintf (out, "%3ld", (long) i);
fputc (':', out);
for (relation_node j = 0; r[i][j] != END_NODE; ++j)
{
@@ -48,7 +48,7 @@ relation_print (const char *title,
if (print)
print (r[i][j], out);
else
fprintf (out, "%3lu", (unsigned long) r[i][j]);
fprintf (out, "%3ld", (long) r[i][j]);
}
fputc ('\n', out);
}
+41 -40
View File
@@ -48,11 +48,12 @@ YY_DECL;
#define YY_USER_ACTION location_compute (loc, &loc->end, yytext, yyleng);
static char *fetch_type_name (char *cp, char const **type_name,
location dollar_loc);
const location *dollar_loc);
static void handle_action_dollar (symbol_list *rule, char *cp,
location dollar_loc);
static void handle_action_at (symbol_list *rule, char *cp, location at_loc);
const location *dollar_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. */
static char *ref_tail_fields;
@@ -163,13 +164,13 @@ ref -?[0-9]+|{id}|"["{id}"]"|"$"
{
"$"("<"{tag}">")?{ref} {
ref_tail_fields = NULL;
handle_action_dollar (self->rule, yytext, *loc);
handle_action_dollar (self->rule, yytext, loc);
if (ref_tail_fields)
obstack_sgrow (&obstack_for_string, ref_tail_fields);
}
"@"{ref} {
ref_tail_fields = NULL;
handle_action_at (self->rule, yytext, *loc);
handle_action_at (self->rule, yytext, loc);
if (ref_tail_fields)
obstack_sgrow (&obstack_for_string, ref_tail_fields);
}
@@ -179,7 +180,7 @@ ref -?[0-9]+|{id}|"["{id}"]"|"$"
{
"$"("<"{tag}">")?"$" {
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_quote (&obstack_for_string, type_name);
obstack_sgrow (&obstack_for_string, ")[");
@@ -215,14 +216,14 @@ is_dot_or_dash (char ch)
static inline bool
contains_dot_or_dash (const char* p)
{
return strpbrk(p, ".-");
return !!strpbrk (p, ".-");
}
/* Defines a variant of a symbolic name resolution. */
typedef struct
{
/* Index in symbol list. */
unsigned symbol_index;
int symbol_index;
/* Matched symbol id and loc. */
uniqstr id;
@@ -249,8 +250,8 @@ typedef struct
#define VARIANT_NOT_VISIBLE_FROM_MIDRULE (1 << 2)
static variant *variant_table = NULL;
static unsigned variant_table_size = 0;
static unsigned variant_count = 0;
static int variant_table_size = 0;
static int variant_count = 0;
static variant *
variant_table_grow (void)
@@ -285,7 +286,7 @@ find_prefix_end (char const *prefix, char const *cp, char const *end)
}
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 *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 *
get_at_spec(unsigned symbol_index)
get_at_spec(int symbol_index)
{
static char at_buf[20];
if (symbol_index == 0)
@@ -320,7 +321,7 @@ static void
show_sub_message (warnings warning,
const char* cp, bool explicit_bracketing,
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);
@@ -384,9 +385,9 @@ static void
show_sub_messages (warnings warning,
const char* cp, bool explicit_bracketing,
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,
cp, explicit_bracketing,
midrule_rhs_index, dollar_or_at,
@@ -406,7 +407,7 @@ show_sub_messages (warnings warning,
accesses. */
static long
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)
{
if ('$' == *cp)
@@ -419,7 +420,7 @@ parse_ref (char *cp, symbol_list *rule, int rule_length,
return num;
else
{
complain (&text_loc, complaint, _("integer out of range: %s"),
complain (text_loc, complaint, _("integer out of range: %s"),
quote (text));
return INVALID_REF;
}
@@ -436,7 +437,7 @@ parse_ref (char *cp, symbol_list *rule, int rule_length,
/* Add all relevant variants. */
{
unsigned symbol_index;
int symbol_index;
symbol_list *l;
variant_count = 0;
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. */
unsigned valid_variants = 0;
unsigned valid_variant_index = 0;
for (unsigned i = 0; i < variant_count; ++i)
int valid_variants = 0;
int valid_variant_index = 0;
for (int i = 0; i < variant_count; ++i)
{
variant *var = &variant_table[i];
unsigned symbol_index = var->symbol_index;
int symbol_index = var->symbol_index;
/* Check visibility from midrule actions. */
if (midrule_rhs_index != 0
@@ -489,16 +490,16 @@ parse_ref (char *cp, symbol_list *rule, int rule_length,
{
case 0:
{
unsigned len = (explicit_bracketing || !ref_tail_fields) ?
int len = (explicit_bracketing || !ref_tail_fields) ?
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));
indent += SUB_INDENT;
if (len == 0)
{
location sym_loc = text_loc;
location sym_loc = *text_loc;
sym_loc.start.column += 1;
sym_loc.end = sym_loc.start;
complain_indent (&sym_loc, complaint, &indent,
@@ -524,17 +525,17 @@ parse_ref (char *cp, symbol_list *rule, int rule_length,
}
case 1:
{
unsigned indent = 0;
int indent = 0;
if (variant_count > 1)
{
complain_indent (&text_loc, Wother, &indent,
complain_indent (text_loc, Wother, &indent,
_("misleading reference: %s"), quote (text));
show_sub_messages (Wother,
cp, explicit_bracketing, midrule_rhs_index,
dollar_or_at, indent + SUB_INDENT);
}
{
unsigned symbol_index =
int symbol_index =
variant_table[valid_variant_index].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:
default:
{
unsigned indent = 0;
complain_indent (&text_loc, complaint, &indent,
int indent = 0;
complain_indent (text_loc, complaint, &indent,
_("ambiguous reference: %s"), quote (text));
show_sub_messages (complaint,
cp, explicit_bracketing, midrule_rhs_index,
@@ -566,7 +567,7 @@ int max_left_semantic_context = 0;
static
char *
fetch_type_name (char *cp, char const **type_name,
location dollar_loc)
const location *dollar_loc)
{
if (*cp == '<')
{
@@ -579,7 +580,7 @@ fetch_type_name (char *cp, char const **type_name,
'text' is needed for error messages. */
++cp;
if (untyped_var_seen)
complain (&dollar_loc, complaint,
complain (dollar_loc, complaint,
_("explicit type given in untyped grammar"));
tag_seen = true;
}
@@ -595,7 +596,7 @@ fetch_type_name (char *cp, char const **type_name,
`------------------------------------------------------------------*/
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;
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 (rule->midrule_parent_rule)
complain (&dollar_loc, complaint,
complain (dollar_loc, complaint,
_("$$ for the midrule at $%d of %s"
" has no declared type"),
rule->midrule_parent_rhs_index,
quote (effective_rule->content.sym->tag));
else
complain (&dollar_loc, complaint,
complain (dollar_loc, complaint,
_("$$ of %s has no declared type"),
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))
{
if (union_seen || tag_seen)
complain (&dollar_loc, complaint,
complain (dollar_loc, complaint,
_("$%s of %s has no declared type"), cp,
quote (effective_rule->content.sym->tag));
else
@@ -689,7 +690,7 @@ handle_action_dollar (symbol_list *rule, char *text, location dollar_loc)
{
if (muscle_percent_define_ifdef ("api.value.automove")
&& sym->action_props.is_value_used)
complain (&dollar_loc, Wother,
complain (dollar_loc, Wother,
_("multiple occurrences of $%d with api.value.automove"),
n);
sym->action_props.is_value_used = true;
@@ -706,7 +707,7 @@ handle_action_dollar (symbol_list *rule, char *text, location dollar_loc)
`------------------------------------------------------*/
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;
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);
}
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,
rule->midrule_parent_rhs_index, text, at_loc, '@');
+6 -9
View File
@@ -21,18 +21,15 @@
#ifndef SCAN_GRAM_H_
# define SCAN_GRAM_H_
/* From the scanner. */
extern FILE *gram_in;
extern int gram__flex_debug;
void gram_scanner_initialize (void);
/* Initialize the scanner to read file GRAM. */
void gram_scanner_open (const char *gram);
/* Close the open files. */
void gram_scanner_close (void);
/* Free all the memory allocated to the scanner. */
void gram_scanner_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)
GRAM_LEX_DECL;
+54 -94
View File
@@ -21,6 +21,8 @@
%option prefix="gram_" outfile="lex.yy.c"
%{
#include <errno.h>
#include <c-ctype.h>
#include <mbswidth.h>
#include <quote.h>
@@ -49,9 +51,6 @@ static boundary scanner_cursor;
#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. */
#define BISON_DIRECTIVE(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]); \
} while (0)
/* The current file name. Might change with #line. */
static uniqstr current_file = NULL;
/* A string representing the most recently saved token. */
static char *last_string = NULL;
@@ -100,7 +102,7 @@ gram_scanner_last_string_free (void)
}
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 void unexpected_eof (boundary, char const *);
static void unexpected_newline (boundary, char const *);
@@ -139,12 +141,14 @@ id {letter}({letter}|[-0-9])*
int [0-9]+
xint 0[xX][0-9abcdefABCDEF]+
eol \n|\r\n
/* 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})
/* Zero or more instances of backslash-newline. Following GCC, allow
white space between the backslash and the newline. */
splice (\\[ \f\t\v]*\n)*
splice (\\[ \f\t\v]*{eol})*
/* An equal sign, with optional leading whitespaces. This is used in some
deprecated constructs. */
@@ -193,7 +197,7 @@ eqopt ({sp}=)?
"," {
complain (loc, Wother, _("stray ',' treated as white space"));
}
[ \f\n\t\v] |
[ \f\t\v\r]|{eol} |
"//".* continue;
"/*" {
token_start = loc->start;
@@ -201,9 +205,7 @@ eqopt ({sp}=)?
BEGIN SC_YACC_COMMENT;
}
/* #line directives are not documented, and may be withdrawn or
modified in future versions of Bison. */
^"#line "{int}(" \"".*"\"")?"\n" {
^"#line "{int}(" \"".*"\"")?{eol} {
handle_syncline (yytext + sizeof "#line " - 1, *loc);
}
}
@@ -233,7 +235,6 @@ eqopt ({sp}=)?
"%expect" return BISON_DIRECTIVE (EXPECT);
"%expect-rr" return BISON_DIRECTIVE (EXPECT_RR);
"%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);
"%glr-parser" return BISON_DIRECTIVE (GLR_PARSER);
"%language" return BISON_DIRECTIVE (LANGUAGE);
@@ -262,7 +263,7 @@ eqopt ({sp}=)?
"%type" return PERCENT_TYPE;
"%union" return PERCENT_UNION;
"%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
issued only since Bison 3.4. */
@@ -281,7 +282,7 @@ eqopt ({sp}=)?
"%error"[-_]"verbose" RETURN_VALUE (PERCENT_ERROR_VERBOSE, uniqstr_new (yytext));
"%expect"[-_]"rr" DEPRECATED ("%expect-rr");
"%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"[-_]"lines" DEPRECATED ("%no-lines");
"%output"{eqopt} DEPRECATED ("%output");
@@ -330,7 +331,7 @@ eqopt ({sp}=)?
}
/* Semantic predicate. */
"%?"[ \f\n\t\v]*"{" {
"%?"([ \f\t\v]|{eol})*"{" {
nesting = 0;
code_start = loc->start;
BEGIN SC_PREDICATE;
@@ -359,7 +360,7 @@ eqopt ({sp}=)?
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",
ngettext ("invalid character", "invalid characters", yyleng),
quote_mem (yytext, yyleng));
@@ -458,7 +459,7 @@ eqopt ({sp}=)?
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",
ngettext ("invalid character in bracketed name",
"invalid characters in bracketed name", yyleng),
@@ -491,7 +492,7 @@ eqopt ({sp}=)?
<SC_YACC_COMMENT>
{
"*/" BEGIN context_state;
.|\n continue;
.|{eol} continue;
<<EOF>> unexpected_eof (token_start, "*/"); BEGIN context_state;
}
@@ -513,7 +514,7 @@ eqopt ({sp}=)?
<SC_LINE_COMMENT>
{
"\n" STRING_GROW; BEGIN context_state;
{eol} STRING_GROW; BEGIN context_state;
{splice} STRING_GROW;
<<EOF>> BEGIN context_state;
}
@@ -535,7 +536,7 @@ eqopt ({sp}=)?
RETURN_VALUE (STRING, last_string);
}
<<EOF>> unexpected_eof (token_start, "\"");
"\n" unexpected_newline (token_start, "\"");
{eol} unexpected_newline (token_start, "\"");
}
/*----------------------------------------------------------.
@@ -564,7 +565,7 @@ eqopt ({sp}=)?
BEGIN INITIAL;
return CHAR;
}
"\n" unexpected_newline (token_start, "'");
{eol} unexpected_newline (token_start, "'");
<<EOF>> unexpected_eof (token_start, "'");
}
@@ -604,22 +605,22 @@ eqopt ({sp}=)?
{
\\[0-7]{1,3} {
verify (UCHAR_MAX < ULONG_MAX);
unsigned long c = strtoul (yytext + 1, NULL, 8);
if (!c || UCHAR_MAX < c)
long c = strtol (yytext + 1, NULL, 8);
if (0 < c && c <= UCHAR_MAX)
obstack_1grow (&obstack_for_string, c);
else
complain (loc, complaint, _("invalid number after \\-escape: %s"),
yytext+1);
else
obstack_1grow (&obstack_for_string, c);
}
\\x[0-9abcdefABCDEF]+ {
verify (UCHAR_MAX < ULONG_MAX);
unsigned long c = strtoul (yytext + 2, NULL, 16);
if (!c || UCHAR_MAX < c)
long c = strtol (yytext + 2, NULL, 16);
if (0 < c && c <= UCHAR_MAX)
obstack_1grow (&obstack_for_string, c);
else
complain (loc, complaint, _("invalid number after \\-escape: %s"),
yytext+1);
else
obstack_1grow (&obstack_for_string, c);
}
\\a obstack_1grow (&obstack_for_string, '\a');
@@ -641,7 +642,7 @@ eqopt ({sp}=)?
else
obstack_1grow (&obstack_for_string, c);
}
\\(.|\n) {
\\(.|{eol}) {
char const *p = yytext + 1;
/* Quote only if escaping won't make the character visible. */
if (c_isspace ((unsigned char) *p) && c_isprint ((unsigned char) *p))
@@ -665,14 +666,14 @@ eqopt ({sp}=)?
<SC_CHARACTER>
{
"'" STRING_GROW; BEGIN context_state;
\n unexpected_newline (token_start, "'");
{eol} unexpected_newline (token_start, "'");
<<EOF>> unexpected_eof (token_start, "'");
}
<SC_STRING>
{
"\"" STRING_GROW; BEGIN context_state;
\n unexpected_newline (token_start, "\"");
{eol} unexpected_newline (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. |
`------------------------------------------------------*/
static unsigned long
static int
scan_integer (char const *number, int base, location loc)
{
verify (INT_MAX < ULONG_MAX);
@@ -869,9 +823,10 @@ scan_integer (char const *number, int base, location loc)
complain (&loc, Wyacc,
_("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"),
quote (number));
@@ -892,7 +847,7 @@ static int
convert_ucn_to_byte (char const *ucn)
{
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
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
multibyte characters. */
if (UCHAR_MAX < code)
if (! (0 <= code && code <= UCHAR_MAX))
return -1;
#if ! ('$' == 0x24 && '@' == 0x40 && '`' == 0x60 && '~' == 0x7e)
@@ -947,8 +902,9 @@ static void
handle_syncline (char *args, location loc)
{
char *file;
unsigned long lineno = strtoul (args, &file, 10);
if (INT_MAX <= lineno)
errno = 0;
long lineno = strtol (args, &file, 10);
if (! (0 <= lineno && lineno <= INT_MAX && errno == 0))
{
complain (&loc, Wother, _("line number overflow"));
lineno = INT_MAX;
@@ -1018,25 +974,29 @@ unexpected_newline (boundary start, char const *token_end)
}
/*-------------------------.
| Initialize the scanner. |
`-------------------------*/
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);
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
gram_scanner_free (void)
{
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
at_complain (int argc, char *argv[], char **out_namep, int *out_linenop)
{
static unsigned indent;
static int indent;
warnings w = flag (argv[1]);
location loc;
location *locp = NULL;
+136 -92
View File
@@ -24,18 +24,27 @@
#include "system.h"
#include <assure.h>
#include <fstrcmp.h>
#include <hash.h>
#include "complain.h"
#include "getargs.h"
#include "gram.h"
#include "intprops.h"
#include "quote.h"
/*-------------------------------------------------------------------.
| Symbols sorted by tag. Allocated by the first invocation of |
| symbols_do, after which no more symbols should be created. |
`-------------------------------------------------------------------*/
static struct hash_table *symbol_table = NULL;
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 **semantic_types_sorted = NULL;
static semantic_type **semantic_types_sorted = NULL;
/*------------------------.
| Distinguished symbols. |
@@ -149,8 +158,8 @@ symbol_free (void *ptr)
declaration first.
*/
static
void symbols_sort (symbol **first, symbol **second)
static void
symbols_sort (symbol **first, symbol **second)
{
if (0 < location_cmp ((*first)->location, (*second)->location))
{
@@ -162,8 +171,8 @@ void symbols_sort (symbol **first, symbol **second)
/* Likewise, for locations. */
static
void locations_sort (location *first, location *second)
static void
locations_sort (location *first, location *second)
{
if (0 < location_cmp (*first, *second))
{
@@ -279,7 +288,7 @@ static void
complain_symbol_redeclared (symbol *s, const char *what, location first,
location second)
{
unsigned i = 0;
int i = 0;
locations_sort (&first, &second);
complain_indent (&second, complaint, &i,
_("%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,
location second)
{
unsigned i = 0;
int i = 0;
locations_sort (&first, &second);
complain_indent (&second, complaint, &i,
_("%s redeclaration for <%s>"), what, s->tag);
@@ -304,7 +313,7 @@ complain_semantic_type_redeclared (semantic_type *s, const char *what, location
static void
complain_class_redeclared (symbol *sym, symbol_class class, location second)
{
unsigned i = 0;
int i = 0;
complain_indent (&second, complaint, &i,
class == token_sym
? _("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
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)
{
unsigned i = 0;
complain (&loc, Wother, _("symbol %s redeclared"), sym->tag);
int i = 0;
complain_indent (&loc, Wother, &i,
_("symbol %s redeclared"), sym->tag);
i += SUB_INDENT;
complain_indent (&sym->location, Wother, &i,
_("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)
complain (&loc, complaint, _("redefining user token number of %s"),
sym->tag);
else if (user_token_number == INT_MAX)
complain (&loc, complaint, _("user token number of %s too large"),
sym->tag);
else
{
*user_token_numberp = user_token_number;
@@ -513,18 +575,13 @@ symbol_user_token_number_set (symbol *sym, int user_token_number, location loc)
| nonterminal. |
`----------------------------------------------------------*/
static inline bool
static void
symbol_check_defined (symbol *sym)
{
sym_content *s = sym->content;
if (s->class == unknown_sym)
{
assert (s->status != declared);
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);
complain_symbol_undeclared (sym);
s->class = nterm_sym;
s->number = nvars++;
}
@@ -540,11 +597,9 @@ symbol_check_defined (symbol *sym)
if (sem_type)
sem_type->status = declared;
}
return true;
}
static inline bool
static void
semantic_type_check_defined (semantic_type *sem_type)
{
/* <*> and <> do not have to be "declared". */
@@ -563,24 +618,8 @@ semantic_type_check_defined (semantic_type *sem_type)
complain (&sem_type->location, Wother,
_("type <%s> is used, but is not associated to any symbol"),
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 |
| 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. |
`-------------------------------------------------------------------*/
static inline bool
static void
symbol_pack (symbol *this)
{
aver (this->content->number != NUMBER_UNDEFINED);
@@ -655,19 +694,12 @@ symbol_pack (symbol *this)
this->content->number += ntokens;
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
complain_user_token_number_redeclared (int num, symbol *first, symbol *second)
{
unsigned i = 0;
int i = 0;
symbols_sort (&first, &second);
complain_indent (&second->location, complaint, &i,
_("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. |
`--------------------------------------------------*/
static inline bool
static void
symbol_translation (symbol *this)
{
/* Nonterminal? */
@@ -699,14 +731,6 @@ symbol_translation (symbol *this)
token_translations[this->content->user_token_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. */
#define HT_INITIAL_CAPACITY 257
static struct hash_table *symbol_table = NULL;
static struct hash_table *semantic_type_table = NULL;
static inline bool
hash_compare_symbol (const symbol *m1, const symbol *m2)
{
@@ -784,6 +805,23 @@ symbols_new (void)
hash_symbol_hasher,
hash_symbol_comparator,
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,
NULL,
hash_semantic_type_hasher,
@@ -905,36 +943,25 @@ symbols_free (void)
}
/*---------------------------------------------------------------.
| Look for undefined symbols, report an error, and consider them |
| terminals. |
`---------------------------------------------------------------*/
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
symbols_cmp_qsort (void const *a, void const *b)
{
return symbols_cmp (*(symbol * const *)a, *(symbol * const *)b);
}
/* Store in *SORTED an array of pointers to the symbols contained in
TABLE, sorted (alphabetically) by tag. */
static void
symbols_do (Hash_processor processor, void *processor_data,
struct hash_table *table, symbol ***sorted)
table_sort (struct hash_table *table, symbol ***sorted)
{
aver (!*sorted);
size_t count = hash_get_n_entries (table);
if (!*sorted)
{
*sorted = xnmalloc (count, sizeof **sorted);
hash_get_entries (table, (void**)*sorted, count);
qsort (*sorted, count, sizeof **sorted, symbols_cmp_qsort);
}
for (size_t i = 0; i < count; ++i)
processor ((*sorted)[i], processor_data);
*sorted = xnmalloc (count + 1, sizeof **sorted);
hash_get_entries (table, (void**)*sorted, count);
qsort (*sorted, count, sizeof **sorted, symbol_cmp);
(*sorted)[count] = NULL;
}
/*--------------------------------------------------------------.
@@ -945,10 +972,20 @@ symbols_do (Hash_processor processor, void *processor_data,
void
symbols_check_defined (void)
{
symbols_do (symbol_check_defined_processor, NULL,
symbol_table, &symbols_sorted);
symbols_do (semantic_type_check_defined_processor, NULL,
semantic_type_table, &semantic_types_sorted);
table_sort (symbol_table, &symbols_sorted);
/* semantic_type, like symbol, starts with a 'tag' field and then a
'location' field. And here we only deal with arrays/hashes of
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;
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)
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
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;
symbols_do (symbol_translation_processor, NULL,
symbol_table, &symbols_sorted);
for (int i = 0; symbols_sorted[i]; ++i)
symbol_translation (symbols_sorted[i]);
}
@@ -1015,7 +1058,8 @@ void
symbols_pack (void)
{
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. */
{
+2 -1
View File
@@ -345,7 +345,8 @@ void semantic_type_code_props_set (semantic_type *type,
| 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);
/** 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>
/* 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. |
`-----------------*/
@@ -249,14 +262,4 @@ typedef size_t uintptr_t;
} \
} 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 */
+6 -6
View File
@@ -84,7 +84,7 @@ int nvectors;
static base_number **froms;
static base_number **tos;
static unsigned **conflict_tos;
static int **conflict_tos;
static size_t *tally;
static base_number *width;
@@ -115,9 +115,9 @@ base_number base_ninf = 0;
-nstates..table_size (as an upper bound) */
static bitset pos_set = NULL;
static unsigned *conflrow;
unsigned *conflict_table;
unsigned *conflict_list;
static int *conflrow;
int *conflict_table;
int *conflict_list;
int conflict_list_cnt;
static int conflict_list_free;
@@ -391,7 +391,7 @@ save_row (state_number s)
/* Allocate non defaulted actions. */
base_number *sp1 = froms[s] = xnmalloc (count, sizeof *sp1);
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;
/* Store non defaulted actions. */
@@ -646,7 +646,7 @@ pack_vector (vector_number vector)
size_t t = tally[i];
base_number *from = froms[i];
base_number *to = tos[i];
unsigned *conflict_to = conflict_tos[i];
int *conflict_to = conflict_tos[i];
aver (t != 0);
+2 -2
View File
@@ -122,8 +122,8 @@ extern base_number *base;
keep parser tables small. */
extern base_number base_ninf;
extern unsigned *conflict_table;
extern unsigned *conflict_list;
extern int *conflict_table;
extern int *conflict_list;
extern int conflict_list_cnt;
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]
11 | a: /* empty. */ {};
| ^~
| %empty
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]
11 | a: /* empty. */ {};
| ^~
| %empty
2.y:13.17-18: warning: empty rule without %empty [-Wempty-rule]
13 | c: /* empty. */ {};
| ^~
| %empty
2.y: warning: fix-its can be applied. Rerun with option '--update'. [-Wother]
]])
@@ -342,9 +345,9 @@ int
main (void)
{]AT_CXX_IF([[
yy::parser p;
p.set_debug_level (!!getenv("YYDEBUG"));
p.set_debug_level (!!getenv ("YYDEBUG"));
return p.parse ();]], [[
yydebug = !!getenv("YYDEBUG");
yydebug = !!getenv ("YYDEBUG");
return !!yyparse (]AT_PARAM_IF([0])[);]])[
}
]])
@@ -422,6 +425,7 @@ AT_DATA_GRAMMAR([[input.y]],
]$3[
%code
{
#include <stdio.h> /* putchar. */
]AT_YYERROR_DECLARE[
]AT_YYLEX_DECLARE[
}
@@ -769,7 +773,7 @@ static
int c = ]AT_VAL[]m4_ifval([$6], [.ival])[ = counter++;
/* 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;
assert (c <= (int) strlen (source));
if (source[c])
@@ -1079,17 +1083,17 @@ AT_DATA_GRAMMAR([[input.y]],
} <*>
%printer {
fprintf (yyoutput, "<> printer for '%c' @ %d", $$, @$.first_column);
fprintf (yyo, "<> printer for '%c' @ %d", $$, @$.first_column);
} <>
%destructor {
fprintf (stdout, "<> destructor for '%c' @ %d.\n", $$, @$.first_column);
printf ("<> destructor for '%c' @ %d.\n", $$, @$.first_column);
} <>
%printer {
fprintf (yyoutput, "'b'/'c' printer for '%c' @ %d", $$, @$.first_column);
fprintf (yyo, "'b'/'c' printer for '%c' @ %d", $$, @$.first_column);
} 'b' 'c'
%destructor {
fprintf (stdout, "'b'/'c' destructor for '%c' @ %d.\n", $$, @$.first_column);
printf ("'b'/'c' destructor for '%c' @ %d.\n", $$, @$.first_column);
} 'b' 'c'
%destructor {
@@ -1175,23 +1179,23 @@ AT_DATA_GRAMMAR([[input.y]],
%type <field1> 'e'
%type <field2> 'f'
%printer {
fprintf (yyoutput, "<*>/<field2>/e printer");
fprintf (yyo, "<*>/<field2>/e printer");
} <*> 'e' <field2>
%destructor {
fprintf (stdout, "<*>/<field2>/e destructor.\n");
printf ("<*>/<field2>/e destructor.\n");
} <*> 'e' <field2>
%type <field1> 'b'
%printer { fprintf (yyoutput, "<field1> printer"); } <field1>
%destructor { fprintf (stdout, "<field1> destructor.\n"); } <field1>
%printer { fprintf (yyo, "<field1> printer"); } <field1>
%destructor { printf ("<field1> destructor.\n"); } <field1>
%type <field0> 'c'
%printer { fprintf (yyoutput, "'c' printer"); } 'c'
%destructor { fprintf (stdout, "'c' destructor.\n"); } 'c'
%printer { fprintf (yyo, "'c' printer"); } 'c'
%destructor { printf ("'c' destructor.\n"); } 'c'
%type <field1> 'd'
%printer { fprintf (yyoutput, "'d' printer"); } 'd'
%destructor { fprintf (stdout, "'d' destructor.\n"); } 'd'
%printer { fprintf (yyo, "'d' printer"); } 'd'
%destructor { printf ("'d' destructor.\n"); } 'd'
%destructor {
#error "<> destructor should not be used."
@@ -1300,10 +1304,10 @@ AT_DATA_GRAMMAR([[input]]$1[[.y]],
%token END 0
%printer {
fprintf (yyoutput, "<]]kind[[> for '%c' @ %d", $$, @$.first_column);
fprintf (yyo, "<]]kind[[> for '%c' @ %d", $$, @$.first_column);
} <]]kind[[>
%destructor {
fprintf (stdout, "<]]kind[[> for '%c' @ %d.\n", $$, @$.first_column);
printf ("<]]kind[[> for '%c' @ %d.\n", $$, @$.first_column);
} <]]kind[[>
%printer {
@@ -1406,7 +1410,7 @@ AT_DATA_GRAMMAR([[input.y]],
%}
%printer {
fprintf (yyoutput, "'%c'", $$);
fprintf (yyo, "'%c'", $$);
} <> <*>
%destructor {
fprintf (stderr, "DESTROY '%c'\n", $$);
@@ -1505,7 +1509,7 @@ AT_DATA_GRAMMAR([[input.y]],
%printer {
char chr = $$;
fprintf (yyoutput, "'%c'", chr);
fprintf (yyo, "'%c'", chr);
} <> <*>
%destructor {
char chr = $$;
@@ -1555,7 +1559,7 @@ AT_DATA_GRAMMAR([[input.y]],
# define LOCATION_PRINT(File, Loc)
%}
%printer { fprintf (yyoutput, "%d", @$); } <>
%printer { fprintf (yyo, "%d", @$); } <>
%destructor { fprintf (stderr, "DESTROY %d\n", @$); } <>
%printer { #error "<*> printer should not be used" } <*>
%destructor { #error "<*> destructor should not be used" } <*>
@@ -1725,6 +1729,7 @@ AT_DATA_GRAMMAR([[input.y]],
# define YYSTYPE sem_type
]AT_CXX_IF([[
# include <cstdio> // EOF.
# include <iostream>
namespace
{
+3 -8
View File
@@ -16,9 +16,8 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# We need 'testsuite.h', (srcdir/test), 'config.h' (builddir/lib), and
# the gnulib headers (srcdir/lib).
CPPFLAGS="-I$abs_top_srcdir/tests -I$abs_top_srcdir/lib -I$abs_top_builddir/lib @CPPFLAGS@"
# We need 'testsuite.h' (srcdir/test).
CPPFLAGS="-I$abs_top_srcdir/tests @CPPFLAGS@"
# 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
@@ -73,11 +72,7 @@ fi
if $BISON_CXX_WORKS; then
# See AT_DATA_SOURCE_PROLOGUE.
cat >conftest.cc <<EOF
#include <config.h>
/* We don't need perfect functions for these tests. */
#undef malloc
#undef memcmp
#undef realloc
#include <testsuite.h>
#include <iostream>
int main ()
+5
View File
@@ -34,6 +34,11 @@ if test -t 2; then
shift
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"
status=$?
+63 -2
View File
@@ -760,7 +760,7 @@ EXTRACT_PRIVATE = 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_BISON_OPTION_POPDEFS
@@ -988,7 +988,8 @@ yy::parser::error (const std::string &m)
# Another file to check syntax_error's linkage.
AT_DATA_SOURCE([scan.cc],
[[#include "input.hh"
[[#include <cstdio> // getchar
#include "input.hh"
// 'a': valid item, 's': syntax error, 'l': lexical error.
int
@@ -1479,3 +1480,63 @@ AT_COMPILE_CXX([parser], [[x[12].o main.cc]], [-Iinclude])
AT_PARSER_CHECK([parser], [0])
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. ##
## ---------------------------------------------------- ##
# -------------- #
# AT_CALC_MAIN. #
# -------------- #
# ------------------------- #
# Helping Autotest macros. #
# ------------------------- #
m4_pushdef([AT_CALC_MAIN], [AT_LANG_DISPATCH([$0], $@)])
# _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],
m4_define([AT_CALC_MAIN(c)],
[[#include <assert.h>
#include <unistd.h>
@@ -113,76 +82,33 @@ main (int argc, const char **argv)
assert (global_count == count); (void) count;
return status;
}
]])])
]])
AT_D_IF([m4_pushdef([AT_CALC_LEX],
[[import std.range.primitives;
import std.stdio;
m4_copy([AT_CALC_MAIN(c)], [AT_CALC_MAIN(c++)])
auto calcLexer(R)(R range)
if (isInputRange!R && is (ElementType!R : dchar))
m4_define([AT_CALC_MAIN(d)],
[[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))
{
R input;
# --------------- #
# AT_CALC_YYLEX. #
# --------------- #
this(R r) { input = r; }
m4_pushdef([AT_CALC_YYLEX], [AT_LANG_DISPATCH([$0], $@)])
public void yyerror (string s)
{
stderr.writeln (s);
}
YYSemanticType semanticVal_;
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],
m4_define([AT_CALC_YYLEX(c)],
[[#include <ctype.h>
]AT_YYLEX_DECLARE_EXTERN[
@@ -257,8 +183,8 @@ read_integer (]AT_YYLEX_FORMALS[)
}
while ((c = get_char (]AT_YYLEX_ARGS[)) == ' ' || c == '\t');
/* Process numbers */
if (c == '.' || isdigit (c))
/* Process numbers. */
if (isdigit (c))
{
unget_char (]AT_YYLEX_PRE_ARGS[ c);
]AT_VAL[.ival = read_integer (]AT_YYLEX_ARGS[);
@@ -273,7 +199,136 @@ read_integer (]AT_YYLEX_FORMALS[)
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],
[[/* Infix notation calculator--calc */
@@ -281,8 +336,6 @@ AT_DATA_GRAMMAR([calc.y],
]AT_CXX_IF([%define global_tokens_and_yystype])[
]AT_D_IF([[
%code imports {
import std.ascii;
import std.stdio;
alias semantic_value = int;
}
]], [[
@@ -346,15 +399,15 @@ void location_print (FILE *o, Span s);
%code
{
#include <assert.h>
#include <string.h>
#define USE(Var)
#include <assert.h>
#include <string.h>
#define USE(Var)
FILE *input;
static int power (int base, int exponent);
FILE *input;
static int power (int base, int exponent);
]AT_YYERROR_DECLARE[
]AT_YYLEX_DECLARE_EXTERN[
]AT_YYERROR_DECLARE[
]AT_YYLEX_DECLARE_EXTERN[
}
]])[
@@ -449,20 +502,18 @@ location_print (FILE *o, Span s)
]])])[
]AT_YYERROR_DEFINE[
]AT_DEFINES_IF([],
[AT_CALC_LEX
[AT_CALC_YYLEX
AT_CALC_MAIN])])
AT_DEFINES_IF([AT_DATA_SOURCE([[calc-lex.]AT_LANG_EXT],
[[#include "calc.]AT_LANG_HDR["
]AT_CALC_LEX])
]AT_CALC_YYLEX])
AT_DATA_SOURCE([[calc-main.]AT_LANG_EXT],
[[#include "calc.]AT_LANG_HDR["
]AT_CALC_MAIN])
])
m4_popdef([AT_CALC_MAIN])
m4_popdef([AT_CALC_LEX])
])# _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
# the skeletons are (or should be) exercized here.
m4_define([AT_CHECK_SPACES],
[AT_CHECK([$PERL -ne '
[AT_PERL_CHECK([-ne '
chomp;
print "$ARGV:$.: {$_}\n"
if (# No starting/ending empty lines.
@@ -578,7 +629,7 @@ m4_define([AT_CHECK_SPACES],
# No tabs.
|| /\t/
)' $1
])dnl
])
])
@@ -598,7 +649,7 @@ AT_DATA_CALC_Y([$1])
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])])
# Test the priorities.
# Test the precedences.
_AT_CHECK_CALC([$1],
[1 + 2 * 3 = 7
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_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([%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([%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}])
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],
[[$end]], [[ab]])
# Only LAC gets it right.
# Only LAC gets it right. In C.
AT_CONSISTENT_ERRORS_CHECK([[%define lr.type canonical-lr
%define parse.lac full]],
[AT_PREVIOUS_STATE_GRAMMAR],
@@ -553,6 +553,20 @@ AT_CONSISTENT_ERRORS_CHECK([[%define lr.type ielr
[AT_PREVIOUS_STATE_INPUT],
[[$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_INPUT])
+198 -15
View File
@@ -18,7 +18,8 @@
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
# 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
# in `input.y`. So use the two-character ^M represent it, and let
# 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_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.
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
# environment.
# 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
@@ -73,31 +76,31 @@ exp: %empty;
[[input.y:9.12-14: <warning>warning:</warning> symbol FOO redeclared [<warning>-Wother</warning>]
9 | %token FOO <warning>FOO</warning> FOO
| <warning>^~~</warning>
input.y:9.8-10: previous declaration
input.y:9.8-10: previous declaration
9 | %token <note>FOO</note> FOO FOO
| <note>^~~</note>
input.y:9.16-18: <warning>warning:</warning> symbol FOO redeclared [<warning>-Wother</warning>]
9 | %token FOO FOO <warning>FOO</warning>
| <warning>^~~</warning>
input.y:9.8-10: previous declaration
input.y:9.8-10: previous declaration
9 | %token <note>FOO</note> FOO FOO
| <note>^~~</note>
input.y:10.8-10: <warning>warning:</warning> symbol FOO redeclared [<warning>-Wother</warning>]
10 | %token <warning>FOO</warning> FOO FOO
| <warning>^~~</warning>
input.y:9.8-10: previous declaration
input.y:9.8-10: previous declaration
9 | %token <note>FOO</note> FOO FOO
| <note>^~~</note>
input.y:10.13-15: <warning>warning:</warning> symbol FOO redeclared [<warning>-Wother</warning>]
10 | %token FOO <warning>FOO</warning> FOO
| <warning>^~~</warning>
input.y:9.8-10: previous declaration
input.y:9.8-10: previous declaration
9 | %token <note>FOO</note> FOO FOO
| <note>^~~</note>
input.y:10.18-20: <warning>warning:</warning> symbol FOO redeclared [<warning>-Wother</warning>]
10 | %token FOO FOO <warning>FOO</warning>
| <warning>^~~</warning>
input.y:9.8-10: previous declaration
input.y:9.8-10: previous declaration
9 | %token <note>FOO</note> FOO FOO
| <note>^~~</note>
]])
@@ -127,18 +130,23 @@ e:
[[input.y:11.4-5: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
11 | a: <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>]
12 | b:<warning>{</warning>
| <warning>^</warning>
| <fixit-insert>%empty</fixit-insert>
input.y:14.3: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
14 | c:
| <warning>^</warning>
| <fixit-insert>%empty</fixit-insert>
input.y:16.2: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
16 | :
| <warning>^</warning>
| <fixit-insert>%empty</fixit-insert>
input.y:17.3: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
17 | e:
| <warning>^</warning>
| <fixit-insert>%empty</fixit-insert>
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>]
11 | a: <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>]
12 | b: <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>]
13 | c: <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>]
14 | d: <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>]
15 | e: <warning>{∇⃗×𝐸⃗ = -∂𝐵⃗/∂t}</warning>
| <warning>^~~~~~~~~~~~~~</warning>
| <fixit-insert>%empty</fixit-insert>
input.y:16.4-17: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
16 | f: <warning>{ 42 }</warning>
| <warning>^~~~~~~~~~~~~~</warning>
| <fixit-insert>%empty</fixit-insert>
input.y:17.4-17: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
17 | g: <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>]
18 | h: <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>]
]])
@@ -210,8 +226,10 @@ b: {}
[[input.y:11.4-5: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
11 | a: <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: <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],
[[input.y:37.8-38.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>
[[input.y:10.8-11.0: <error>error:</error> missing '"' at end of line
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])
@@ -302,12 +483,14 @@ exp : '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
| ^~~~~~~~~~~~
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
| ^~~~~~~~~~~~~~
| %define parse.error verbose
]])
AT_CLEANUP
+2 -2
View File
@@ -1711,10 +1711,10 @@ Reading a token: Now at end of input.
Stack 0 Entering state 7
Now at end of input.
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
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.
Stack 1 Entering state 2
Now at end of input.
+6 -4
View File
@@ -127,8 +127,9 @@ AT_DATA_GRAMMAR([input.y],
%define parse.error verbose
]AT_VARIANT_IF([%token <int> 'x'], [%union {int integer;}])[
%code {
#include <stdio.h> /* printf. */
]AT_PUSH_IF([[
#if defined __GNUC__ && 7 == __GNUC__
#if defined __GNUC__ && (7 == __GNUC__ || 9 == __GNUC__)
# pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif
]])[
@@ -212,8 +213,9 @@ $2
int integer;
}
%{
#include <stdio.h> /* printf. */
]AT_PUSH_IF([[
#if defined __GNUC__ && 7 == __GNUC__
#if defined __GNUC__ && (7 == __GNUC__ || 9 == __GNUC__)
# pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#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)?
# (constant definition), YY_\w+_INCLUDED (header guards).
# YYDEBUG (not renamed) can be read, but not changed.
AT_CHECK([[$PERL -n -0777 -e '
AT_PERL_CHECK([[-n -0777 -e '
s{/\*.*?\*/}{}gs;
s{//.*}{}g;
s{\b((defined|if)\ YYDEBUG
|YYChar
|YYPUSH_MORE(?:_DEFINED)?
|YYUSE
|YY_ATTRIBUTE(?:_PURE|_UNUSED)?
|YY_ATTRIBUTE(?:_PURE|_UNUSED)
|YY_CONSTEXPR
|YY_COPY
|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], [],
[[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
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";
| ^~~~~~~~
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;
| ^~~~~~
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]
1 | %token FOO FOO
| ^~~
input.y:1.8-10: previous declaration
input.y:1.8-10: previous declaration
1 | %token FOO FOO
| ^~~
input.y:2.15-17: warning: symbol BAR redeclared [-Wother]
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
| ^~~
input.y:3.14-16: warning: symbol EOF redeclared [-Wother]
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
| ^~~
]])
@@ -822,16 +822,16 @@ exp: bar;
]])
AT_BISON_CHECK([-fcaret input.y], [1], [],
[[input.y:2.16-18: error: symbol bar is used, but is not defined as a token and has no rules
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]
[[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
| ^~~
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
| ^~~
]])
@@ -1061,9 +1061,9 @@ AT_BISON_CHECK([-fcaret input.y], [1], [],
input.y:2.10-12: error: user token number 42 redeclaration for BAR
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"
| ^~~
| ^~~~~
]])
AT_CLEANUP
@@ -1320,8 +1320,10 @@ yylex (void)
static char const input[] = "@<:@\1\2$@{@oline@__@&t@oline__\
#output "; /* "
*/
static size_t toknum;
assert (toknum < sizeof input);
enum { input_elts = sizeof input };
(void) input_elts;
static int toknum;
assert (0 <= toknum && toknum < input_elts);
yylval = value_as_yystype (input[toknum]);
return input[toknum++];
}
@@ -1521,7 +1523,9 @@ start: TOO_LARGE_DEC TOO_LARGE_HEX
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: 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: user token number of TOO_LARGE_HEX too large
]])
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: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: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:2.1-40: warning: %define variable 'api.push-pull' requires keyword values [-Wdeprecated]
]])
])
@@ -2049,21 +2053,26 @@ AT_DATA([[input.y]],
start: %empty;
]])
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
| ^~~~~~~~~~~~~~~~~~~~~~~~~~
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
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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"
| ^~~~~~~~~~~~~~~~~~~~~~~
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
| ^~~~~~~~~~~~~~~
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}
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| %define api.parser.class {parser}
input.y:2.1-40: error: invalid value for %define Boolean variable 'lr.keep-unreachable-state'
2 | %define lr.keep_unreachable_states maybe
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -2166,18 +2175,13 @@ AT_CLEANUP
# Bison used to accept character literals that were empty or contained
# 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_DATA([empty.y],
AT_DATA_NO_FINAL_EOL([empty.y],
[[%%
start: '';
start: '
]])
AT_CHECK([[$PERL -e "print 'start: \'';" >> empty.y || exit 77]])
start: ']])
AT_BISON_CHECK([-fcaret empty.y], [1], [],
[[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
]])
AT_CHECK([[$PERL -e "print 'start: \'ab';" >> two.y || exit 77]])
start: 'ab]])
AT_BISON_CHECK([two.y], [1], [],
[[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]
]])
AT_DATA([three.y],
AT_DATA_NO_FINAL_EOL([three.y],
[[%%
start: 'abc';
start: 'abc
]])
AT_CHECK([[$PERL -e "print 'start: \'abc';" >> three.y || exit 77]])
start: 'abc]])
AT_BISON_CHECK([three.y], [1], [],
[[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
# (well three with \n): at least Bash 3.2 converts the two-character
# sequence "\0" into a single NUL character.
AT_CHECK([[$PERL -e 'print "start: \"\\\t\\\f\\\0\\\1\" ;";' >> input.y \
|| exit 77]])
AT_PERL_REQUIRE([[-e 'print "start: \"\\\t\\\f\\\0\\\1\" ;";' >> input.y]])
AT_BISON_CHECK([input.y], [1], [],
[[input.y:2.9-12: error: invalid number after \-escape: 777
@@ -2285,6 +2286,7 @@ AT_CLEANUP
## ------------------------- ##
AT_SETUP([[LAC: Errors for %define]])
AT_KEYWORDS([lac])
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
]])
# 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
@@ -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:13.1-20: previous declaration
fix-it:"input.y":{14:1-16:6}:""
input.y:17.9-27: warning: deprecated directive: '%fixed-output_files', use '%fixed-output-files' [-Wdeprecated]
fix-it:"input.y":{17:2-17:21}:"%fixed-output-files"
input.y:18.9-27: warning: duplicate directive: '%fixed_output-files' [-Wother]
input.y:17.9-27: previous declaration
fix-it:"input.y":{18:9-18:28}:""
input.y:19.1-19: warning: duplicate directive: '%fixed-output-files' [-Wother]
input.y:17.9-27: previous declaration
fix-it:"input.y":{19:1-19:20}:""
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}:"%output \"y.tab.c\""
input.y:18.9-27: warning: deprecated directive: '%fixed_output-files', use '%output "y.tab.c"' [-Wdeprecated]
fix-it:"input.y":{18:9-18:28}:"%output \"y.tab.c\""
input.y:19.1-19: warning: deprecated directive: '%fixed-output-files', use '%output "y.tab.c"' [-Wdeprecated]
fix-it:"input.y":{19:1-19:20}:"%output \"y.tab.c\""
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}"
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
%expect-rr 0
%file-prefix "foo"
%fixed-output-files
@&t@
%output "y.tab.c"
%output "y.tab.c"
%output "y.tab.c"
%define api.prefix {foo}
%no-default-prec
%no-default-prec
@@ -2712,7 +2723,6 @@ AT_DATA_GRAMMAR([[input.y]],
%file-prefix "foo"
%file-prefix
"bar"
%fixed-output-files
%no-default-prec
%no-lines
%output "foo"
@@ -2751,3 +2761,37 @@ AT_BISON_CHECK([[-fcaret input.y]], [[0]], [[]],
AT_BISON_OPTION_POPDEFS
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],
[[/* Infix notation calculator--calc */
%language "Java"
%name-prefix "Calc"
%define api.prefix {Calc}
%define api.parser.class {Calc}
%define public
@@ -127,17 +127,17 @@ class CalcLexer implements Calc.Lexer {
]])[
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.resetSyntax ();
st.eolIsSignificant (true);
st.whitespaceChars (9, 9);
st.whitespaceChars (32, 32);
st.wordChars (48, 57);
st.whitespaceChars ('\t', '\t');
st.whitespaceChars (' ', ' ');
st.wordChars ('0', '9');
}
AT_LOCATION_IF([[
]AT_LOCATION_IF([[
Position yypos = new Position (1, 0);
public Position getStartPos() {
@@ -157,15 +157,14 @@ AT_LOCATION_IF([[
}
public int yylex () throws IOException {
int ttype = st.nextToken ();
]AT_LOCATION_IF([[yypos = new Position (yypos.lineno (),
yypos.token () + 1);]])[
int ttype = st.nextToken ();]AT_LOCATION_IF([[
yypos = new Position (yypos.lineno (), yypos.token () + 1);]])[
if (ttype == st.TT_EOF)
return EOF;
else if (ttype == st.TT_EOL)
{
]AT_LOCATION_IF([[yypos = new Position (yypos.lineno () + 1, 0);]])[
{]AT_LOCATION_IF([[
yypos = new Position (yypos.lineno () + 1, 0);]])[
return (int) '\n';
}
@@ -251,7 +250,7 @@ $2
AT_BISON_CHECK([-Wno-deprecated -o Calc.java Calc.y])
AT_JAVA_COMPILE([Calc.java])
# Test the priorities.
# Test the precedences.
AT_DATA([[input]],
[[1 + 2 * 3 = 7
1 + 2 * -3 = -5
@@ -445,6 +444,9 @@ AT_CHECK_JAVA_GREP([[class YYParser]])
AT_CHECK_JAVA_MINIMAL([[%name-prefix "Prefix"]])
AT_CHECK_JAVA_GREP([[class PrefixParser]])
AT_CHECK_JAVA_MINIMAL([[%define api.prefix {Prefix}]])
AT_CHECK_JAVA_GREP([[class PrefixParser]])
AT_CHECK_JAVA_MINIMAL([[%define api.token.prefix {TOK_}]])
AT_CHECK_JAVA_GREP([[.*TOK_END.*]])

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