Compare commits

..
47 Commits
Author SHA1 Message Date
Akim Demaille 5d501ee728 version 3.7.3
* NEWS: Record release date.
2020-10-13 07:01:24 +02:00
Akim Demaille bc5e4541da build: don't link bison against libreadline
Reported by Paul Smith <[email protected]>.
https://lists.gnu.org/r/bug-bison/2020-10/msg00001.html

* src/local.mk (src_bison_LDADD): here.
2020-10-13 06:57:33 +02:00
Akim Demaille 567d1eaa19 gnulib: update 2020-10-13 06:46:06 +02:00
Akim Demaille c08e0863be glr.cc: fix: use symbol_name
* data/skeletons/glr.cc: here.
2020-09-27 09:22:02 +02:00
Akim Demaille 541943ee04 build: fix a concurrent build issue in examples
Reported by Thomas Deutschmann <[email protected]>.
https://lists.gnu.org/r/bug-bison/2020-09/msg00010.html

* examples/c/lexcalc/local.mk: scan.o depends on parse.[ch].
2020-09-06 10:08:22 +02:00
Akim Demaille dcdd119f69 maint: post-release administrivia
* NEWS: Add header line for next release.
* .prev-version: Record previous version.
* cfg.mk (old_NEWS_hash): Auto-update.
2020-09-05 18:31:25 +02:00
Akim Demaille a0bc06b703 version 3.7.2
* NEWS: Record release date.
2020-09-05 18:06:16 +02:00
Akim Demaille 5e33dfe59d build: disable syntax-check warning
error_message_uppercase
etc/bench.pl.in-419-static int yylex (@{[is_pure (@directive) ? "YYSTYPE *yylvalp" : "void"]});

* cfg.mk: here.
2020-09-05 17:59:56 +02:00
Akim Demaille 2a4e9a358f gnulib: update 2020-09-05 17:44:38 +02:00
Akim Demaille f7b642cff7 build: fix incorrect dependencies
Commit af000bab11 ("doc: work around
Texinfo 6.7 bug"), published in 3.4.91, added a dependency on the
"all" target.

This is a super bad idea, since "make all" will run this
target *before* "all", which builds bison.  It turns out that this new
dependency actually needed bison to be built.  So all the regular
process (i) build $(BUILT_SOURCES) and then (ii) build bison, was
wrecked since some of the $(BUILT_SOURCES) depended on bison...

It was "easy" to see in the logs of "make V=1" because we were
building bison files (such as src/files.o) *before* displaying the
banner for "all-recursive".  With this fix, we finally get again the
proper sequence:

    rm -f examples/c/reccalc/scan.stamp examples/c/reccalc/scan.stamp.tmp
    /opt/local/libexec/gnubin/mkdir -p examples/c/reccalc
    touch examples/c/reccalc/scan.stamp.tmp
    flex   -oexamples/c/reccalc/scan.c --header=examples/c/reccalc/scan.h ./examples/c/reccalc/scan.l
    mv examples/c/reccalc/scan.stamp.tmp examples/c/reccalc/scan.stamp
    rm -f lib/fcntl.h-t lib/fcntl.h && \
    { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
      ...
    } > lib/fcntl.h-t && \
    mv lib/fcntl.h-t lib/fcntl.h
    ...
    mv -f lib/alloca.h-t lib/alloca.h
    make  all-recursive

Reported by Mingli Yu <[email protected]>.
https://github.com/akimd/bison/issues/31
https://lists.gnu.org/r/bison-patches/2020-05/msg00055.html

Reported by Claudio Calvelli <[email protected]>.
https://lists.gnu.org/r/bug-bison/2020-09/msg00001.html
https://bugs.gentoo.org/716516

* doc/local.mk (all): Rename as...
(all-local): this.
So that we don't compete with BUILT_SOURCES.
2020-09-05 17:42:20 +02:00
Akim Demaille 3da17724ad doc: updates
* NEWS, TODO: here.
2020-09-02 21:37:23 +02:00
Akim Demaille 68e3e442f9 gnulib: update 2020-08-30 17:32:43 +02:00
Akim Demaille e432619d11 tests: beware of sed portability issues
Reported by David Laxer <[email protected]>.
https://lists.gnu.org/r/bug-bison/2020-08/msg00027.html

* tests/output.at: Don't use + with sed.
While at it, fix a quotation problem hidden by the use of '#'.
2020-08-30 17:16:18 +02:00
Akim Demaille a1b7fef045 c: always use YYMALLOC/YYFREE
Reported by Kovalex <[email protected]>.
https://lists.gnu.org/r/bug-bison/2020-08/msg00015.html

* data/skeletons/yacc.c: Don't make direct calls to malloc/free.
* tests/calc.at: Check it.
2020-08-30 10:05:18 +02:00
Akim Demaille 067e35a8be build: beware of POSIX mode
Reported by Dennis Clarke.
https://lists.gnu.org/r/bug-bison/2020-08/msg00013.html

* examples/d/local.mk, examples/java/calc/local.mk,
* examples/java/simple/local.mk: Pass bison's options before its
argument, in case we're in POSIX mode.
2020-08-30 09:38:05 +02:00
Akim Demaille 0522047c96 doc: history of api.prefix
Reported by Matthew Fernandez <[email protected]>.
https://lists.gnu.org/r/help-bison/2020-08/msg00015.html

* doc/bison.texi (api.prefix): We move to {} in 3.0.
2020-08-30 09:29:00 +02:00
Akim Demaille 3724b50ef9 CI: intel moved the script for ICC
* .travis.yml: Adjust.
2020-08-11 07:18:48 +02:00
Akim Demaille b801b7b670 fix: unterminated \-escape
An assertion failed when the last character is a '\' and we're in a
character or a string.
Reported by Agency for Defense Development.
https://lists.gnu.org/r/bug-bison/2020-08/msg00009.html

* src/scan-gram.l: Catch unterminated escapes.
* tests/input.at (Unexpected end of file): New.
2020-08-08 07:53:33 +02:00
Akim Demaille b7aab2dbad fix: crash when redefining the EOF token
Reported by Agency for Defense Development.
https://lists.gnu.org/r/bug-bison/2020-08/msg00008.html

On an empty such as

    %token FOO
           BAR
           FOO 0
    %%
    input: %empty

we crash because when we find FOO 0, we decrement ntokens (since FOO
was discovered to be EOF, which is already known to be a token, so we
increment ntokens for it, and need to cancel this).  This "works well"
when EOF is properly defined in one go, but here it is first defined
and later only assign token code 0.  In the meanwhile BAR was given
the token number that we just decremented.

To fix this, assign symbol numbers after parsing, not during parsing,
so that we also saw all the explicit token codes.  To maintain the
current numbers (I'd like to keep no difference in the output, not
just equivalence), we need to make sure the symbols are numbered in
the same order: that of appearance in the source file.  So we need the
locations to be correct, which was almost the case, except for nterms
that appeared several times as LHS (i.e., several times as "foo:
...").  Fixing the use of location_of_lhs sufficed (it appears it was
intended for this use, but its implementation was unfinished: it was
always set to "false" only).

* src/symtab.c (symbol_location_as_lhs_set): Update location_of_lhs.
(symbol_code_set): Remove broken hack that decremented ntokens.
(symbol_class_set, dummy_symbol_get): Don't set number, ntokens and
nnterms.
(symbol_check_defined): Do it.
(symbols): Don't count nsyms here.
Actually, don't count nsyms at all: let it be done in...
* src/reader.c (check_and_convert_grammar): here.  Define nsyms from
ntokens and nnterms after parsing.
* tests/input.at (EOF redeclared): New.

* examples/c/bistromathic/bistromathic.test: Adjust the traces: in
"%nterm <double> exp %% input: ...", exp used to be numbered before
input.
2020-08-07 07:30:06 +02:00
Akim Demaille 89e42ffb4b style: fix missing space before paren
* cfg.mk (_space_before_paren_exempt): Be less laxist.
* src/output.c, src/reader.c: Fix space before paren issues.
Pacify the warnings where applicable.
2020-08-07 07:30:06 +02:00
Akim Demaille 6aae4a7378 style: fix comments and more debug trace
* src/location.c, src/symtab.h, src/symtab.c: here.
2020-08-07 07:30:06 +02:00
Akim Demaille 7d4a4300c2 style: more uses of const
* src/symtab.c: here.
2020-08-07 07:30:06 +02:00
Akim Demaille 31d4ec28bd bench: fix support for pure parser
* etc/bench.pl.in (is_pure): New.
(generate_grammar_calc): Use code provides where needed.
Use is_pure to call yylex properly.
Coding style fixes.
2020-08-07 07:29:16 +02:00
Akim Demaille 0a5bfb4fda portability: multiple typedefs
Older versions of GCC (4.1.2 here) don't like repeated typedefs.

      CC       src/bison-parse-simulation.o
    src/parse-simulation.c:61: error: redefinition of typedef 'parse_state'
    src/parse-simulation.h:74: error: previous declaration of 'parse_state' was here
    make: *** [Makefile:7876: src/bison-parse-simulation.o] Error 1

Reported by Nelson H. F. Beebe.

* src/parse-simulation.c (parse_state): Don't typedef,
parse-simulation.h did it already.
2020-08-03 07:30:35 +02:00
Akim Demaille 12d0b15679 style: revert "avoid warnings with GCC 4.6"
This reverts commit d0bec3175f (which
should have read "We have a clash...", not "With have a clash...").
Now that `max()` was renamed `max_int()`, we can use `max` again, as
elsewhere in the code.

* src/counterexample.c (visited_hasher): Alpha reconversion.
2020-08-02 10:20:23 +02:00
Akim Demaille cb7dcb011e maint: post-release administrivia
* NEWS: Add header line for next release.
* .prev-version: Record previous version.
* cfg.mk (old_NEWS_hash): Auto-update.
2020-08-02 09:32:34 +02:00
Akim Demaille 71579c7219 version 3.7.1
* NEWS: Record release date.
2020-08-02 09:10:02 +02:00
Akim Demaille 2f8a874215 portability: we use termios.h and sys/ioctl.h
Reported by Maarten De Braekeleer.
https://lists.gnu.org/r/bison-patches/2020-07/msg00079.html

* bootstrap.conf (gnulib_modules): Add termios and sys_ioctl.
2020-08-02 08:36:49 +02:00
Maarten De BraekeleerandAkim Demaille ad6f600bb1 portability: rename accept to acceptsymbol because of MSVC
MSVC already defines this symbol.

* src/symtab.h, src/symtab.c (accept): Rename as...
(acceptsymbol): this.
Adjust dependencies.
2020-08-02 08:32:57 +02:00
Akim Demaille de4f41eab7 regen 2020-08-02 08:32:57 +02:00
Maarten De BraekeleerandAkim Demaille e73f086b0d portability: use CHAR_LITERAL instead of CHAR because MSVC defines CHAR
* src/parse-gram.y, src/scan-gram.l: here.
2020-08-02 08:32:57 +02:00
Maarten De BraekeleerandAkim Demaille 8cf098415e portability: use INT_LITERAL instead of INT because MSVC defines INT
It is defined as a typedef, not a macro.
https://lists.gnu.org/r/bison-patches/2020-08/msg00001.html

* src/parse-gram.y, src/scan-gram.l: here.
2020-08-02 08:32:30 +02:00
Akim Demaille 977e19840d portability: beware of max () with MSVC
Reported by Maarten De Braekeleer.
https://lists.gnu.org/r/bison-patches/2020-07/msg00080.html

We don't want to use gnulib's min and max macros, since we use
function calls in min/max arguments.

* src/location.c (max_int, min_int): Move to...
* src/system.h: here.
* src/counterexample.c, src/derivation.c: Use max_int instead of max.
2020-08-02 08:19:35 +02:00
Akim Demaille d975c2f76e libtextstyle: be sure to have ostream_printf and hyperlink support
Older versions of libtextstyle do not support them, rule them out.

Reported by Lars Wendler
https://lists.gnu.org/r/bug-bison/2020-07/msg00030.html

and by Arnold Robbins
https://lists.gnu.org/r/bug-bison/2020-07/msg00041.html and
https://lists.gnu.org/mailman/private/gawk-devel/2020-July/003988.html

and by Nelson H. F. Beebe
https://lists.gnu.org/mailman/private/gawk-devel/2020-July/003993.html

With support from Bruno Haible in gnulib
https://lists.gnu.org/r/bug-gnulib/2020-08/msg00000.html
thread starting at
https://lists.gnu.org/r/bug-gnulib/2020-07/msg00148.html

* configure.ac: Require libtextstyle 0.20.5.
* gnulib: Update.
2020-08-02 08:19:35 +02:00
Akim Demaille 0676801b8c CI: comment changes 2020-08-01 10:02:44 +02:00
Akim Demaille 82aa96e9b1 regen 2020-08-01 08:54:46 +02:00
Akim Demaille cb65553449 diagnostics: better location for type redeclarations
From

    foo.y:1.7-11: error: %type redeclaration for bar
        1 | %type <foo> bar bar
          |       ^~~~~
    foo.y:1.7-11: note: previous declaration
        1 | %type <foo> bar bar
          |       ^~~~~

to

    foo.y:1.17-19: error: %type redeclaration for bar
        1 | %type <foo> bar bar
          |                 ^~~
    foo.y:1.13-15: note: previous declaration
        1 | %type <foo> bar bar
          |             ^~~

* src/symlist.h, src/symlist.c (symbol_list_type_set): There's no need
for the tag's location, use that of the symbol.
* src/parse-gram.y: Adjust.
* tests/input.at: Adjust.
2020-08-01 08:54:46 +02:00
Akim Demaille f47a1bd622 todo: updates for D 2020-07-30 07:14:57 +02:00
Akim Demaille 205d372c68 cex: style: comment changes
* src/parse-simulation.c: here.
2020-07-29 20:00:59 +02:00
Akim Demaille 07a1243b40 cex: style: prefer "res" for the returned value
* src/derivation.c (derivation_new): here.
2020-07-29 20:00:59 +02:00
Akim Demaille ece343d2c2 cex: style: prefer FOO_print to print_FOO
* src/state-item.h, src/state-item.c (print_state_item): Rename as...
(state_item_print): this.
* src/counterexample.c (print_counterexample): Rename as...
(counterexample_print): this.
2020-07-29 20:00:27 +02:00
Akim Demaille be95a4fe29 scanner: don't crash on strings containing a NUL byte
We crash if the input contains a string containing a NUL byte.
Reported by Suhwan Song.
https://lists.gnu.org/r/bug-bison/2020-07/msg00051.html

* src/flex-scanner.h (STRING_FREE): Avoid accidental use of
last_string.
* src/scan-gram.l: Don't call STRING_FREE without calling
STRING_FINISH first.
* tests/input.at (Invalid inputs): Check that case.
2020-07-28 19:01:48 +02:00
Akim Demaille 6accee7716 doc: refer to cex from sections dealing with conflicts
The documentation about -Wcex should be put forward.

* doc/bison.texi: Refer to -Wcex from the sections about conflicts.
2020-07-28 07:45:07 +02:00
Akim Demaille e63f22703e doc: factor ifnottex/iftex examples
* doc/bison.texi: Factor the common bits out of ifnottex/iftex.
2020-07-28 07:45:07 +02:00
Akim Demaille fa390dc311 doc: fix colors
The original Texinfo macros introducing colors were made for
diagnostics, which are printed in bold.  So by copy-paste accident the
styles we introduced for counterexamples were also in bold.  They
should not.

* doc/bison.texi: Separate the styling of diagnostics from the styling
for counterexamples.
Don't use bold in the latter case.
2020-07-28 07:45:07 +02:00
Akim Demaille 17fdf5eca2 doc: fixes
* doc/bison.texi: Fix spello.
Fix missing colors, and factor.
2020-07-28 07:45:07 +02:00
Akim Demaille 72b3c1a673 maint: post-release administrivia
* NEWS: Add header line for next release.
* .prev-version: Record previous version.
* cfg.mk (old_NEWS_hash): Auto-update.
2020-07-23 20:15:38 +02:00
48 changed files with 927 additions and 357 deletions
+1 -1
View File
@@ -1 +1 @@
3.6.93 3.7.2
+4 -1
View File
@@ -50,6 +50,7 @@ jobs:
- make -j2 dist-xz - make -j2 dist-xz
# Can help understanding why we get "dirty" tarballs. # Can help understanding why we get "dirty" tarballs.
- git status - git status
- git diff
- dist=$(echo bison*.xz) - dist=$(echo bison*.xz)
# Unfortunately we cannot deterministically know the name of the tarball without the full # Unfortunately we cannot deterministically know the name of the tarball without the full
@@ -119,6 +120,8 @@ jobs:
- CXX='clang++-10 -fsanitize=address -stdlib=libc++' - CXX='clang++-10 -fsanitize=address -stdlib=libc++'
- PART=2 - PART=2
# See https://github.com/simd-everywhere/simde/blob/master/.travis.yml
# and https://software.intel.com/content/www/us/en/develop/documentation/get-started-with-intel-oneapi-render-linux/top/configure-your-system.html.
- name: "ICC" - name: "ICC"
stage: check stage: check
os: linux os: linux
@@ -127,7 +130,7 @@ jobs:
- CC=icc - CC=icc
- CXX=icpc - CXX=icpc
install: install:
- source /opt/intel/inteloneapi/compiler/latest/env/vars.sh - source /opt/intel/oneapi/compiler/latest/env/vars.sh
addons: addons:
apt: apt:
sources: sources:
+52 -1
View File
@@ -1,5 +1,55 @@
GNU Bison NEWS GNU Bison NEWS
* Noteworthy changes in release 3.7.3 (2020-10-13) [stable]
** Bug fixes
Fix concurrent build issues.
The bison executable is no longer linked uselessly against libreadline.
Fix incorrect use of yytname in glr.cc.
* Noteworthy changes in release 3.7.2 (2020-09-05) [stable]
This release of Bison fixes all known bugs reported for Bison in MITRE's
Common Vulnerabilities and Exposures (CVE) system. These vulnerabilities
are only about bison-the-program itself, not the generated code.
Although these bugs are typically irrelevant to how Bison is used, they
are worth fixing if only to give users peace of mind.
There is no known vulnerability in the generated parsers.
** Bug fixes
Fix concurrent build issues (introduced in Bison 3.5).
Push parsers always use YYMALLOC/YYFREE (no direct calls to malloc/free).
Fix portability issues of the test suite, and of bison itself.
Some unlikely crashes found by fuzzing have been fixed. This is only
about bison itself, not the generated parsers.
* Noteworthy changes in release 3.7.1 (2020-08-02) [stable]
** Bug fixes
Crash when a token alias contains a NUL byte.
Portability issues with libtextstyle.
Portability issues of Bison itself with MSVC.
** Changes
Improvements and fixes in the documentation.
More precise location about symbol type redefinitions.
* Noteworthy changes in release 3.7 (2020-07-23) [stable] * Noteworthy changes in release 3.7 (2020-07-23) [stable]
** Deprecated features ** Deprecated features
@@ -537,7 +587,8 @@ GNU Bison NEWS
\005) with incorrect styling. Fixes for similar issues with unexpectedly \005) with incorrect styling. Fixes for similar issues with unexpectedly
short lines (e.g., the file was changed between parsing and diagnosing). short lines (e.g., the file was changed between parsing and diagnosing).
Several unlikely crashes found by fuzzing have been fixed. Some unlikely crashes found by fuzzing have been fixed. This is only
about bison itself, not the generated parsers.
* Noteworthy changes in release 3.5.2 (2020-02-13) [stable] * Noteworthy changes in release 3.5.2 (2020-02-13) [stable]
+12 -3
View File
@@ -42,9 +42,11 @@ installing it. In that case, do not use `src/bison`: it would use the
As an experimental feature, diagnostics are now colored, controlled by the As an experimental feature, diagnostics are now colored, controlled by the
`--color` and `--style` options. `--color` and `--style` options.
To use them, install the libtextstyle library before configuring Bison. It To use them, install the libtextstyle library, 0.20.5 or newer, before
is available from https://alpha.gnu.org/gnu/gettext/, for instance configuring Bison. It is available from https://alpha.gnu.org/gnu/gettext/,
https://alpha.gnu.org/pub/gnu/gettext/libtextstyle-0.20.5.tar.gz. for instance https://alpha.gnu.org/gnu/gettext/libtextstyle-0.20.5.tar.gz,
or as part of Gettext 0.21 or newer, for instance
https://ftp.gnu.org/gnu/gettext/gettext-0.21.tar.gz.
The option --color supports the following arguments: The option --color supports the following arguments:
- always, yes: Enable colors. - always, yes: Enable colors.
@@ -61,6 +63,13 @@ To customize the styles, create a CSS file, say `bison-bw.css`, similar to
then invoke bison with `--style=bison-bw.css`, or set the `BISON_STYLE` then invoke bison with `--style=bison-bw.css`, or set the `BISON_STYLE`
environment variable to `bison-bw.css`. environment variable to `bison-bw.css`.
In some diagnostics, bison uses libtextstyle to emit special escapes to
generate clickable hyperlinks. The environment variable
`NO_TERM_HYPERLINKS` can be used to suppress them. This may be useful for
terminal emulators which produce garbage output when they receive the escape
sequence for a hyperlink. Currently (as of 2020), this affects some versions
of emacs, guake, konsole, lxterminal, rxvt, yakuake.
## Relocatability ## Relocatability
If you pass `--enable-relocatable` to `configure`, Bison is relocatable. If you pass `--enable-relocatable` to `configure`, Bison is relocatable.
+3
View File
@@ -106,9 +106,11 @@ Keith Browne [email protected]
Ken Moffat [email protected] Ken Moffat [email protected]
Kiyoshi Kanazawa [email protected] Kiyoshi Kanazawa [email protected]
Lars Maier [email protected] Lars Maier [email protected]
Lars Wendler [email protected]
László Várady [email protected] László Várady [email protected]
Laurent Mascherpa [email protected] Laurent Mascherpa [email protected]
Lie Yan [email protected] Lie Yan [email protected]
Maarten De Braekeleer [email protected]
Magnus Fromreide [email protected] Magnus Fromreide [email protected]
Marc Autret [email protected] Marc Autret [email protected]
Marc Mendiola [email protected] Marc Mendiola [email protected]
@@ -185,6 +187,7 @@ Simon Sobisch [email protected]
Stefano Lattarini [email protected] Stefano Lattarini [email protected]
Stephen Cameron [email protected] Stephen Cameron [email protected]
Steve Murphy [email protected] Steve Murphy [email protected]
Suhwan Song [email protected]
Sum Wu [email protected] Sum Wu [email protected]
Théophile Ranquet [email protected] Théophile Ranquet [email protected]
Thiru Ramakrishnan [email protected] Thiru Ramakrishnan [email protected]
+306 -16
View File
@@ -1,4 +1,12 @@
* Bison 3.7 * Soon
** gnulib
Bruno notes:
> I haven't looked deeply, but it strikes me that gnulib/lib/bitset/array.c
> does not make use of the 'ffsl' function, nor or the 'integer_length_l'
> function. Maybe because in Bison, all bitsets are so dense that it does
> not give a performance advantage?
** Cex ** Cex
*** Improve gnulib *** Improve gnulib
Don't do this (counterexample.c): Don't do this (counterexample.c):
@@ -48,13 +56,6 @@ Unless we play it dumb (little structure).
- promote YYEOF rather than EOF. - promote YYEOF rather than EOF.
*** D
- is there a way to attach yysymbol_name to the enum itself? As we did
in Java.
- It would be better to have TokenKind as return value. Can we use
reflection to support both output types?
** YYerror ** YYerror
https://git.savannah.gnu.org/gitweb/?p=gettext.git;a=blob;f=gettext-runtime/intl/plural.y;h=a712255af4f2f739c93336d4ff6556d932a426a5;hb=HEAD https://git.savannah.gnu.org/gitweb/?p=gettext.git;a=blob;f=gettext-runtime/intl/plural.y;h=a712255af4f2f739c93336d4ff6556d932a426a5;hb=HEAD
@@ -67,7 +68,7 @@ Stop hard-coding "Calc". Adjust local.at (look for FIXME).
** A dev warning for b4_ ** A dev warning for b4_
Maybe we should check for m4_ and b4_ leaking out of the m4 processing, as Maybe we should check for m4_ and b4_ leaking out of the m4 processing, as
Autoconf does. It would have caught overquotation issues. Autoconf does. It would have caught over-quotation issues.
** doc ** doc
I feel it's ugly to use the GNU style to declare functions in the doc. It I feel it's ugly to use the GNU style to declare functions in the doc. It
@@ -88,7 +89,7 @@ push parsers on top of pull parser. Which is currently not relevant, since
push parsers are measurably slower. push parsers are measurably slower.
** %define parse.error formatted ** %define parse.error formatted
How about pushing bistromathics' yyreport_syntax_error as another standard How about pushing Bistromathic's yyreport_syntax_error as another standard
way to generate the error message, and leave to the user the task of way to generate the error message, and leave to the user the task of
providing the message formats? Currently in bistro, it reads: providing the message formats? Currently in bistro, it reads:
@@ -202,18 +203,282 @@ The "automaton" and "set" categories are not so useful. We should probably
introduce lr(0) and lalr, just the way we have ielr categories. The introduce lr(0) and lalr, just the way we have ielr categories. The
"closure" function is too verbose, it should probably have its own category. "closure" function is too verbose, it should probably have its own category.
"set" can still be used for summariring the important sets. That would make "set" can still be used for summarizing the important sets. That would make
tests easy to maintain. tests easy to maintain.
*** complain.* *** complain.*
Rename these guys as "diagnostics.*" (or "diagnose.*"), since that's the Rename these guys as "diagnostics.*" (or "diagnose.*"), since that's the
name they have in gcc, clang, etc. Likewise for the complain_* series of name they have in GCC, clang, etc. Likewise for the complain_* series of
functions. functions.
*** ritem *** ritem
states/nstates, rules/nrules, ..., ritem/nritems states/nstates, rules/nrules, ..., ritem/nritems
Fix the latter. Fix the latter.
* D programming language
There's a number of features that are missing, here sorted in _suggested_
order of implementation.
When copying code from other skeletons, keep the comments exactly as they
are. Keep the same variable names. If you change the wording in one place,
do it in the others too. In other words: make sure to keep the
maintenance *simple* by avoiding any gratuitous difference.
** Rename the D example
Move the current content of examples/d into examples/d/simple.
** Create a second example
Duplicate examples/d/simple into examples/d/calc.
** Add location tracking to d/calc
Look at the examples in the other languages to see how to do that.
** yysymbol_name
The SymbolKind is an enum. For a given SymbolKind we want to get its string
representation. Currently it's a separate table in the parser that does
that:
/* Symbol kinds. */
public enum SymbolKind
{
S_YYEMPTY = -2, /* No symbol. */
S_YYEOF = 0, /* "end of file" */
S_YYerror = 1, /* error */
S_YYUNDEF = 2, /* "invalid token" */
S_EQ = 3, /* "=" */
...
S_input = 14, /* input */
S_line = 15, /* line */
S_exp = 16, /* exp */
};
...
/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
First, the terminals, then, starting at \a yyntokens_, nonterminals. */
private static immutable string[] yytname_ =
[
"\"end of file\"", "error", "\"invalid token\"", "\"=\"", "\"+\"",
"\"-\"", "\"*\"", "\"/\"", "\"(\"", "\")\"", "\"end of line\"",
"\"number\"", "UNARY", "$accept", "input", "line", "exp", null
];
...
So to get a symbol kind, one runs `yytname_[yykind]`.
Is there a way to attach this conversion to string to SymbolKind? In Java
for instance, we have:
public enum SymbolKind
{
S_YYEOF(0), /* "end of file" */
S_YYerror(1), /* error */
S_YYUNDEF(2), /* "invalid token" */
...
S_input(16), /* input */
S_line(17), /* line */
S_exp(18); /* exp */
private final int yycode_;
SymbolKind (int n) {
this.yycode_ = n;
}
...
/* YYNAMES_[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
First, the terminals, then, starting at \a YYNTOKENS_, nonterminals. */
private static final String[] yynames_ = yynames_init();
private static final String[] yynames_init()
{
return new String[]
{
i18n("end of file"), i18n("error"), i18n("invalid token"), "!", "+", "-", "*",
"/", "^", "(", ")", "=", i18n("end of line"), i18n("number"), "NEG",
"$accept", "input", "line", "exp", null
};
}
/* The user-facing name of this symbol. */
public final String getName() {
return yynames_[yycode_];
}
};
which allows to write more naturally `yykind.getName()` rather than
`yytname_[yykind]`. Is there something comparable in (idiomatic) D?
** Change the return value of yylex
Historically people were allowed to return any int from the scanner (which
is convenient and allows `return '+'` from the scanner). Akim tends to see
this as an error, we should restrict the return values to TokenKind (not to
be confused with SymbolKind).
In the case of D, without the history, we have the choice to support or not
`int`. If we want to _keep_ `int`, is there a way, say via introspection,
to support both signatures of yylex? If we don't keep `int`, just move to
TokenKind.
** Documentation
Write documentation about D support in doc/bison.texi. Imitate the Java
documentation. You should be more succinct IMHO.
** Complete Symbols
The current interface from the scanner to the parser is somewhat clumsy: the
token kind is returned by yylex, but the value and location are stored in
the scanner. This reflects the fact that the implementation of the parser
uses three variables to deal with each parsed symbol: its kind, its value,
its location.
So today the scanner of examples/d/calc.d (no locations) looks like:
if (input.front.isNumber)
{
import std.conv : parse;
semanticVal_.ival = input.parse!int;
return TokenKind.NUM;
}
and the generated parser:
/* Read a lookahead token. */
if (yychar == TokenKind.YYEMPTY)
{
yychar = yylex ();
yylval = yylexer.semanticVal;
}
The parser class should feature a `Symbol` type which binds together kind,
value and location, and the scanner should be able to return an instance of
that type. Something like
if (input.front.isNumber)
{
import std.conv : parse;
return parser.Symbol (TokenKind.NUM, input.parse!int);
}
** Token Constructors
In the previous example it is possible to mix incorrectly kinds and values,
and for instance:
return parser.Symbol (TokenKind.NUM, "Hello, World!\n");
attaches a string value to NUM kind (wrong, of course). When
api.token.constructor is set, in C++, Bison generated "token constructors":
parser.make_NUM. parser.make_PLUS, parser.make_STRING, etc. The previous
example becomes
return parser.make_NUM ("Hello, World!\n");
which would easily be caught by the type checker.
** Lookahead Correction
Add support for LAC to the D skeleton. It should not be too hard: look how
this is done in lalr1.cc, and mock it.
** Push Parser
Add support for push parser. Do not start a nice skeleton, just enhance the
current one to support push parsers. This is going to be a tougher nut to
crack.
First, you need to understand well how the push parser is expected to work.
To this end:
- read the doc
- look at examples/c/pushcalc
- create an example of a Java push parser.
- have a look at the generated parser in Java, which has the advantage of
being already based on a parser object, instead of just a function.
The C case is harder to read, but it may help too. Keep in mind that
because there's no object to maintain state, the C push parser uses some
struct (yypstate) to preserve this state. We don't need this in D, the
parser object will suffice.
I think working directly on the skeleton to add push-parser support is not
the simplest path. I suggest that you (1) transform a generated parser into
a push parser by hand, and then (2) transform lalr1.d to generate such a
parser.
Use `git commit` frequently to make sure you keep track of your progress.
*** (1.a) Prepare pull parser by hand
Copy again one of the D examples into say examples/d/pushcalc. Also
check-in the generated parser to facilitate experimentation.
- find local variables of yyparse should become members of the parser object
(so that we preserve state from one call to the next).
- do it in your generated D parser. We don't need an equivalent for
yypstate, because we already have it: that the parser object itself.
- have your *pull*-parser (i.e., the good old yy::parser::parse()) work
properly this way. Write and run tests. That's one of the reasons I
suggest using examples/d/calc as a starting point: it already has tests,
you can/should add more.
At this point you have a pull-parser which you prepared to turn into a
push-parser.
*** (1.b) Turn pull parser into push parser by hand
- look again at how push parsers are implemented in Java/C to see what needs
to change in yyparse so that the control is inverted: parse() will
be *given* the tokens, instead of having to call yylex itself. When I say
"look at C", I think your best option are (i) yacc.c (look for b4_push_if)
and (ii) examples/c/pushcalc.
- rename parse() as push_parse(Symbol yyla) (or push_parse(TokenKind, Value,
Location)) that takes the symbol as argument. That's the push parser we
are looking for.
- define a new parse() function which has the same signature as the usual
pull-parser, that repeatedly calls the push_parse function. Something
like this:
int parse ()
{
int status = 0;
do {
status = this->push_parse (yylex());
} while (status == YYPUSH_MORE);
return status;
}
- show me that parser, so that we can validate the approach.
*** (2) Port that into the skeleton
- once we agree on the API of the push parser, implement it into lalr1.d.
You will probaby need help on this regard, but imitation, again, should
help.
- have example/d/pushcalc work properly and pass tests
- add tests in the "real" test suite. Do that in tests/calc.at. I can
help.
- document
** GLR Parser
This is very ambitious. That's the final boss. There are currently no
"clean" implementation to get inspiration from.
glr.c is very clean but:
- is low-level C
- is a different skeleton from yacc.c
glr.cc is (currently) an ugly hack: a C++ shell around glr.c. Valentin
Tolmer is currently rewriting glr.cc to be clean C++, but he is not
finished. There will be a lot a common code between lalr1.cc and glr.cc, so
eventually I would like them to be fused into a single skeleton, supporting
both deterministic and generalized parsing.
It would be great for D to also support this.
The basic ideas of GLR are explained here:
https://www.codeproject.com/Articles/5259825/GLR-Parsing-in-Csharp-How-to-Use-The-Most-Powerful
* Better error messages * Better error messages
The users are not provided with enough tools to forge their error messages. The users are not provided with enough tools to forge their error messages.
See for instance "Is there an option to change the message produced by See for instance "Is there an option to change the message produced by
@@ -231,7 +496,7 @@ and older C++ compilers. Currently the code defaults to defining it to
define it to the same type as the C ptrdiff_t type. define it to the same type as the C ptrdiff_t type.
* Completion * Completion
Several features are not available in all the backends. Several features are not available in all the back-ends.
- lac: D, Java (easy) - lac: D, Java (easy)
- push parsers: glr.c, glr.cc, lalr1.cc (not very difficult) - push parsers: glr.c, glr.cc, lalr1.cc (not very difficult)
@@ -301,7 +566,7 @@ opposite side we have some use of \l, which is graphviz-specific, in what
should be generic code. should be generic code.
Little effort seems to have been given to factoring these files and their 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 print{,-xml} counterpart. We would very much like to re-use the pretty format
of states from .output for the graphs, etc. of states from .output for the graphs, etc.
Since graphviz dies on medium-to-big grammars, maybe consider an other tool? Since graphviz dies on medium-to-big grammars, maybe consider an other tool?
@@ -579,14 +844,39 @@ to bison. If you're interested, I'll work on a patch.
Equip the parser with a means to create the (visual) parse tree. Equip the parser with a means to create the (visual) parse tree.
-----
# LocalWords: Cex gnulib gl Bistromathic TokenKinds yylex enum YYEOF EOF
# LocalWords: YYerror gettext af hb YYERRCODE undef calc FIXME dev yyerror
# LocalWords: Autoconf YYUNDEFTOK lexemes parsers Bistromathic's yyreport
# LocalWords: const argc yacc yyclearin lookahead destructor Rici incluent
# LocalWords: yydestruct yydiscardin catégories d'avertissements sr activé
# LocalWords: conflits défaut rr l'alias chaîne n'est attaché un symbole
# LocalWords: obsolète règle vide midrule valeurs de intermédiaire ou avec
# LocalWords: définies inutilisées priorité associativité inutiles POSIX
# LocalWords: incompatibilités tous les autres avertissements sauf dans rp
# LocalWords: désactiver CATEGORIE traiter comme des erreurs glr Akim bool
# LocalWords: Demaille arith lalr goto struct pathlen nullable ntokens lr
# LocalWords: nterm bitsetv ielr ritem nstates nrules nritems yysymbol EQ
# LocalWords: SymbolKind YYEMPTY YYUNDEF YYTNAME NUM yyntokens yytname sed
# LocalWords: nonterminals yykind yycode YYNAMES yynames init getName conv
# LocalWords: TokenKind semanticVal ival yychar yylval yylexer Tolmer hoc
# LocalWords: Sobisch YYPTRDIFF ptrdiff Autotest YYPRINT toknum yytoknum
# LocalWords: sym Wother stderr FP fixits xgettext fdiagnostics Graphviz
# LocalWords: graphviz VCG bitset xml bw maint yytoken YYABORT deps
# LocalWords: YYACCEPT yytranslate nonnegative destructors yyerrlab repo
# LocalWords: backends stmt expr yy Mardle baz qux Vadim Maslow CPP cpp
# LocalWords: yydebug gcc UCHAR EBCDIC gung PDP NUL Pre Florian Krohm utf
# LocalWords: YYACT YYLLOC YYLSP yyval yyvsp yylen yyloc yylsp endif
# LocalWords: ispell american
Local Variables: Local Variables:
mode: outline mode: outline
coding: utf-8 coding: utf-8
fill-column: 76 fill-column: 76
ispell-dictionary: "american"
End: End:
-----
Copyright (C) 2001-2004, 2006, 2008-2015, 2018-2020 Free Software Copyright (C) 2001-2004, 2006, 2008-2015, 2018-2020 Free Software
Foundation, Inc. Foundation, Inc.
+2
View File
@@ -45,6 +45,8 @@ gnulib_modules='
relocatable-prog relocatable-script relocatable-prog relocatable-script
rename rename
spawn-pipe stdbool stpcpy stpncpy strdup-posix strerror strverscmp spawn-pipe stdbool stpcpy stpncpy strdup-posix strerror strverscmp
sys_ioctl
termios
timevar timevar
unicodeio unistd unistd-safer unlink unlocked-io unicodeio unistd unistd-safer unlink unlocked-io
update-copyright unsetenv verify update-copyright unsetenv verify
+2 -1
View File
@@ -126,7 +126,7 @@ _sed_rm_comments_q = $(subst ','\'',$(_sed_remove_comments))
_space_before_paren_exempt =? \\n\\$$ _space_before_paren_exempt =? \\n\\$$
_space_before_paren_exempt = \ _space_before_paren_exempt = \
(^ *\#|(LA)?LR\([01]\)|percent_(code|define)|b4_syncline|m4_(define|init)|symbol) (^ *\#|(LA)?LR\([01]\)|percent_(code|define)|b4_syncline|m4_(define|init))
# Ensure that there is a space before each open parenthesis in C code. # Ensure that there is a space before each open parenthesis in C code.
sc_space_before_open_paren: sc_space_before_open_paren:
@if $(VC_LIST_EXCEPT) | grep -l '\.[ch]$$' > /dev/null; then \ @if $(VC_LIST_EXCEPT) | grep -l '\.[ch]$$' > /dev/null; then \
@@ -156,6 +156,7 @@ exclude = \
$(call exclude, \ $(call exclude, \
bindtextdomain=^lib/main.c$$ \ bindtextdomain=^lib/main.c$$ \
cast_of_argument_to_free=^src/muscle-tab.c$$ \ cast_of_argument_to_free=^src/muscle-tab.c$$ \
error_message_uppercase=etc/bench.pl.in$$ \
po_check=^tests|(^po/POTFILES.in|.md)$$ \ po_check=^tests|(^po/POTFILES.in|.md)$$ \
preprocessor_indentation=^data/|^lib/|^src/parse-gram.[ch]$$ \ preprocessor_indentation=^data/|^lib/|^src/parse-gram.[ch]$$ \
program_name=^lib/main.c$$ \ program_name=^lib/main.c$$ \
+3
View File
@@ -60,6 +60,9 @@ AC_PROG_CXX
# Gnulib (early checks). # Gnulib (early checks).
gl_EARLY gl_EARLY
# We want ostream_printf and hyperlink support.
gl_LIBTEXTSTYLE_OPTIONAL([0.20.5])
# Gnulib uses '#pragma GCC diagnostic push' to silence some # Gnulib uses '#pragma GCC diagnostic push' to silence some
# warnings, but older gcc doesn't support this. # warnings, but older gcc doesn't support this.
AC_CACHE_CHECK([whether pragma GCC diagnostic push works], AC_CACHE_CHECK([whether pragma GCC diagnostic push works],
+1 -1
View File
@@ -172,7 +172,7 @@ m4_pushdef([b4_parse_param], m4_defn([b4_parse_param_orig]))dnl
const location_type* yylocationp]])[) const const location_type* yylocationp]])[) const
{ {
*yycdebug_ << (yykind < YYNTOKENS ? "token" : "nterm") *yycdebug_ << (yykind < YYNTOKENS ? "token" : "nterm")
<< ' ' << yytname[yykind] << " ("]b4_locations_if([[ << ' ' << yysymbol_name (yykind) << " ("]b4_locations_if([[
<< *yylocationp << ": "]])[; << *yylocationp << ": "]])[;
yy_symbol_value_print_ (yykind, yyvaluep]b4_locations_if([[, yylocationp]])[); yy_symbol_value_print_ (yykind, yyvaluep]b4_locations_if([[, yylocationp]])[);
*yycdebug_ << ')'; *yycdebug_ << ')';
+2 -2
View File
@@ -1486,7 +1486,7 @@ yypstate_new (void)
yypstate *yyps;]b4_pure_if([], [[ yypstate *yyps;]b4_pure_if([], [[
if (yypstate_allocated) if (yypstate_allocated)
return YY_NULLPTR;]])[ return YY_NULLPTR;]])[
yyps = YY_CAST (yypstate *, malloc (sizeof *yyps)); yyps = YY_CAST (yypstate *, YYMALLOC (sizeof *yyps));
if (!yyps) if (!yyps)
return YY_NULLPTR;]b4_pure_if([], [[ return YY_NULLPTR;]b4_pure_if([], [[
yypstate_allocated = 1;]])[ yypstate_allocated = 1;]])[
@@ -1515,7 +1515,7 @@ yypstate_delete (yypstate *yyps)
#endif]b4_lac_if([[ #endif]b4_lac_if([[
if (yyes != yyesa) if (yyes != yyesa)
YYSTACK_FREE (yyes);]])[ YYSTACK_FREE (yyes);]])[
free (yyps);]b4_pure_if([], [[ YYFREE (yyps);]b4_pure_if([], [[
yypstate_allocated = 0;]])[ yypstate_allocated = 0;]])[
} }
} }
+105 -79
View File
@@ -57,44 +57,57 @@
\gdef\colorPurple{% \gdef\colorPurple{%
\setcolor{\rgbPurple}% \setcolor{\rgbPurple}%
} }
\gdef\colorOff{%
\setcolor{\maincolor}%
}
\gdef\rgbError{0.80 0 0} \gdef\rgbError{0.80 0 0}
\gdef\colorError{% \gdef\diagError{%
\setcolor{\rgbError}% \setcolor{\rgbError}%
} }
\gdef\rgbNotice{0 0 0.80} \gdef\rgbNotice{0 0 0.80}
\gdef\colorNotice{% \gdef\diagNotice{%
\setcolor{\rgbNotice}% \setcolor{\rgbNotice}%
} }
\gdef\colorOff{% \gdef\rgbWarning{0.50 0 0.50}
\gdef\diagWarning{%
\setcolor{\rgbWarning}%
}
\gdef\diagOff{%
\setcolor{\maincolor}% \setcolor{\maincolor}%
} }
@end tex @end tex
@ifnottex @ifnottex
@macro colorGreen @macro colorGreen
@inlineraw{html, <b style="color:green">} @inlineraw{html, <span style="color:green">}
@end macro @end macro
@macro colorYellow @macro colorYellow
@inlineraw{html, <b style="color:#ff8000">} @inlineraw{html, <span style="color:#ff8000">}
@end macro @end macro
@macro colorRed @macro colorRed
@inlineraw{html, <b style="color:red">} @inlineraw{html, <span style="color:red">}
@end macro @end macro
@macro colorBlue @macro colorBlue
@inlineraw{html, <b style="color:blue">} @inlineraw{html, <span style="color:blue">}
@end macro @end macro
@macro colorPurple @macro colorPurple
@inlineraw{html, <b style="color:darkviolet">} @inlineraw{html, <span style="color:darkviolet">}
@end macro
@macro colorError
@inlineraw{html, <b style="color:red">}
@end macro
@macro colorNotice
@inlineraw{html, <b style="color:darkcyan">}
@end macro @end macro
@macro colorOff @macro colorOff
@inlineraw{html, </span>}
@end macro
@macro diagError
@inlineraw{html, <b style="color:red">}
@end macro
@macro diagNotice
@inlineraw{html, <b style="color:darkcyan">}
@end macro
@macro diagWarning
@inlineraw{html, <b style="color:darkviolet">}
@end macro
@macro diagOff
@inlineraw{html, </b>} @inlineraw{html, </b>}
@end macro @end macro
@end ifnottex @end ifnottex
@@ -120,15 +133,15 @@
@end macro @end macro
@macro dwarning{text} @macro dwarning{text}
@purple{\text\} @diagWarning{}\text\@diagOff{}
@end macro @end macro
@macro derror{text} @macro derror{text}
@colorError{}\text\@colorOff{} @diagError{}\text\@diagOff{}
@end macro @end macro
@macro dnotice{text} @macro dnotice{text}
@colorNotice{}\text\@colorOff{} @diagNotice{}\text\@diagOff{}
@end macro @end macro
@finalout @finalout
@@ -6283,7 +6296,10 @@ Introduced in Bison 3.3 to replace @code{parser_class_name}.
@item Default Value: @code{YY} for Java, @code{yy} otherwise. @item Default Value: @code{YY} for Java, @code{yy} otherwise.
@item History: introduced in Bison 2.6 @item History:
introduced in Bison 2.6, with its argument in double quotes. Uses braces
since Bison 3.0 (double quotes are still supported for backward
compatibility).
@end itemize @end itemize
@end deffn @end deffn
@@ -8302,7 +8318,53 @@ write an unambiguous grammar, but that is very hard to do in this case.)
This particular ambiguity was first encountered in the specifications of This particular ambiguity was first encountered in the specifications of
Algol 60 and is called the ``dangling @code{else}'' ambiguity. Algol 60 and is called the ``dangling @code{else}'' ambiguity.
To avoid warnings from Bison about predictable, legitimate shift/reduce To assist the grammar author in understanding the nature of each conflict,
Bison can be asked to generate ``counterexamples''. In the present case it
actually even proves that the grammar is ambiguous by exhibiting a string
with two different parses:
@macro danglingElseCex
@group
@ifnottex
Example: @yellow{"if" expr "then"} @blue{"if" expr "then" stmt} @red{•} @blue{"else" stmt}
Shift derivation
@yellow{if_stmt}
@yellow{↳ "if" expr "then"} @green{stmt}
@green{↳} @blue{if_stmt}
@blue{↳ "if" expr "then" stmt} @red{•} @blue{"else" stmt}
Example: @yellow{"if" expr "then"} @blue{"if" expr "then" stmt} @red{•} @yellow{"else" stmt}
Reduce derivation
@yellow{if_stmt}
@yellow{↳ "if" expr "then"} @green{stmt} @yellow{"else" stmt}
@green{↳} @blue{if_stmt}
@blue{↳ "if" expr "then" stmt} @red{•}
@end ifnottex
@iftex
Example: @yellow{"if" expr "then"} @blue{"if" expr "then" stmt} @red{•} @blue{"else" stmt}
Shift derivation
@yellow{if_stmt}
@yellow{@arrow{} "if" expr "then"} @green{stmt}
@green{@arrow{}} @blue{if_stmt}
@blue{@arrow{} "if" expr "then" stmt} @red{•} @blue{"else" stmt}
Example: @yellow{"if" expr "then"} @blue{"if" expr "then" stmt} @red{•} @yellow{"else" stmt}
Reduce derivation
@yellow{if_stmt}
@yellow{@arrow{} "if" expr "then"} @green{stmt} @yellow{"else" stmt}
@green{@arrow{}} @blue{if_stmt}
@blue{@arrow{} "if" expr "then" stmt} @red{•}
@end iftex
@end group
@end macro
@example
@danglingElseCex
@end example
@noindent
@xref{Counterexamples}, for more details.
@sp 1
To avoid warnings from Bison about predictable, @emph{legitimate} shift/reduce
conflicts, you can use the @code{%expect @var{n}} declaration. conflicts, you can use the @code{%expect @var{n}} declaration.
There will be no warning as long as the number of shift/reduce conflicts There will be no warning as long as the number of shift/reduce conflicts
is exactly @var{n}, and Bison will report an error if there is a is exactly @var{n}, and Bison will report an error if there is a
@@ -8693,7 +8755,8 @@ maybeword:
@end example @end example
@noindent @noindent
The error is an ambiguity: there is more than one way to parse a single The error is an ambiguity: as counterexample generation would demonstrate
(@pxref{Counterexamples}), there is more than one way to parse a single
@code{word} into a @code{sequence}. It could be reduced to a @code{word} into a @code{sequence}. It could be reduced to a
@code{maybeword} and then into a @code{sequence} via the second rule. @code{maybeword} and then into a @code{sequence} via the second rule.
Alternatively, nothing-at-all could be reduced into a @code{sequence} Alternatively, nothing-at-all could be reduced into a @code{sequence}
@@ -8890,12 +8953,14 @@ name_list:
It would seem that this grammar can be parsed with only a single token of It would seem that this grammar can be parsed with only a single token of
lookahead: when a @code{param_spec} is being read, an @code{"id"} is a lookahead: when a @code{param_spec} is being read, an @code{"id"} is a
@code{name} if a comma or colon follows, or a @code{type} if another @code{name} if a comma or colon follows, or a @code{type} if another
@code{"id"} follows. In other words, this grammar is LR(1). @code{"id"} follows. In other words, this grammar is LR(1). Yet Bison
finds one reduce/reduce conflict, for which counterexample generation
(@pxref{Counterexamples}) would find a @emph{nonunifying} example.
@cindex LR @cindex LR
@cindex LALR @cindex LALR
However, for historical reasons, Bison cannot by default handle all This is because Bison does not handle all LR(1) grammars @emph{by default},
LR(1) grammars. for historical reasons.
In this grammar, two contexts, that after an @code{"id"} at the beginning In this grammar, two contexts, that after an @code{"id"} at the beginning
of a @code{param_spec} and likewise at the beginning of a of a @code{param_spec} and likewise at the beginning of a
@code{return_spec}, are similar enough that Bison assumes they are the @code{return_spec}, are similar enough that Bison assumes they are the
@@ -9870,6 +9935,9 @@ and understand the parser run-time traces (@pxref{Tracing}).
@node Counterexamples @node Counterexamples
@section Generation of Counterexamples @section Generation of Counterexamples
@cindex cex
@cindex counterexamples
@cindex conflict counterexamples
Solving conflicts is probably the most delicate part of the design of an LR Solving conflicts is probably the most delicate part of the design of an LR
parser, as demonstrated by the number of sections devoted to them in this parser, as demonstrated by the number of sections devoted to them in this
@@ -9886,8 +9954,8 @@ That task is made much easier thanks to the generation of counterexamples,
initially developed by Chinawat Isradisaikul and Andrew Myers initially developed by Chinawat Isradisaikul and Andrew Myers
@pcite{Isradisaikul 2015}. @pcite{Isradisaikul 2015}.
As a first example, see the example grammar of @ref{Shift/Reduce}, which As a first example, see the grammar of @ref{Shift/Reduce}, which features
features on shift/reduce conflict: one shift/reduce conflict:
@c see doc/if-then-else.y @c see doc/if-then-else.y
@example @example
@@ -9901,49 +9969,14 @@ Let's rerun @command{bison} with the option
@option{-Wcex}/@option{-Wcounterexamples}@inlinefmt{info, (the following @option{-Wcex}/@option{-Wcounterexamples}@inlinefmt{info, (the following
output is actually in color)}: output is actually in color)}:
@ifnottex
@example @example
if-then-else.y: @dwarning{warning}: 1 shift/reduce conflict [@dwarning{-Wconflicts-sr}] if-then-else.y: @dwarning{warning}: 1 shift/reduce conflict [@dwarning{-Wconflicts-sr}]
if-then-else.y: @dwarning{warning}: shift/reduce conflict on token "else" [@dwarning{-Wcounterexamples}] if-then-else.y: @dwarning{warning}: shift/reduce conflict on token "else" [@dwarning{-Wcounterexamples}]
@group @danglingElseCex
Example: @yellow{"if" expr "then"} "if" expr "then" stmt • "else" stmt
Shift derivation
@yellow{if_stmt}
@yellow{↳ "if" expr "then"} @green{stmt}
@green{↳} @blue{if_stmt}
@blue{↳ "if" expr "then" stmt} @red{•} @blue{"else" stmt}
Example: @yellow{"if" expr "then"} @blue{"if" expr "then" stmt} @red{•} @yellow{"else" stmt}
Reduce derivation
@yellow{if_stmt}
@yellow{↳ "if" expr "then"} @green{stmt} @yellow{"else" stmt}
@green{↳} @blue{if_stmt}
@blue{↳ "if" expr "then" stmt} @red{•}
@end group
@end example @end example
@end ifnottex
@iftex
@example
if-then-else.y: @dwarning{warning}: 1 shift/reduce conflict [@dwarning{-Wconflicts-sr}]
if-then-else.y: @dwarning{warning}: shift/reduce conflict on token "else" [@dwarning{-Wcounterexamples}]
@group
Example: @yellow{"if" expr "then"} "if" expr "then" stmt • "else" stmt
Shift derivation
@yellow{if_stmt}
@yellow{@arrow{} "if" expr "then"} @green{stmt}
@green{@arrow{}} @blue{if_stmt}
@blue{@arrow{} "if" expr "then" stmt} @red{•} @blue{"else" stmt}
Example: @yellow{"if" expr "then"} @blue{"if" expr "then" stmt} @red{•} @yellow{"else" stmt}
Reduce derivation
@yellow{if_stmt}
@yellow{@arrow{} "if" expr "then"} @green{stmt} @yellow{"else" stmt}
@green{@arrow{}} @blue{if_stmt}
@blue{@arrow{} "if" expr "then" stmt} @red{•}
@end group
@end example
@end iftex
This shows two different derivations for one single expression. That This shows two different derivations for one single expression, which proves
demonstrates that the grammar is ambiguous. that the grammar is ambiguous.
@sp 1 @sp 1
@@ -9966,13 +9999,13 @@ maybeword:
Bison generates the following counterexamples: Bison generates the following counterexamples:
@ifnottex
@example @example
@group @group
$ @kbd{bison -Wcex sequence.y} $ @kbd{bison -Wcex sequence.y}
sequence.y: @dwarning{warning}: 1 shift/reduce conflict [@dwarning{-Wconflicts-sr}] sequence.y: @dwarning{warning}: 1 shift/reduce conflict [@dwarning{-Wconflicts-sr}]
sequence.y: @dwarning{warning}: 2 reduce/reduce conflicts [@dwarning{-Wconflicts-rr}] sequence.y: @dwarning{warning}: 2 reduce/reduce conflicts [@dwarning{-Wconflicts-rr}]
@end group @end group
@ifnottex
@group @group
sequence.y: @dwarning{warning}: shift/reduce conflict on token "word" [@dwarning{-Wcounterexamples}] sequence.y: @dwarning{warning}: shift/reduce conflict on token "word" [@dwarning{-Wcounterexamples}]
Example: @red{•} @green{"word"} Example: @red{•} @green{"word"}
@@ -10017,15 +10050,8 @@ sequence.y:8.3-45: @dwarning{warning}: rule useless in parser due to conflicts [
8 | @dwarning{%empty @{ printf ("empty maybeword\n"); @}} 8 | @dwarning{%empty @{ printf ("empty maybeword\n"); @}}
| @dwarning{^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~} | @dwarning{^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
@end group @end group
@end example
@end ifnottex @end ifnottex
@iftex @iftex
@example
@group
$ @kbd{bison -Wcex sequence.y}
sequence.y: @dwarning{warning}: 1 shift/reduce conflict [@dwarning{-Wconflicts-sr}]
sequence.y: @dwarning{warning}: 2 reduce/reduce conflicts [@dwarning{-Wconflicts-rr}]
@end group
@group @group
sequence.y: @dwarning{warning}: shift/reduce conflict on token "word" [@dwarning{-Wcounterexamples}] sequence.y: @dwarning{warning}: shift/reduce conflict on token "word" [@dwarning{-Wcounterexamples}]
Example: @red{•} @green{"word"} Example: @red{•} @green{"word"}
@@ -10070,8 +10096,8 @@ sequence.y:8.3-45: @dwarning{warning}: rule useless in parser due to conflicts [
8 | @dwarning{%empty @{ printf ("empty maybeword\n"); @}} 8 | @dwarning{%empty @{ printf ("empty maybeword\n"); @}}
| @dwarning{^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~} | @dwarning{^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
@end group @end group
@end example
@end iftex @end iftex
@end example
Each of these three conflicts, again, prove that the grammar is ambiguous. Each of these three conflicts, again, prove that the grammar is ambiguous.
For instance, the second conflict (the reduce/reduce one) shows that the For instance, the second conflict (the reduce/reduce one) shows that the
@@ -10096,10 +10122,10 @@ expr: %empty | expr ID ','
@command{bison} reports: @command{bison} reports:
@ifnottex
@example @example
ids.y: @dwarning{warning}: 1 shift/reduce conflict [@dwarning{-Wconflicts-sr}] ids.y: @dwarning{warning}: 1 shift/reduce conflict [@dwarning{-Wconflicts-sr}]
ids.y: @dwarning{warning}: shift/reduce conflict on token ID [@dwarning{-Wcounterexamples}] ids.y: @dwarning{warning}: shift/reduce conflict on token ID [@dwarning{-Wcounterexamples}]
@ifnottex
@group @group
First example: @purple{expr} @red{•} @purple{ID ','} @green{ID} @yellow{$end} First example: @purple{expr} @red{•} @purple{ID ','} @green{ID} @yellow{$end}
Shift derivation Shift derivation
@@ -10120,12 +10146,8 @@ ids.y:4.4-7: @dwarning{warning}: rule useless in parser due to conflicts [@dwarn
4 | a: expr 4 | a: expr
| ^~~~ | ^~~~
@end group @end group
@end example
@end ifnottex @end ifnottex
@iftex @iftex
@example
ids.y: @dwarning{warning}: 1 shift/reduce conflict [@dwarning{-Wconflicts-sr}]
ids.y: @dwarning{warning}: shift/reduce conflict on token ID [@dwarning{-Wcounterexamples}]
@group @group
First example: @purple{expr} @red{•} @purple{ID ','} @green{ID} @yellow{$end} First example: @purple{expr} @red{•} @purple{ID ','} @green{ID} @yellow{$end}
Shift derivation Shift derivation
@@ -10146,8 +10168,8 @@ ids.y:4.4-7: @dwarning{warning}: rule useless in parser due to conflicts [@dwarn
4 | a: expr 4 | a: expr
| ^~~~ | ^~~~
@end group @end group
@end example
@end iftex @end iftex
@end example
This conflict is caused by the parser not having enough information to know This conflict is caused by the parser not having enough information to know
the difference between these two examples. The parser would need an the difference between these two examples. The parser would need an
@@ -15631,6 +15653,10 @@ permitted. @xref{Language and Grammar}.
A sequence of tokens and/or nonterminals, with one dot, that demonstrates a A sequence of tokens and/or nonterminals, with one dot, that demonstrates a
conflict. The dot marks the place where the conflict occurs. conflict. The dot marks the place where the conflict occurs.
@cindex unifying counterexample
@cindex counterexample, unifying
@cindex nonunifying counterexample
@cindex counterexample, nonunifying
A @emph{unifying} counterexample is a single string that has two different A @emph{unifying} counterexample is a single string that has two different
parses; its existence proves that the grammar is ambiguous. When a unifying parses; its existence proves that the grammar is ambiguous. When a unifying
counterexample cannot be found in reasonable time, a @emph{nonunifying} counterexample cannot be found in reasonable time, a @emph{nonunifying}
+1 -1
View File
@@ -57,7 +57,7 @@ MAINTAINERCLEANFILES = $(CROSS_OPTIONS_TEXI)
# Fix Info's @code in @deftype # Fix Info's @code in @deftype
# https://lists.gnu.org/archive/html/help-texinfo/2019-11/msg00004.html # https://lists.gnu.org/archive/html/help-texinfo/2019-11/msg00004.html
all: $(srcdir)/$(%C%_bison).info.bak all-local: $(srcdir)/$(%C%_bison).info.bak
$(srcdir)/$(%C%_bison).info.bak: $(srcdir)/$(%C%_bison).info $(srcdir)/$(%C%_bison).info.bak: $(srcdir)/$(%C%_bison).info
$(AM_V_GEN) $(PERL) -pi.bak -0777 \ $(AM_V_GEN) $(PERL) -pi.bak -0777 \
-e 's{(^ --.*\n(?: {10}.*\n)*)}' \ -e 's{(^ --.*\n(?: {10}.*\n)*)}' \
+41 -29
View File
@@ -185,13 +185,13 @@ my $verbose = 1;
=over 4 =over 4
=item C<verbose($level, $message)> =item C<verbose ($level, $message)>
Report the C<$message> is C<$level> E<lt>= C<$verbose>. Report the C<$message> is C<$level> E<lt>= C<$verbose>.
=cut =cut
sub verbose($$) sub verbose ($$)
{ {
my ($level, $message) = @_; my ($level, $message) = @_;
print STDERR $message print STDERR $message
@@ -201,13 +201,13 @@ sub verbose($$)
###################################################################### ######################################################################
=item C<directives($bench, @directive)> =item C<directives ($bench, @directive)>
Format the list of directives for Bison for bench named C<$bench>. Format the list of directives for Bison for bench named C<$bench>.
=cut =cut
sub directives($@) sub directives ($@)
{ {
my ($bench, @directive) = @_; my ($bench, @directive) = @_;
my $res = "/* Directives for bench '$bench'. */\n"; my $res = "/* Directives for bench '$bench'. */\n";
@@ -218,6 +218,27 @@ sub directives($@)
###################################################################### ######################################################################
=item C<is_pure (@directive)>
Whether api.pure is set.
=cut
sub is_pure (@)
{
my (@directive) = @_;
for my $dir (@directive)
{
if ($dir =~ /\A%define api.pure/)
{
return 1;
}
}
return 0;
}
######################################################################
=item C<generate_grammar_triangular ($base, $max, @directive)> =item C<generate_grammar_triangular ($base, $max, @directive)>
Create a large triangular grammar which looks like : Create a large triangular grammar which looks like :
@@ -389,18 +410,14 @@ sub generate_grammar_calc ($$@)
%define api.value.type union %define api.value.type union
$directives $directives
%{ %code provides {
static int power (int base, int exponent); static int power (int base, int exponent);
/* yyerror receives the location if: /* yyerror receives the location if:
- %location & %pure & %glr - %location & %pure & %glr
- %location & %pure & %yacc & %parse-param. */ - %location & %pure & %yacc & %parse-param. */
static void yyerror (const char *s); static void yyerror (const char *s);
#if YYPURE static int yylex (@{[is_pure (@directive) ? "YYSTYPE *yylvalp" : "void"]});
static int yylex (YYSTYPE* yylvalp); }
#else
static int yylex (void);
#endif
%}
/* Bison Declarations */ /* Bison Declarations */
%token %token
@@ -467,12 +484,7 @@ yyerror (const char *s)
} }
static int static int
#if YYPURE yylex (@{[is_pure (@directive) ? "YYSTYPE *yylvalp" : "void"]})
# define yylval (*yylvalp)
yylex (YYSTYPE* yylvalp)
#else
yylex (void)
#endif
{ {
int c; int c;
@@ -498,7 +510,7 @@ yylex (void)
case '5': case '6': case '7': case '8': case '9': case '5': case '6': case '7': case '8': case '9':
{ {
int nchars = 0; int nchars = 0;
int n = sscanf (input - 1, "%d%n", &yylval.NUM, &nchars); int n = sscanf (input - 1, "%d%n", &@{[is_pure (@directive) ? "yylvalp->" : "yylval."]}NUM, &nchars);
assert (n == 1); assert (n == 1);
input += nchars - 1; input += nchars - 1;
return NUM; return NUM;
@@ -506,7 +518,7 @@ yylex (void)
default: default:
yyerror ("error: invalid character"); yyerror ("error: invalid character");
return yylex (); return yylex (@{[is_pure (@directive) ? "yylvalp" : ""]});
} }
} }
EOF EOF
@@ -592,10 +604,10 @@ $directives
// Prototype of the yylex function providing subsequent tokens. // Prototype of the yylex function providing subsequent tokens.
static static
#if USE_TOKEN_CTOR #if USE_TOKEN_CTOR
yy::parser::symbol_type yylex(); yy::parser::symbol_type yylex ();
#else #else
yy::parser::token_type yylex(yy::parser::semantic_type* yylvalp, yy::parser::token_type yylex (yy::parser::semantic_type *yylvalp,
yy::parser::location_type* yyllocp); yy::parser::location_type *yyllocp);
#endif #endif
// Conversion to string. // Conversion to string.
@@ -618,8 +630,8 @@ EOF
print $out <<'EOF'; print $out <<'EOF';
%token <std::string> TEXT %token <std::string> TEXT
%token <int> NUMBER %token <int> NUMBER
%printer { std::cerr << "Number: " << $$; } <int> %printer { yyo << "Number: " << $$; } <int>
%printer { std::cerr << "Text: " << $$; } <std::string> %printer { yyo << "Text: " << $$; } <std::string>
%type <std::string> text result %type <std::string> text result
%% %%
@@ -641,8 +653,8 @@ EOF
%union {int ival; std::string* sval;} %union {int ival; std::string* sval;}
%token <sval> TEXT %token <sval> TEXT
%token <ival> NUMBER %token <ival> NUMBER
%printer { std::cerr << "Number: " << $$; } <ival> %printer { yyo << "Number: " << $$; } <ival>
%printer { std::cerr << "Text: " << *$$; } <sval> %printer { yyo << "Text: " << *$$; } <sval>
%type <sval> text result %type <sval> text result
%% %%
@@ -664,10 +676,10 @@ EOF
static static
#if USE_TOKEN_CTOR #if USE_TOKEN_CTOR
yy::parser::symbol_type yylex() yy::parser::symbol_type yylex ()
#else #else
yy::parser::token_type yylex(yy::parser::semantic_type* yylvalp, yy::parser::token_type yylex (yy::parser::semantic_type *yylvalp,
yy::parser::location_type* yyllocp) yy::parser::location_type *yyllocp)
#endif #endif
{ {
typedef yy::parser::location_type location_type; typedef yy::parser::location_type location_type;
+10 -10
View File
@@ -251,29 +251,29 @@ err: Next token is token ) (1.4: )
err: Shifting token ) (1.4: ) err: Shifting token ) (1.4: )
err: Entering state 20 err: Entering state 20
err: Stack now 0 2 10 20 err: Stack now 0 2 10 20
err: Reducing stack by rule 15 (line 151): err: Reducing stack by rule XX (line XXX):
err: $1 = token ( (1.1: ) err: $1 = token ( (1.1: )
err: $2 = token error (1.2-3: ) err: $2 = token error (1.2-3: )
err: $3 = token ) (1.4: ) err: $3 = token ) (1.4: )
err: -> $$ = nterm exp (1.1-4: 666) err: -> $$ = nterm exp (1.1-4: 666)
err: Entering state 7 err: Entering state 8
err: Stack now 0 7 err: Stack now 0 8
err: Return for a new token: err: Return for a new token:
err: Reading a token err: Reading a token
err: Now at end of input. err: Now at end of input.
err: LAC: initial context established for end of file err: LAC: initial context established for end of file
err: LAC: checking lookahead end of file: R2 G8 S19 err: LAC: checking lookahead end of file: R2 G7 S14
err: Reducing stack by rule 2 (line 126): err: Reducing stack by rule XX (line XXX):
err: $1 = nterm exp (1.1-4: 666) err: $1 = nterm exp (1.1-4: 666)
err: -> $$ = nterm input (1.1-4: ) err: -> $$ = nterm input (1.1-4: )
err: Entering state 8 err: Entering state 7
err: Stack now 0 8 err: Stack now 0 7
err: Now at end of input. err: Now at end of input.
err: Shifting token end of file (1.5: ) err: Shifting token end of file (1.5: )
err: LAC: initial context discarded due to shift err: LAC: initial context discarded due to shift
err: Entering state 19 err: Entering state 14
err: Stack now 0 8 19 err: Stack now 0 7 14
err: Stack now 0 8 19 err: Stack now 0 7 14
err: Cleanup: popping token end of file (1.5: ) err: Cleanup: popping token end of file (1.5: )
err: Cleanup: popping nterm input (1.1-4: )' -p err: Cleanup: popping nterm input (1.1-4: )' -p
+7
View File
@@ -31,6 +31,13 @@ endif FLEX_WORKS
%D%/parse.c: $(dependencies) %D%/parse.c: $(dependencies)
# 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%/lexcalc$(DASH)scan.o: %D%/parse.c
# Likewise, but for Automake before 1.16.
%D%/examples_c_lexcalc_lexcalc$(DASH)scan.o: %D%/parse.c
EXTRA_DIST += %D%/lexcalc.test EXTRA_DIST += %D%/lexcalc.test
dist_lexcalc_DATA = %D%/parse.y %D%/scan.l %D%/Makefile %D%/README.md dist_lexcalc_DATA = %D%/parse.y %D%/scan.l %D%/Makefile %D%/README.md
CLEANFILES += %D%/parse.[ch] %D%/scan.c %D%/parse.output CLEANFILES += %D%/parse.[ch] %D%/scan.c %D%/parse.output
+1 -1
View File
@@ -27,7 +27,7 @@ EXTRA_DIST += %D%/calc.test
%D%/calc.d: %D%/calc.y $(dependencies) %D%/calc.d: %D%/calc.y $(dependencies)
$(AM_V_GEN)$(MKDIR_P) %D% $(AM_V_GEN)$(MKDIR_P) %D%
$(AM_V_at)$(BISON) $(srcdir)/%D%/calc.y -o $@ $(AM_V_at)$(BISON) -o $@ $(srcdir)/%D%/calc.y
%D%/calc: %D%/calc.d %D%/calc: %D%/calc.d
$(AM_V_GEN) $(DC) $(DCFLAGS) -of$@ %D%/calc.d $(AM_V_GEN) $(DC) $(DCFLAGS) -of$@ %D%/calc.d
+1 -1
View File
@@ -27,7 +27,7 @@ EXTRA_DIST += %D%/Calc.test
%D%/Calc.java: %D%/Calc.y $(dependencies) %D%/Calc.java: %D%/Calc.y $(dependencies)
$(AM_V_GEN)$(MKDIR_P) %D% $(AM_V_GEN)$(MKDIR_P) %D%
$(AM_V_at)$(BISON) $(srcdir)/%D%/Calc.y -o $@ $(AM_V_at)$(BISON) -o $@ $(srcdir)/%D%/Calc.y
%D%/Calc.class: %D%/Calc.java %D%/Calc.class: %D%/Calc.java
$(AM_V_GEN) $(SHELL) $(top_builddir)/javacomp.sh %D%/Calc.java $(AM_V_GEN) $(SHELL) $(top_builddir)/javacomp.sh %D%/Calc.java
+1 -1
View File
@@ -27,7 +27,7 @@ EXTRA_DIST += %D%/Calc.test
%D%/Calc.java: %D%/Calc.y $(dependencies) %D%/Calc.java: %D%/Calc.y $(dependencies)
$(AM_V_GEN)$(MKDIR_P) %D% $(AM_V_GEN)$(MKDIR_P) %D%
$(AM_V_at)$(BISON) $(srcdir)/%D%/Calc.y -o $@ $(AM_V_at)$(BISON) -o $@ $(srcdir)/%D%/Calc.y
%D%/Calc.class: %D%/Calc.java %D%/Calc.class: %D%/Calc.java
$(AM_V_GEN) $(SHELL) $(top_builddir)/javacomp.sh %D%/Calc.java $(AM_V_GEN) $(SHELL) $(top_builddir)/javacomp.sh %D%/Calc.java
+1 -1
Submodule gnulib updated: ac34618e85...160d5e7d9a
+3 -2
View File
@@ -192,8 +192,6 @@
/localcharset.h /localcharset.h
/locale.h /locale.h
/locale.in.h /locale.in.h
/localtime-buffer.c
/localtime-buffer.h
/lstat.c /lstat.c
/malloc.c /malloc.c
/malloca.c /malloca.c
@@ -338,8 +336,11 @@
/sys_types.in.h /sys_types.in.h
/sys_wait.in.h /sys_wait.in.h
/sysexits.in.h /sysexits.in.h
/termios.h
/termios.in.h
/textstyle.h /textstyle.h
/textstyle.in.h /textstyle.in.h
/thread-optim.h
/time.h /time.h
/time.in.h /time.in.h
/timespec.c /timespec.c
+4 -1
View File
@@ -97,7 +97,6 @@
/locale-ja.m4 /locale-ja.m4
/locale-zh.m4 /locale-zh.m4
/locale_h.m4 /locale_h.m4
/localtime-buffer.m4
/lock.m4 /lock.m4
/longlong.m4 /longlong.m4
/lstat.m4 /lstat.m4
@@ -117,6 +116,7 @@
/msvc-inval.m4 /msvc-inval.m4
/msvc-nothrow.m4 /msvc-nothrow.m4
/multiarch.m4 /multiarch.m4
/musl.m4
/nls.m4 /nls.m4
/nocrash.m4 /nocrash.m4
/non-recursive-gnulib-prefix-hack.m4 /non-recursive-gnulib-prefix-hack.m4
@@ -128,6 +128,7 @@
/open.m4 /open.m4
/pathmax.m4 /pathmax.m4
/perror.m4 /perror.m4
/pid_t.m4
/pipe2.m4 /pipe2.m4
/po.m4 /po.m4
/posix_spawn.m4 /posix_spawn.m4
@@ -184,6 +185,7 @@
/strndup.m4 /strndup.m4
/strnlen.m4 /strnlen.m4
/strverscmp.m4 /strverscmp.m4
/sys_ioctl_h.m4
/sys_resource_h.m4 /sys_resource_h.m4
/sys_socket_h.m4 /sys_socket_h.m4
/sys_stat_h.m4 /sys_stat_h.m4
@@ -191,6 +193,7 @@
/sys_times_h.m4 /sys_times_h.m4
/sys_types_h.m4 /sys_types_h.m4
/sys_wait_h.m4 /sys_wait_h.m4
/termios_h.m4
/threadlib.m4 /threadlib.m4
/time_h.m4 /time_h.m4
/timespec.m4 /timespec.m4
+12 -17
View File
@@ -113,13 +113,8 @@ free_counterexample (counterexample *cex)
free (cex); free (cex);
} }
static int max (int a, int b)
{
return a < b ? b : a;
}
static void static void
print_counterexample (const counterexample *cex, FILE *out, const char *prefix) counterexample_print (const counterexample *cex, FILE *out, const char *prefix)
{ {
const bool flat = getenv ("YYFLAT"); const bool flat = getenv ("YYFLAT");
const char *example1_label const char *example1_label
@@ -131,8 +126,8 @@ print_counterexample (const counterexample *cex, FILE *out, const char *prefix)
const char *deriv2_label const char *deriv2_label
= cex->shift_reduce ? _("Reduce derivation") : _("Second reduce derivation"); = cex->shift_reduce ? _("Reduce derivation") : _("Second reduce derivation");
const int width = const int width =
max (max (mbswidth (example1_label, 0), mbswidth (example2_label, 0)), max_int (max_int (mbswidth (example1_label, 0), mbswidth (example2_label, 0)),
max (mbswidth (deriv1_label, 0), mbswidth (deriv2_label, 0))); max_int (mbswidth (deriv1_label, 0), mbswidth (deriv2_label, 0)));
if (flat) if (flat)
fprintf (out, " %s%s%*s ", prefix, fprintf (out, " %s%s%*s ", prefix,
example1_label, width - mbswidth (example1_label, 0), ""); example1_label, width - mbswidth (example1_label, 0), "");
@@ -526,7 +521,7 @@ nonunifying_shift_path (state_item_list reduce_path, state_item *shift_conflict)
for (gl_list_iterator_t it = gl_list_iterator (result); for (gl_list_iterator_t it = gl_list_iterator (result);
state_item_list_next (&it, &sip); state_item_list_next (&it, &sip);
) )
print_state_item (sip, stderr, ""); state_item_print (sip, stderr, "");
} }
return result; return result;
} }
@@ -717,10 +712,10 @@ ssb_equals (const search_state_bundle *s1, const search_state_bundle *s2)
typedef gl_list_t ssb_list; typedef gl_list_t ssb_list;
static size_t static size_t
visited_hasher (const search_state *ss, size_t maximum) visited_hasher (const search_state *ss, size_t max)
{ {
return (parse_state_hasher (ss->states[0], maximum) return (parse_state_hasher (ss->states[0], max)
+ parse_state_hasher (ss->states[1], maximum)) % maximum; + parse_state_hasher (ss->states[1], max)) % max;
} }
static bool static bool
@@ -1267,7 +1262,7 @@ counterexample_report (state_item_number itm1, state_item_number itm2,
: example_from_path (shift_reduce, itm2, shortest_path, next_sym); : example_from_path (shift_reduce, itm2, shortest_path, next_sym);
gl_list_free (shortest_path); gl_list_free (shortest_path);
print_counterexample (cex, out, prefix); counterexample_print (cex, out, prefix);
free_counterexample (cex); free_counterexample (cex);
} }
@@ -1290,8 +1285,8 @@ counterexample_report_shift_reduce (state_item_number itm1, state_item_number it
// In the report, print the items. // In the report, print the items.
if (out != stderr || trace_flag & trace_cex) if (out != stderr || trace_flag & trace_cex)
{ {
print_state_item (&state_items[itm1], out, prefix); state_item_print (&state_items[itm1], out, prefix);
print_state_item (&state_items[itm2], out, prefix); state_item_print (&state_items[itm2], out, prefix);
} }
counterexample_report (itm1, itm2, next_sym, true, out, prefix); counterexample_report (itm1, itm2, next_sym, true, out, prefix);
} }
@@ -1334,8 +1329,8 @@ counterexample_report_reduce_reduce (state_item_number itm1, state_item_number i
// In the report, print the items. // In the report, print the items.
if (out != stderr || trace_flag & trace_cex) if (out != stderr || trace_flag & trace_cex)
{ {
print_state_item (&state_items[itm1], out, prefix); state_item_print (&state_items[itm1], out, prefix);
print_state_item (&state_items[itm2], out, prefix); state_item_print (&state_items[itm2], out, prefix);
} }
counterexample_report (itm1, itm2, bitset_first (conflict_syms), counterexample_report (itm1, itm2, bitset_first (conflict_syms),
false, out, prefix); false, out, prefix);
+8 -14
View File
@@ -76,12 +76,12 @@ void derivation_list_free (derivation_list dl)
derivation * derivation *
derivation_new (symbol_number sym, derivation_list children) derivation_new (symbol_number sym, derivation_list children)
{ {
derivation *deriv = xmalloc (sizeof (derivation)); derivation *res = xmalloc (sizeof *res);
deriv->sym = sym; res->sym = sym;
deriv->children = children; res->children = children;
deriv->reference_count = 0; res->reference_count = 0;
deriv->color = -1; res->color = -1;
return deriv; return res;
} }
void void
@@ -135,12 +135,6 @@ derivation_size (const derivation *deriv)
} }
static int
max (int a, int b)
{
return a < b ? b : a;
}
// Longest distance from root to leaf. // Longest distance from root to leaf.
static int static int
derivation_depth (const derivation *deriv) derivation_depth (const derivation *deriv)
@@ -154,7 +148,7 @@ derivation_depth (const derivation *deriv)
for (gl_list_iterator_t it = gl_list_iterator (deriv->children); for (gl_list_iterator_t it = gl_list_iterator (deriv->children);
derivation_list_next (&it, &child); derivation_list_next (&it, &child);
) )
res = max (res, derivation_depth (child)); res = max_int (res, derivation_depth (child));
return res + 1; return res + 1;
} }
else else
@@ -237,7 +231,7 @@ derivation_width (const derivation *deriv)
// No separator at the beginning. // No separator at the beginning.
children_width -= derivation_separator_width; children_width -= derivation_separator_width;
} }
return max (self_width, children_width); return max_int (self_width, children_width);
} }
else if (deriv == &d_dot) else if (deriv == &d_dot)
{ {
+9 -1
View File
@@ -112,7 +112,15 @@ static struct obstack obstack_for_string;
# define STRING_1GROW(Char) \ # define STRING_1GROW(Char) \
obstack_1grow (&obstack_for_string, Char) obstack_1grow (&obstack_for_string, Char)
# define STRING_FREE() \ # ifdef NDEBUG
# define STRING_FREE() \
obstack_free (&obstack_for_string, last_string) obstack_free (&obstack_for_string, last_string)
# else
# define STRING_FREE() \
do { \
obstack_free (&obstack_for_string, last_string); \
last_string = NULL; \
} while (0)
# endif
#endif #endif
+1 -1
View File
@@ -423,7 +423,7 @@ ielr_item_has_lookahead (state *s, symbol_number lhs, size_t item,
check all predecessors' goto follows for the LHS. */ check all predecessors' goto follows for the LHS. */
if (item_number_is_rule_number (ritem[s->items[item] - 2])) if (item_number_is_rule_number (ritem[s->items[item] - 2]))
{ {
aver (lhs != accept->content->number); aver (lhs != acceptsymbol->content->number);
for (state **predecessor = predecessors[s->number]; for (state **predecessor = predecessors[s->number];
*predecessor; *predecessor;
++predecessor) ++predecessor)
-1
View File
@@ -143,7 +143,6 @@ src_bison_LDADD = \
$(LIB_SETLOCALE_NULL) \ $(LIB_SETLOCALE_NULL) \
$(LIBICONV) \ $(LIBICONV) \
$(LIBINTL) \ $(LIBINTL) \
$(LIBREADLINE) \
$(LIBTEXTSTYLE) $(LIBTEXTSTYLE)
+3 -13
View File
@@ -40,18 +40,6 @@
location const empty_loc = EMPTY_LOCATION_INIT; location const empty_loc = EMPTY_LOCATION_INIT;
static int
min_int (int a, int b)
{
return a < b ? a : b;
}
static int
max_int (int a, int b)
{
return a >= b ? a : b;
}
/* The terminal width. Not less than 40. */ /* The terminal width. Not less than 40. */
static int static int
columns (void) columns (void)
@@ -167,7 +155,9 @@ int
location_print (location loc, FILE *out) location_print (location loc, FILE *out)
{ {
int res = 0; int res = 0;
if (trace_flag & trace_locations) if (location_empty (loc))
res += fprintf (out, "(empty location)");
else if (trace_flag & trace_locations)
{ {
res += boundary_print (&loc.start, out); res += boundary_print (&loc.start, out);
res += fprintf (out, "-"); res += fprintf (out, "-");
+1 -1
View File
@@ -256,7 +256,7 @@ shortest_path_from_start (state_item_number target, symbol_number next_sym)
gl_list_iterator_t it = gl_list_iterator (res); gl_list_iterator_t it = gl_list_iterator (res);
const void *sip; const void *sip;
while (gl_list_iterator_next (&it, &sip, NULL)) while (gl_list_iterator_next (&it, &sip, NULL))
print_state_item ((state_item *) sip, stdout, ""); state_item_print ((state_item *) sip, stdout, "");
} }
return res; return res;
} }
+4 -4
View File
@@ -249,7 +249,7 @@ prepare_symbol_names (char const *muscle_name)
if (i) if (i)
obstack_1grow (&format_obstack, ' '); obstack_1grow (&format_obstack, ' ');
if (translatable) if (translatable)
obstack_sgrow (&format_obstack, "]b4_symbol_translate(["); obstack_sgrow (&format_obstack, "]b4_symbol_translate""([");
obstack_escape (&format_obstack, cp); obstack_escape (&format_obstack, cp);
if (translatable) if (translatable)
obstack_sgrow (&format_obstack, "])["); obstack_sgrow (&format_obstack, "])[");
@@ -554,7 +554,7 @@ prepare_symbol_definitions (void)
/* Map "orig NUM" to new numbers. See data/README. */ /* Map "orig NUM" to new numbers. See data/README. */
for (symbol_number i = ntokens; i < nsyms + nuseless_nonterminals; ++i) for (symbol_number i = ntokens; i < nsyms + nuseless_nonterminals; ++i)
{ {
obstack_printf (&format_obstack, "symbol(orig %d, number)", i); obstack_printf (&format_obstack, "symbol""(orig %d, number)", i);
const char *key = obstack_finish0 (&format_obstack); const char *key = obstack_finish0 (&format_obstack);
MUSCLE_INSERT_INT (key, nterm_map ? nterm_map[i - ntokens] : i); MUSCLE_INSERT_INT (key, nterm_map ? nterm_map[i - ntokens] : i);
} }
@@ -565,12 +565,12 @@ prepare_symbol_definitions (void)
const char *key; const char *key;
#define SET_KEY(Entry) \ #define SET_KEY(Entry) \
obstack_printf (&format_obstack, "symbol(%d, %s)", \ obstack_printf (&format_obstack, "symbol""(%d, %s)", \
i, Entry); \ i, Entry); \
key = obstack_finish0 (&format_obstack); key = obstack_finish0 (&format_obstack);
#define SET_KEY2(Entry, Suffix) \ #define SET_KEY2(Entry, Suffix) \
obstack_printf (&format_obstack, "symbol(%d, %s_%s)", \ obstack_printf (&format_obstack, "symbol""(%d, %s_%s)", \
i, Entry, Suffix); \ i, Entry, Suffix); \
key = obstack_finish0 (&format_obstack); key = obstack_finish0 (&format_obstack);
+22 -23
View File
@@ -1,4 +1,4 @@
/* A Bison parser, made by GNU Bison 3.6.90. */ /* A Bison parser, made by GNU Bison 3.7.14-eb26-dirty. */
/* Bison implementation for Yacc-like parsers in C /* Bison implementation for Yacc-like parsers in C
@@ -49,7 +49,7 @@
#define YYBISON 1 #define YYBISON 1
/* Bison version. */ /* Bison version. */
#define YYBISON_VERSION "3.6.90" #define YYBISON_VERSION "3.7.14-eb26-dirty"
/* Skeleton name. */ /* Skeleton name. */
#define YYSKELETON_NAME "yacc.c" #define YYSKELETON_NAME "yacc.c"
@@ -149,7 +149,7 @@ enum yysymbol_kind_t
YYSYMBOL_BRACED_CODE = 41, /* "{...}" */ YYSYMBOL_BRACED_CODE = 41, /* "{...}" */
YYSYMBOL_BRACED_PREDICATE = 42, /* "%?{...}" */ YYSYMBOL_BRACED_PREDICATE = 42, /* "%?{...}" */
YYSYMBOL_BRACKETED_ID = 43, /* "[identifier]" */ YYSYMBOL_BRACKETED_ID = 43, /* "[identifier]" */
YYSYMBOL_CHAR = 44, /* "character literal" */ YYSYMBOL_CHAR_LITERAL = 44, /* "character literal" */
YYSYMBOL_COLON = 45, /* ":" */ YYSYMBOL_COLON = 45, /* ":" */
YYSYMBOL_EPILOGUE = 46, /* "epilogue" */ YYSYMBOL_EPILOGUE = 46, /* "epilogue" */
YYSYMBOL_EQUAL = 47, /* "=" */ YYSYMBOL_EQUAL = 47, /* "=" */
@@ -162,7 +162,7 @@ enum yysymbol_kind_t
YYSYMBOL_TAG = 54, /* "<tag>" */ YYSYMBOL_TAG = 54, /* "<tag>" */
YYSYMBOL_TAG_ANY = 55, /* "<*>" */ YYSYMBOL_TAG_ANY = 55, /* "<*>" */
YYSYMBOL_TAG_NONE = 56, /* "<>" */ YYSYMBOL_TAG_NONE = 56, /* "<>" */
YYSYMBOL_INT = 57, /* "integer literal" */ YYSYMBOL_INT_LITERAL = 57, /* "integer literal" */
YYSYMBOL_PERCENT_PARAM = 58, /* "%param" */ YYSYMBOL_PERCENT_PARAM = 58, /* "%param" */
YYSYMBOL_PERCENT_UNION = 59, /* "%union" */ YYSYMBOL_PERCENT_UNION = 59, /* "%union" */
YYSYMBOL_PERCENT_EMPTY = 60, /* "%empty" */ YYSYMBOL_PERCENT_EMPTY = 60, /* "%empty" */
@@ -1115,8 +1115,8 @@ tron (yyo);
{ fprintf (yyo, "[%s]", ((*yyvaluep).BRACKETED_ID)); } { fprintf (yyo, "[%s]", ((*yyvaluep).BRACKETED_ID)); }
break; break;
case YYSYMBOL_CHAR: /* "character literal" */ case YYSYMBOL_CHAR_LITERAL: /* "character literal" */
{ fputs (char_name (((*yyvaluep).CHAR)), yyo); } { fputs (char_name (((*yyvaluep).CHAR_LITERAL)), yyo); }
break; break;
case YYSYMBOL_EPILOGUE: /* "epilogue" */ case YYSYMBOL_EPILOGUE: /* "epilogue" */
@@ -1139,8 +1139,8 @@ tron (yyo);
{ fprintf (yyo, "<%s>", ((*yyvaluep).TAG)); } { fprintf (yyo, "<%s>", ((*yyvaluep).TAG)); }
break; break;
case YYSYMBOL_INT: /* "integer literal" */ case YYSYMBOL_INT_LITERAL: /* "integer literal" */
{ fprintf (yyo, "%d", ((*yyvaluep).INT)); } { fprintf (yyo, "%d", ((*yyvaluep).INT_LITERAL)); }
break; break;
case YYSYMBOL_PERCENT_PARAM: /* "%param" */ case YYSYMBOL_PERCENT_PARAM: /* "%param" */
@@ -2087,11 +2087,11 @@ yyreduce:
break; break;
case 12: /* prologue_declaration: "%expect" "integer literal" */ case 12: /* prologue_declaration: "%expect" "integer literal" */
{ expected_sr_conflicts = (yyvsp[0].INT); } { expected_sr_conflicts = (yyvsp[0].INT_LITERAL); }
break; break;
case 13: /* prologue_declaration: "%expect-rr" "integer literal" */ case 13: /* prologue_declaration: "%expect-rr" "integer literal" */
{ expected_rr_conflicts = (yyvsp[0].INT); } { expected_rr_conflicts = (yyvsp[0].INT_LITERAL); }
break; break;
case 14: /* prologue_declaration: "%file-prefix" "string" */ case 14: /* prologue_declaration: "%file-prefix" "string" */
@@ -2339,13 +2339,13 @@ yyreduce:
case 67: /* token_decls: "<tag>" token_decl.1 */ case 67: /* token_decls: "<tag>" token_decl.1 */
{ {
(yyval.token_decls) = symbol_list_type_set ((yyvsp[0].yykind_80), (yyvsp[-1].TAG), (yylsp[-1])); (yyval.token_decls) = symbol_list_type_set ((yyvsp[0].yykind_80), (yyvsp[-1].TAG));
} }
break; break;
case 68: /* token_decls: token_decls "<tag>" token_decl.1 */ case 68: /* token_decls: token_decls "<tag>" token_decl.1 */
{ {
(yyval.token_decls) = symbol_list_append ((yyvsp[-2].token_decls), symbol_list_type_set ((yyvsp[0].yykind_80), (yyvsp[-1].TAG), (yylsp[-1]))); (yyval.token_decls) = symbol_list_append ((yyvsp[-2].token_decls), symbol_list_type_set ((yyvsp[0].yykind_80), (yyvsp[-1].TAG)));
} }
break; break;
@@ -2396,13 +2396,13 @@ yyreduce:
case 78: /* token_decls_for_prec: "<tag>" token_decl_for_prec.1 */ case 78: /* token_decls_for_prec: "<tag>" token_decl_for_prec.1 */
{ {
(yyval.token_decls_for_prec) = symbol_list_type_set ((yyvsp[0].yykind_85), (yyvsp[-1].TAG), (yylsp[-1])); (yyval.token_decls_for_prec) = symbol_list_type_set ((yyvsp[0].yykind_85), (yyvsp[-1].TAG));
} }
break; break;
case 79: /* token_decls_for_prec: token_decls_for_prec "<tag>" token_decl_for_prec.1 */ case 79: /* token_decls_for_prec: token_decls_for_prec "<tag>" token_decl_for_prec.1 */
{ {
(yyval.token_decls_for_prec) = symbol_list_append ((yyvsp[-2].token_decls_for_prec), symbol_list_type_set ((yyvsp[0].yykind_85), (yyvsp[-1].TAG), (yylsp[-1]))); (yyval.token_decls_for_prec) = symbol_list_append ((yyvsp[-2].token_decls_for_prec), symbol_list_type_set ((yyvsp[0].yykind_85), (yyvsp[-1].TAG)));
} }
break; break;
@@ -2431,13 +2431,13 @@ yyreduce:
case 85: /* symbol_decls: "<tag>" symbol_decl.1 */ case 85: /* symbol_decls: "<tag>" symbol_decl.1 */
{ {
(yyval.symbol_decls) = symbol_list_type_set ((yyvsp[0].yykind_88), (yyvsp[-1].TAG), (yylsp[-1])); (yyval.symbol_decls) = symbol_list_type_set ((yyvsp[0].yykind_88), (yyvsp[-1].TAG));
} }
break; break;
case 86: /* symbol_decls: symbol_decls "<tag>" symbol_decl.1 */ case 86: /* symbol_decls: symbol_decls "<tag>" symbol_decl.1 */
{ {
(yyval.symbol_decls) = symbol_list_append ((yyvsp[-2].symbol_decls), symbol_list_type_set ((yyvsp[0].yykind_88), (yyvsp[-1].TAG), (yylsp[-1]))); (yyval.symbol_decls) = symbol_list_append ((yyvsp[-2].symbol_decls), symbol_list_type_set ((yyvsp[0].yykind_88), (yyvsp[-1].TAG)));
} }
break; break;
@@ -2506,7 +2506,7 @@ yyreduce:
break; break;
case 105: /* rhs: rhs "%dprec" "integer literal" */ case 105: /* rhs: rhs "%dprec" "integer literal" */
{ grammar_current_rule_dprec_set ((yyvsp[0].INT), (yylsp[0])); } { grammar_current_rule_dprec_set ((yyvsp[0].INT_LITERAL), (yylsp[0])); }
break; break;
case 106: /* rhs: rhs "%merge" "<tag>" */ case 106: /* rhs: rhs "%merge" "<tag>" */
@@ -2514,11 +2514,11 @@ yyreduce:
break; break;
case 107: /* rhs: rhs "%expect" "integer literal" */ case 107: /* rhs: rhs "%expect" "integer literal" */
{ grammar_current_rule_expect_sr ((yyvsp[0].INT), (yylsp[0])); } { grammar_current_rule_expect_sr ((yyvsp[0].INT_LITERAL), (yylsp[0])); }
break; break;
case 108: /* rhs: rhs "%expect-rr" "integer literal" */ case 108: /* rhs: rhs "%expect-rr" "integer literal" */
{ grammar_current_rule_expect_rr ((yyvsp[0].INT), (yylsp[0])); } { grammar_current_rule_expect_rr ((yyvsp[0].INT_LITERAL), (yylsp[0])); }
break; break;
case 109: /* named_ref.opt: %empty */ case 109: /* named_ref.opt: %empty */
@@ -2566,9 +2566,9 @@ yyreduce:
location loc = muscle_percent_define_get_loc (var); location loc = muscle_percent_define_get_loc (var);
subcomplain (&loc, complaint, _("definition of %s"), var); subcomplain (&loc, complaint, _("definition of %s"), var);
} }
(yyval.id) = symbol_get (char_name ((yyvsp[0].CHAR)), (yylsp[0])); (yyval.id) = symbol_get (char_name ((yyvsp[0].CHAR_LITERAL)), (yylsp[0]));
symbol_class_set ((yyval.id), token_sym, (yylsp[0]), false); symbol_class_set ((yyval.id), token_sym, (yylsp[0]), false);
symbol_code_set ((yyval.id), (yyvsp[0].CHAR), (yylsp[0])); symbol_code_set ((yyval.id), (yyvsp[0].CHAR_LITERAL), (yylsp[0]));
} }
break; break;
@@ -3147,8 +3147,7 @@ char_name (char c)
} }
} }
static static void
void
current_lhs (symbol *sym, location loc, named_ref *ref) current_lhs (symbol *sym, location loc, named_ref *ref)
{ {
current_lhs_symbol = sym; current_lhs_symbol = sym;
+5 -5
View File
@@ -1,4 +1,4 @@
/* A Bison parser, made by GNU Bison 3.6.90. */ /* A Bison parser, made by GNU Bison 3.7.14-eb26-dirty. */
/* Bison interface for Yacc-like parsers in C /* Bison interface for Yacc-like parsers in C
@@ -123,7 +123,7 @@ extern int gram_debug;
BRACED_CODE = 41, /* "{...}" */ BRACED_CODE = 41, /* "{...}" */
BRACED_PREDICATE = 42, /* "%?{...}" */ BRACED_PREDICATE = 42, /* "%?{...}" */
BRACKETED_ID = 43, /* "[identifier]" */ BRACKETED_ID = 43, /* "[identifier]" */
CHAR = 44, /* "character literal" */ CHAR_LITERAL = 44, /* "character literal" */
COLON = 45, /* ":" */ COLON = 45, /* ":" */
EPILOGUE = 46, /* "epilogue" */ EPILOGUE = 46, /* "epilogue" */
EQUAL = 47, /* "=" */ EQUAL = 47, /* "=" */
@@ -136,7 +136,7 @@ extern int gram_debug;
TAG = 54, /* "<tag>" */ TAG = 54, /* "<tag>" */
TAG_ANY = 55, /* "<*>" */ TAG_ANY = 55, /* "<*>" */
TAG_NONE = 56, /* "<>" */ TAG_NONE = 56, /* "<>" */
INT = 57, /* "integer literal" */ INT_LITERAL = 57, /* "integer literal" */
PERCENT_PARAM = 58, /* "%param" */ PERCENT_PARAM = 58, /* "%param" */
PERCENT_UNION = 59, /* "%union" */ PERCENT_UNION = 59, /* "%union" */
PERCENT_EMPTY = 60 /* "%empty" */ PERCENT_EMPTY = 60 /* "%empty" */
@@ -156,7 +156,7 @@ union GRAM_STYPE
char* EPILOGUE; /* "epilogue" */ char* EPILOGUE; /* "epilogue" */
char* PROLOGUE; /* "%{...%}" */ char* PROLOGUE; /* "%{...%}" */
code_props_type code_props_type; /* code_props_type */ code_props_type code_props_type; /* code_props_type */
int INT; /* "integer literal" */ int INT_LITERAL; /* "integer literal" */
int yykind_82; /* int.opt */ int yykind_82; /* int.opt */
named_ref* yykind_95; /* named_ref.opt */ named_ref* yykind_95; /* named_ref.opt */
param_type PERCENT_PARAM; /* "%param" */ param_type PERCENT_PARAM; /* "%param" */
@@ -188,7 +188,7 @@ union GRAM_STYPE
uniqstr yykind_74; /* tag.opt */ uniqstr yykind_74; /* tag.opt */
uniqstr tag; /* tag */ uniqstr tag; /* tag */
uniqstr variable; /* variable */ uniqstr variable; /* variable */
unsigned char CHAR; /* "character literal" */ unsigned char CHAR_LITERAL; /* "character literal" */
value_type value; /* value */ value_type value; /* value */
+17 -18
View File
@@ -214,7 +214,7 @@
BRACED_CODE "{...}" BRACED_CODE "{...}"
BRACED_PREDICATE "%?{...}" BRACED_PREDICATE "%?{...}"
BRACKETED_ID _("[identifier]") BRACKETED_ID _("[identifier]")
CHAR _("character literal") CHAR_LITERAL _("character literal")
COLON ":" COLON ":"
EPILOGUE _("epilogue") EPILOGUE _("epilogue")
EQUAL "=" EQUAL "="
@@ -232,7 +232,7 @@
%code pre-printer {tron (yyo);} %code pre-printer {tron (yyo);}
%code post-printer {troff (yyo);} %code post-printer {troff (yyo);}
%type <unsigned char> CHAR %type <unsigned char> CHAR_LITERAL
%printer { fputs (char_name ($$), yyo); } <unsigned char> %printer { fputs (char_name ($$), yyo); } <unsigned char>
%type <char*> "{...}" "%?{...}" "%{...%}" EPILOGUE STRING TSTRING %type <char*> "{...}" "%?{...}" "%{...%}" EPILOGUE STRING TSTRING
@@ -249,7 +249,7 @@
%printer { fprintf (yyo, "%%%s", $$); } PERCENT_FLAG %printer { fprintf (yyo, "%%%s", $$); } PERCENT_FLAG
%printer { fprintf (yyo, "<%s>", $$); } TAG tag %printer { fprintf (yyo, "<%s>", $$); } TAG tag
%token <int> INT _("integer literal") %token <int> INT_LITERAL _("integer literal")
%printer { fprintf (yyo, "%d", $$); } <int> %printer { fprintf (yyo, "%d", $$); } <int>
%type <symbol*> id id_colon string_as_id symbol token_decl token_decl_for_prec %type <symbol*> id id_colon string_as_id symbol token_decl token_decl_for_prec
@@ -342,8 +342,8 @@ prologue_declaration:
| "%defines" { defines_flag = true; } | "%defines" { defines_flag = true; }
| "%defines" STRING { handle_defines ($2); } | "%defines" STRING { handle_defines ($2); }
| "%error-verbose" { handle_error_verbose (&@$, $1); } | "%error-verbose" { handle_error_verbose (&@$, $1); }
| "%expect" INT { expected_sr_conflicts = $2; } | "%expect" INT_LITERAL { expected_sr_conflicts = $2; }
| "%expect-rr" INT { expected_rr_conflicts = $2; } | "%expect-rr" INT_LITERAL { expected_rr_conflicts = $2; }
| "%file-prefix" STRING { handle_file_prefix (&@$, &@1, $1, $2); } | "%file-prefix" STRING { handle_file_prefix (&@$, &@1, $1, $2); }
| "%glr-parser" | "%glr-parser"
{ {
@@ -532,11 +532,11 @@ token_decls:
} }
| TAG token_decl.1[syms] | TAG token_decl.1[syms]
{ {
$$ = symbol_list_type_set ($syms, $TAG, @TAG); $$ = symbol_list_type_set ($syms, $TAG);
} }
| token_decls TAG token_decl.1[syms] | token_decls TAG token_decl.1[syms]
{ {
$$ = symbol_list_append ($1, symbol_list_type_set ($syms, $TAG, @TAG)); $$ = symbol_list_append ($1, symbol_list_type_set ($syms, $TAG));
} }
; ;
@@ -561,7 +561,7 @@ token_decl:
%type <int> int.opt; %type <int> int.opt;
int.opt: int.opt:
%empty { $$ = -1; } %empty { $$ = -1; }
| INT | INT_LITERAL
; ;
%type <symbol*> alias; %type <symbol*> alias;
@@ -592,11 +592,11 @@ token_decls_for_prec:
} }
| TAG token_decl_for_prec.1[syms] | TAG token_decl_for_prec.1[syms]
{ {
$$ = symbol_list_type_set ($syms, $TAG, @TAG); $$ = symbol_list_type_set ($syms, $TAG);
} }
| token_decls_for_prec TAG token_decl_for_prec.1[syms] | token_decls_for_prec TAG token_decl_for_prec.1[syms]
{ {
$$ = symbol_list_append ($1, symbol_list_type_set ($syms, $TAG, @TAG)); $$ = symbol_list_append ($1, symbol_list_type_set ($syms, $TAG));
} }
; ;
@@ -632,11 +632,11 @@ symbol_decls:
} }
| TAG symbol_decl.1[syms] | TAG symbol_decl.1[syms]
{ {
$$ = symbol_list_type_set ($syms, $TAG, @TAG); $$ = symbol_list_type_set ($syms, $TAG);
} }
| symbol_decls TAG symbol_decl.1[syms] | symbol_decls TAG symbol_decl.1[syms]
{ {
$$ = symbol_list_append ($1, symbol_list_type_set ($syms, $TAG, @TAG)); $$ = symbol_list_append ($1, symbol_list_type_set ($syms, $TAG));
} }
; ;
@@ -703,13 +703,13 @@ rhs:
{ grammar_current_rule_empty_set (@2); } { grammar_current_rule_empty_set (@2); }
| rhs "%prec" symbol | rhs "%prec" symbol
{ grammar_current_rule_prec_set ($3, @3); } { grammar_current_rule_prec_set ($3, @3); }
| rhs "%dprec" INT | rhs "%dprec" INT_LITERAL
{ grammar_current_rule_dprec_set ($3, @3); } { grammar_current_rule_dprec_set ($3, @3); }
| rhs "%merge" TAG | rhs "%merge" TAG
{ grammar_current_rule_merge_set ($3, @3); } { grammar_current_rule_merge_set ($3, @3); }
| rhs "%expect" INT | rhs "%expect" INT_LITERAL
{ grammar_current_rule_expect_sr ($3, @3); } { grammar_current_rule_expect_sr ($3, @3); }
| rhs "%expect-rr" INT | rhs "%expect-rr" INT_LITERAL
{ grammar_current_rule_expect_rr ($3, @3); } { grammar_current_rule_expect_rr ($3, @3); }
; ;
@@ -765,7 +765,7 @@ value:
id: id:
ID ID
{ $$ = symbol_from_uniqstr ($1, @1); } { $$ = symbol_from_uniqstr ($1, @1); }
| CHAR | CHAR_LITERAL
{ {
const char *var = "api.token.raw"; const char *var = "api.token.raw";
if (current_class == nterm_sym) if (current_class == nterm_sym)
@@ -1158,8 +1158,7 @@ char_name (char c)
} }
} }
static static void
void
current_lhs (symbol *sym, location loc, named_ref *ref) current_lhs (symbol *sym, location loc, named_ref *ref)
{ {
current_lhs_symbol = sym; current_lhs_symbol = sym;
+15 -19
View File
@@ -28,19 +28,19 @@
#include "lssi.h" #include "lssi.h"
#include "nullable.h" #include "nullable.h"
typedef struct parse_state struct parse_state
{ {
// path of state-items the parser has traversed // Path of state-items the parser has traversed.
struct si_chunk struct si_chunk
{ {
// elements newly added in this chunk // Elements newly added in this chunk.
state_item_list contents; state_item_list contents;
// properties of the linked list this chunk represents // Properties of the linked list this chunk represents.
const state_item *head_elt; const state_item *head_elt;
const state_item *tail_elt; const state_item *tail_elt;
size_t total_size; size_t total_size;
} state_items; } state_items;
// list of derivations of the symbols // List of derivations of the symbols.
struct deriv_chunk struct deriv_chunk
{ {
derivation_list contents; derivation_list contents;
@@ -50,18 +50,15 @@ typedef struct parse_state
} derivs; } derivs;
struct parse_state *parent; struct parse_state *parent;
int reference_count; int reference_count;
// incremented during productions, // Incremented during productions, decremented during reductions.
// decremented during reductions
int depth; int depth;
// whether the contents of the chunks should be // Whether the contents of the chunks should be prepended or
// prepended or appended to the list the chunks // appended to the list the chunks represent.
// represent
bool prepend; bool prepend;
// causes chunk contents to be freed when the // Causes chunk contents to be freed when the reference count is
// reference count is one. Used when only the chunk metadata // one. Used when only the chunk metadata will be needed.
// will be needed.
bool free_contents_early; bool free_contents_early;
} parse_state; };
static void static void
@@ -438,9 +435,8 @@ simulate_transition (parse_state *ps)
// symbols into account. // symbols into account.
parse_state_list result = parse_state_list_new (); parse_state_list result = parse_state_list_new ();
state_item_number si_next = si->trans; state_item_number si_next = si->trans;
// check for disabled transition, shouldn't happen // Check for disabled transition, shouldn't happen as any
// as any state_items that lead to these should be // state_items that lead to these should be disabled.
// disabled.
if (si_next < 0) if (si_next < 0)
return result; return result;
parse_state *next_ps = copy_parse_state (false, ps); parse_state *next_ps = copy_parse_state (false, ps);
@@ -594,8 +590,8 @@ print_parse_state (parse_state *ps)
FILE *out = stderr; FILE *out = stderr;
fprintf (out, "(size %zu depth %d rc %d)\n", fprintf (out, "(size %zu depth %d rc %d)\n",
ps->state_items.total_size, ps->depth, ps->reference_count); ps->state_items.total_size, ps->depth, ps->reference_count);
print_state_item (ps->state_items.head_elt, out, ""); state_item_print (ps->state_items.head_elt, out, "");
print_state_item (ps->state_items.tail_elt, out, ""); state_item_print (ps->state_items.tail_elt, out, "");
if (ps->derivs.total_size > 0) if (ps->derivs.total_size > 0)
derivation_print (ps->derivs.head_elt, out, ""); derivation_print (ps->derivs.head_elt, out, "");
putc ('\n', out); putc ('\n', out);
+8 -5
View File
@@ -406,8 +406,8 @@ grammar_midrule_action (void)
action. Create the MIDRULE. */ action. Create the MIDRULE. */
location dummy_loc = current_rule->action_props.location; location dummy_loc = current_rule->action_props.location;
symbol *dummy = dummy_symbol_get (dummy_loc); symbol *dummy = dummy_symbol_get (dummy_loc);
symbol_type_set(dummy, symbol_type_set (dummy,
current_rule->action_props.type, current_rule->action_props.location); current_rule->action_props.type, current_rule->action_props.location);
symbol_list *midrule = symbol_list_sym_new (dummy, dummy_loc); symbol_list *midrule = symbol_list_sym_new (dummy, dummy_loc);
/* Remember named_ref of previous action. */ /* Remember named_ref of previous action. */
@@ -804,7 +804,7 @@ check_and_convert_grammar (void)
$accept: %start $end. */ $accept: %start $end. */
{ {
symbol_list *p = symbol_list_sym_new (accept, empty_loc); symbol_list *p = symbol_list_sym_new (acceptsymbol, empty_loc);
p->rhs_loc = grammar->rhs_loc; p->rhs_loc = grammar->rhs_loc;
p->next = symbol_list_sym_new (startsymbol, empty_loc); p->next = symbol_list_sym_new (startsymbol, empty_loc);
p->next->next = symbol_list_sym_new (eoftoken, empty_loc); p->next->next = symbol_list_sym_new (eoftoken, empty_loc);
@@ -815,8 +815,11 @@ check_and_convert_grammar (void)
grammar = p; grammar = p;
} }
aver (nsyms <= SYMBOL_NUMBER_MAXIMUM); if (SYMBOL_NUMBER_MAXIMUM - nnterms < ntokens)
aver (nsyms == ntokens + nnterms); complain (NULL, fatal, "too many symbols in input grammar (limit is %d)",
SYMBOL_NUMBER_MAXIMUM);
nsyms = ntokens + nnterms;
/* Assign the symbols their symbol numbers. */ /* Assign the symbols their symbol numbers. */
symbols_pack (); symbols_pack ();
+4 -4
View File
@@ -160,9 +160,9 @@ inaccessable_symbols (void)
bitset Pp = bitset_create (nrules, BITSET_FIXED); bitset Pp = bitset_create (nrules, BITSET_FIXED);
/* If the start symbol isn't useful, then nothing will be useful. */ /* If the start symbol isn't useful, then nothing will be useful. */
if (bitset_test (N, accept->content->number - ntokens)) if (bitset_test (N, acceptsymbol->content->number - ntokens))
{ {
bitset_set (V, accept->content->number); bitset_set (V, acceptsymbol->content->number);
while (1) while (1)
{ {
@@ -301,7 +301,7 @@ nonterminals_reduce (void)
for (item_number *rhsp = rules[r].rhs; 0 <= *rhsp; ++rhsp) for (item_number *rhsp = rules[r].rhs; 0 <= *rhsp; ++rhsp)
if (ISVAR (*rhsp)) if (ISVAR (*rhsp))
*rhsp = symbol_number_as_item_number (nterm_map[*rhsp - ntokens]); *rhsp = symbol_number_as_item_number (nterm_map[*rhsp - ntokens]);
accept->content->number = nterm_map[accept->content->number - ntokens]; acceptsymbol->content->number = nterm_map[acceptsymbol->content->number - ntokens];
} }
nsyms -= nuseless_nonterminals; nsyms -= nuseless_nonterminals;
@@ -381,7 +381,7 @@ reduce_grammar (void)
{ {
reduce_print (); reduce_print ();
if (!bitset_test (N, accept->content->number - ntokens)) if (!bitset_test (N, acceptsymbol->content->number - ntokens))
complain (&startsymbol_loc, fatal, complain (&startsymbol_loc, fatal,
_("start symbol %s does not derive any sentence"), _("start symbol %s does not derive any sentence"),
startsymbol->tag); startsymbol->tag);
+21 -12
View File
@@ -322,8 +322,8 @@ eqopt ({sp}=)?
BEGIN SC_AFTER_IDENTIFIER; BEGIN SC_AFTER_IDENTIFIER;
} }
{int} RETURN_VALUE (INT, scan_integer (yytext, 10, *loc)); {int} RETURN_VALUE (INT_LITERAL, scan_integer (yytext, 10, *loc));
{xint} RETURN_VALUE (INT, scan_integer (yytext, 16, *loc)); {xint} RETURN_VALUE (INT_LITERAL, scan_integer (yytext, 16, *loc));
/* Identifiers may not start with a digit. Yet, don't silently /* Identifiers may not start with a digit. Yet, don't silently
accept "1FOO" as "1 FOO". */ accept "1FOO" as "1 FOO". */
@@ -403,6 +403,7 @@ eqopt ({sp}=)?
{ {
\0 { \0 {
complain (loc, complaint, _("invalid null character")); complain (loc, complaint, _("invalid null character"));
STRING_FINISH ();
STRING_FREE (); STRING_FREE ();
return GRAM_error; return GRAM_error;
} }
@@ -566,6 +567,8 @@ eqopt ({sp}=)?
_("POSIX Yacc does not support string literals")); _("POSIX Yacc does not support string literals"));
RETURN_VALUE (STRING, last_string); RETURN_VALUE (STRING, last_string);
} }
<<EOF>> unexpected_eof (token_start, "\"");
"\n" unexpected_newline (token_start, "\"");
} }
<SC_ESCAPED_TSTRING> <SC_ESCAPED_TSTRING>
@@ -579,13 +582,10 @@ eqopt ({sp}=)?
_("POSIX Yacc does not support string literals")); _("POSIX Yacc does not support string literals"));
RETURN_VALUE (TSTRING, last_string); RETURN_VALUE (TSTRING, last_string);
} }
<<EOF>> unexpected_eof (token_start, "\")");
"\n" unexpected_newline (token_start, "\")");
} }
<SC_ESCAPED_STRING,SC_ESCAPED_TSTRING>
{
<<EOF>> unexpected_eof (token_start, "\"");
"\n" unexpected_newline (token_start, "\"");
}
/*----------------------------------------------------------. /*----------------------------------------------------------.
@@ -599,7 +599,6 @@ eqopt ({sp}=)?
STRING_FINISH (); STRING_FINISH ();
BEGIN INITIAL; BEGIN INITIAL;
loc->start = token_start; loc->start = token_start;
val->CHAR = last_string[0];
if (last_string[0] == '\0') if (last_string[0] == '\0')
{ {
@@ -615,8 +614,9 @@ eqopt ({sp}=)?
} }
else else
{ {
val->CHAR_LITERAL = last_string[0];
STRING_FREE (); STRING_FREE ();
return CHAR; return CHAR_LITERAL;
} }
} }
{eol} unexpected_newline (token_start, "'"); {eol} unexpected_newline (token_start, "'");
@@ -691,6 +691,15 @@ eqopt ({sp}=)?
p); p);
STRING_1GROW ('?'); STRING_1GROW ('?');
} }
"\\" {
// None of the other rules matched: the last character of this
// file is "\". But Flex does not support "\\<<EOF>>".
unexpected_eof (token_start,
YY_START == SC_ESCAPED_CHARACTER ? "?'"
: YY_START == SC_ESCAPED_STRING ? "?\""
: "?\")");
}
} }
/*--------------------------------------------. /*--------------------------------------------.
@@ -933,9 +942,9 @@ convert_ucn_to_byte (char const *ucn)
} }
/*---------------------------------------------------------------------. /*----------------------------------------------------------------------------.
| Handle '#line INT( "FILE")?\n'. ARGS has already skipped '#line '. | | Handle '#line INT_LITERAL( "FILE")?\n'. ARGS has already skipped '#line '. |
`---------------------------------------------------------------------*/ `----------------------------------------------------------------------------*/
static void static void
handle_syncline (char *args, location loc) handle_syncline (char *args, location loc)
+3 -3
View File
@@ -475,7 +475,7 @@ prune_disabled_paths (void)
} }
void void
print_state_item (const state_item *si, FILE *out, const char *prefix) state_item_print (const state_item *si, FILE *out, const char *prefix)
{ {
fputs (prefix, out); fputs (prefix, out);
item_print (si->item, NULL, out); item_print (si->item, NULL, out);
@@ -506,7 +506,7 @@ state_items_report (void)
if (si->trans >= 0) if (si->trans >= 0)
{ {
fputs (" -> ", stdout); fputs (" -> ", stdout);
print_state_item (&state_items[si->trans], stdout, ""); state_item_print (&state_items[si->trans], stdout, "");
} }
bitset sets[2] = { si->prods, si->revs }; bitset sets[2] = { si->prods, si->revs };
@@ -521,7 +521,7 @@ state_items_report (void)
BITSET_FOR_EACH (biter, b, sin, 0) BITSET_FOR_EACH (biter, b, sin, 0)
{ {
fputs (txt[seti], stdout); fputs (txt[seti], stdout);
print_state_item (&state_items[sin], stdout, ""); state_item_print (&state_items[sin], stdout, "");
} }
} }
} }
+2 -1
View File
@@ -90,9 +90,10 @@ state_item_index_lookup (state_number s, state_item_number off)
} }
void state_items_init (void); void state_items_init (void);
void print_state_item (const state_item *si, FILE *out, const char *prefix);
void state_items_free (void); void state_items_free (void);
void state_item_print (const state_item *si, FILE *out, const char *prefix);
bool production_allowed (const state_item *si, const state_item *next); bool production_allowed (const state_item *si, const state_item *next);
// Iterating on a state_item_list. // Iterating on a state_item_list.
+2 -2
View File
@@ -83,10 +83,10 @@ symbol_list_type_new (uniqstr type_name, location loc)
symbol_list * symbol_list *
symbol_list_type_set (symbol_list *syms, uniqstr type_name, location loc) symbol_list_type_set (symbol_list *syms, uniqstr type_name)
{ {
for (symbol_list *l = syms; l; l = l->next) for (symbol_list *l = syms; l; l = l->next)
symbol_type_set (l->content.sym, type_name, loc); symbol_type_set (l->content.sym, type_name, l->sym_loc);
return syms; return syms;
} }
+1 -2
View File
@@ -110,8 +110,7 @@ symbol_list *symbol_list_type_new (uniqstr type_name, location loc);
/** Assign the type \c type_name to all the members of \c syms. /** Assign the type \c type_name to all the members of \c syms.
** \returns \c syms */ ** \returns \c syms */
symbol_list *symbol_list_type_set (symbol_list *syms, symbol_list *symbol_list_type_set (symbol_list *syms, uniqstr type_name);
uniqstr type_name, location loc);
/** Print this list. /** Print this list.
+33 -36
View File
@@ -59,7 +59,7 @@ static semantic_type **semantic_types_sorted = NULL;
symbol *errtoken = NULL; symbol *errtoken = NULL;
symbol *undeftoken = NULL; symbol *undeftoken = NULL;
symbol *eoftoken = NULL; symbol *eoftoken = NULL;
symbol *accept = NULL; symbol *acceptsymbol = NULL;
symbol *startsymbol = NULL; symbol *startsymbol = NULL;
location startsymbol_loc; location startsymbol_loc;
@@ -137,11 +137,6 @@ symbol_new (uniqstr tag, location loc)
res->alias = NULL; res->alias = NULL;
res->content = sym_content_new (res); res->content = sym_content_new (res);
res->is_alias = false; res->is_alias = false;
if (nsyms == SYMBOL_NUMBER_MAXIMUM)
complain (NULL, fatal, _("too many symbols in input grammar (limit is %d)"),
SYMBOL_NUMBER_MAXIMUM);
nsyms++;
return res; return res;
} }
@@ -182,11 +177,11 @@ symbol_free (void *ptr)
*/ */
static void static void
symbols_sort (symbol **first, symbol **second) symbols_sort (const symbol **first, const symbol **second)
{ {
if (0 < location_cmp ((*first)->location, (*second)->location)) if (0 < location_cmp ((*first)->location, (*second)->location))
{ {
symbol* tmp = *first; const symbol* tmp = *first;
*first = *second; *first = *second;
*second = tmp; *second = tmp;
} }
@@ -243,7 +238,11 @@ semantic_type_new (uniqstr tag, const location *loc)
| Print a symbol. | | Print a symbol. |
`-----------------*/ `-----------------*/
#define SYMBOL_ATTR_PRINT(Attr) \ #define SYMBOL_INT_ATTR_PRINT(Attr) \
if (s->content) \
fprintf (f, " %s = %d", #Attr, s->content->Attr)
#define SYMBOL_STR_ATTR_PRINT(Attr) \
if (s->content && s->content->Attr) \ if (s->content && s->content->Attr) \
fprintf (f, " %s { %s }", #Attr, s->content->Attr) fprintf (f, " %s { %s }", #Attr, s->content->Attr)
@@ -264,7 +263,11 @@ symbol_print (symbol const *s, FILE *f)
: c == nterm_sym ? "nterm" : c == nterm_sym ? "nterm"
: NULL, /* abort. */ : NULL, /* abort. */
s->tag); s->tag);
SYMBOL_ATTR_PRINT (type_name); putc (' ', f);
location_print (s->location, f);
SYMBOL_INT_ATTR_PRINT (code);
SYMBOL_INT_ATTR_PRINT (number);
SYMBOL_STR_ATTR_PRINT (type_name);
SYMBOL_CODE_PRINT (destructor); SYMBOL_CODE_PRINT (destructor);
SYMBOL_CODE_PRINT (printer); SYMBOL_CODE_PRINT (printer);
} }
@@ -371,7 +374,7 @@ symbol_from_uniqstr_fuzzy (const uniqstr key)
} }
static void static void
complain_symbol_undeclared (symbol *sym) complain_symbol_undeclared (const symbol *sym)
{ {
assert (sym->content->status != declared); assert (sym->content->status != declared);
const symbol *best = symbol_from_uniqstr_fuzzy (sym->tag); const symbol *best = symbol_from_uniqstr_fuzzy (sym->tag);
@@ -398,7 +401,10 @@ void
symbol_location_as_lhs_set (symbol *sym, location loc) symbol_location_as_lhs_set (symbol *sym, location loc)
{ {
if (!sym->location_of_lhs) if (!sym->location_of_lhs)
sym->location = loc; {
sym->location = loc;
sym->location_of_lhs = true;
}
} }
@@ -548,10 +554,6 @@ symbol_class_set (symbol *sym, symbol_class class, location loc, bool declaring)
if (class == token_sym && s->class == pct_type_sym) if (class == token_sym && s->class == pct_type_sym)
complain_pct_type_on_token (&sym->location); complain_pct_type_on_token (&sym->location);
if (class == nterm_sym && s->class != nterm_sym)
s->number = nnterms++;
else if (class == token_sym && s->number == NUMBER_UNDEFINED)
s->number = ntokens++;
s->class = class; s->class = class;
if (declaring) if (declaring)
@@ -573,9 +575,9 @@ symbol_class_set (symbol *sym, symbol_class class, location loc, bool declaring)
} }
/*------------------------------------------------. /*----------------------------.
| Set the USER_TOKEN_NUMBER associated with SYM. | | Set the token code of SYM. |
`------------------------------------------------*/ `----------------------------*/
void void
symbol_code_set (symbol *sym, int code, location loc) symbol_code_set (symbol *sym, int code, location loc)
@@ -598,10 +600,6 @@ symbol_code_set (symbol *sym, int code, location loc)
if (code == 0 && !eoftoken) if (code == 0 && !eoftoken)
{ {
eoftoken = sym->content->symbol; eoftoken = sym->content->symbol;
/* It is always mapped to 0, so it was already counted in
NTOKENS. */
if (eoftoken->content->number != NUMBER_UNDEFINED)
--ntokens;
eoftoken->content->number = 0; eoftoken->content->number = 0;
} }
} }
@@ -621,9 +619,11 @@ symbol_check_defined (symbol *sym)
{ {
complain_symbol_undeclared (sym); complain_symbol_undeclared (sym);
s->class = nterm_sym; s->class = nterm_sym;
s->number = nnterms++;
} }
if (s->number == NUMBER_UNDEFINED)
s->number = s->class == token_sym ? ntokens++ : nnterms++;
if (s->class == token_sym if (s->class == token_sym
&& sym->tag[0] == '"' && sym->tag[0] == '"'
&& !sym->is_alias) && !sym->is_alias)
@@ -742,7 +742,7 @@ symbol_pack (symbol *sym)
} }
static void static void
complain_code_redeclared (int num, symbol *first, symbol *second) complain_code_redeclared (int num, const symbol *first, const symbol *second)
{ {
symbols_sort (&first, &second); symbols_sort (&first, &second);
complain (&second->location, complaint, complain (&second->location, complaint,
@@ -758,13 +758,11 @@ complain_code_redeclared (int num, symbol *first, symbol *second)
`-------------------------------------------------*/ `-------------------------------------------------*/
static void static void
symbol_translation (symbol *sym) symbol_translation (const symbol *sym)
{ {
/* Nonterminal? */ if (sym->content->class == token_sym && !sym->is_alias)
if (sym->content->class == token_sym
&& !sym->is_alias)
{ {
/* A token which translation has already been set?*/ /* A token whose translation has already been set? */
if (token_translations[sym->content->code] if (token_translations[sym->content->code]
!= undeftoken->content->number) != undeftoken->content->number)
complain_code_redeclared complain_code_redeclared
@@ -849,10 +847,10 @@ symbols_new (void)
hash_symbol_comparator, hash_symbol_comparator,
symbol_free); symbol_free);
/* Construct the accept symbol. */ /* Construct the acceptsymbol symbol. */
accept = symbol_get ("$accept", empty_loc); acceptsymbol = symbol_get ("$accept", empty_loc);
accept->content->class = nterm_sym; acceptsymbol->content->class = nterm_sym;
accept->content->number = nnterms++; acceptsymbol->content->number = nnterms++;
/* Construct the YYerror/"error" token */ /* Construct the YYerror/"error" token */
errtoken = symbol_get ("YYerror", empty_loc); errtoken = symbol_get ("YYerror", empty_loc);
@@ -969,7 +967,6 @@ dummy_symbol_get (location loc)
assure (len < sizeof buf); assure (len < sizeof buf);
symbol *sym = symbol_get (buf, loc); symbol *sym = symbol_get (buf, loc);
sym->content->class = nterm_sym; sym->content->class = nterm_sym;
sym->content->number = nnterms++;
return sym; return sym;
} }
@@ -1002,7 +999,7 @@ symbol_cmp (void const *a, void const *b)
} }
/* Store in *SORTED an array of pointers to the symbols contained in /* Store in *SORTED an array of pointers to the symbols contained in
TABLE, sorted (alphabetically) by tag. */ TABLE, sorted by order of appearance (i.e., by location). */
static void static void
table_sort (struct hash_table *table, symbol ***sorted) table_sort (struct hash_table *table, symbol ***sorted)
+2 -2
View File
@@ -227,7 +227,7 @@ void symbol_precedence_set (symbol *sym, int prec, assoc a, location loc);
void symbol_class_set (symbol *sym, symbol_class class, location loc, void symbol_class_set (symbol *sym, symbol_class class, location loc,
bool declaring); bool declaring);
/** Set the \c code associated with \c sym. */ /** Set the token \c code of \c sym, specified by the user at \c loc. */
void symbol_code_set (symbol *sym, int code, location loc); void symbol_code_set (symbol *sym, int code, location loc);
@@ -245,7 +245,7 @@ extern symbol *eoftoken;
/** The genuine start symbol. /** The genuine start symbol.
$accept: start-symbol $end */ $accept: start-symbol $end */
extern symbol *accept; extern symbol *acceptsymbol;
/** The user start symbol. */ /** The user start symbol. */
extern symbol *startsymbol; extern symbol *startsymbol;
+16
View File
@@ -131,6 +131,22 @@ typedef size_t uintptr_t;
# include <stdbool.h> # include <stdbool.h>
/*-----------.
| Integers. |
`-----------*/
static inline int
min_int (int a, int b)
{
return a < b ? a : b;
}
static inline int
max_int (int a, int b)
{
return a >= b ? a : b;
}
/*-------------. /*-------------.
| Assertions. | | Assertions. |
+6
View File
@@ -915,6 +915,12 @@ AT_BISON_OPTION_PUSHDEFS([$1])
AT_DATA_CALC_Y([$1]) AT_DATA_CALC_Y([$1])
AT_FULL_COMPILE(AT_JAVA_IF([[Calc]], [[calc]]), AT_DEFINES_IF([[lex], [main]], [[], []]), [$2], [-Wno-deprecated]) AT_FULL_COMPILE(AT_JAVA_IF([[Calc]], [[calc]]), AT_DEFINES_IF([[lex], [main]], [[], []]), [$2], [-Wno-deprecated])
AT_YACC_IF(
[# No direct calls to malloc/free.
AT_CHECK([[$EGREP '(malloc|free) *\(' calc.[ch] | $EGREP -v 'INFRINGES ON USER NAME SPACE']],
[1])])
AT_PUSH_IF([AT_JAVA_IF( AT_PUSH_IF([AT_JAVA_IF(
[# Verify that this is a push parser. [# Verify that this is a push parser.
AT_CHECK_JAVA_GREP([[Calc.java]], AT_CHECK_JAVA_GREP([[Calc.java]],
+166 -19
View File
@@ -1,4 +1,4 @@
# Checking the Bison scanner. -*- Autotest -*- # Checking the Bison reader. -*- Autotest -*-
# Copyright (C) 2002-2015, 2018-2020 Free Software Foundation, Inc. # Copyright (C) 2002-2015, 2018-2020 Free Software Foundation, Inc.
@@ -78,10 +78,13 @@ AT_CLEANUP
## Invalid inputs. ## ## Invalid inputs. ##
## ---------------- ## ## ---------------- ##
# The truly bad guys no human would write, but easily uncovered by
# fuzzers.
AT_SETUP([Invalid inputs]) AT_SETUP([Invalid inputs])
AT_DATA([input.y], AT_DATA([input.y],
[[\000\001\002\377? [[\000\001\002\377?
"\000"
%% %%
? ?
default: 'a' } default: 'a' }
@@ -92,21 +95,50 @@ default: 'a' }
]]) ]])
AT_PERL_REQUIRE([[-pi -e 's/\\(\d{3})/chr(oct($1))/ge' input.y]]) AT_PERL_REQUIRE([[-pi -e 's/\\(\d{3})/chr(oct($1))/ge' input.y]])
AT_BISON_CHECK([input.y], [1], [], AT_BISON_CHECK([-fcaret input.y], [1], [], [stderr])
# Autotest's diffing, when there are NUL bytes, just reports "binary
# files differ". So don't leave NUL bytes.
AT_PERL_CHECK([[-p -e 's{([\0\377])}{sprintf "\\x%02x", ord($1)}ge' stderr]], [],
[[input.y:1.1-2: error: invalid characters: '\0\001\002\377?' [[input.y:1.1-2: error: invalid characters: '\0\001\002\377?'
input.y:3.1: error: invalid character: '?' 1 | \x00\xff?
input.y:4.14: error: invalid character: '}' | ^~
input.y:5.1: error: invalid character: '%' input.y:2.2: error: invalid null character
input.y:5.2: error: invalid character: '&' 2 | "\x00"
input.y:6.1-17: error: invalid directive: '%a-does-not-exist' | ^
input.y:7.1: error: invalid character: '%' input.y:4.1: error: invalid character: '?'
input.y:7.2: error: invalid character: '-' 4 | ?
input.y:8.1-9.0: error: missing '%}' at end of file | ^
input.y:5.14: error: invalid character: '}'
5 | default: 'a' }
| ^
input.y:6.1: error: invalid character: '%'
6 | %&
| ^
input.y:6.2: error: invalid character: '&'
6 | %&
| ^
input.y:7.1-17: error: invalid directive: '%a-does-not-exist'
7 | %a-does-not-exist
| ^~~~~~~~~~~~~~~~~
input.y:8.1: error: invalid character: '%'
8 | %-
| ^
input.y:8.2: error: invalid character: '-'
8 | %-
| ^
input.y:9.1-10.0: error: missing '%}' at end of file
9 | %{
| ^~
]]) ]])
AT_CLEANUP AT_CLEANUP
## ------------------------ ##
## Invalid inputs with {}. ##
## ------------------------ ##
AT_SETUP([Invalid inputs with {}]) AT_SETUP([Invalid inputs with {}])
# We used to SEGV here. See # We used to SEGV here. See
@@ -788,6 +820,33 @@ input.y:3.8-10: note: previous declaration
AT_CLEANUP AT_CLEANUP
## ---------------- ##
## EOF redeclared. ##
## ---------------- ##
AT_SETUP([EOF redeclared])
# We used to crash when redefining a token after having defined EOF.
# See https://lists.gnu.org/r/bug-bison/2020-08/msg00008.html.
AT_DATA([[input.y]],
[[%token FOO BAR FOO 0
%%
input: %empty
]])
AT_BISON_CHECK([-fcaret input.y], [0], [],
[[input.y:1.16-18: warning: symbol FOO redeclared [-Wother]
1 | %token FOO BAR FOO 0
| ^~~
input.y:1.8-10: note: previous declaration
1 | %token FOO BAR FOO 0
| ^~~
]])
AT_CLEANUP
## --------------------------- ## ## --------------------------- ##
## Symbol class redefinition. ## ## Symbol class redefinition. ##
## --------------------------- ## ## --------------------------- ##
@@ -1224,12 +1283,12 @@ AT_TEST([[%token foo "foo"
%% %%
exp: foo; exp: foo;
]], ]],
[[input.y:3.7-11: error: %type redeclaration for foo [[input.y:3.13-15: error: %type redeclaration for foo
3 | %type <baz> foo 3 | %type <baz> foo
| ^~~~~ | ^~~
input.y:2.7-11: note: previous declaration input.y:2.13-17: note: previous declaration
2 | %type <bar> "foo" 2 | %type <bar> "foo"
| ^~~~~ | ^~~~~
]]) ]])
AT_TEST([[%token foo "foo" AT_TEST([[%token foo "foo"
@@ -1336,11 +1395,6 @@ AT_CLEANUP
AT_SETUP([Torturing the Scanner]) AT_SETUP([Torturing the Scanner])
AT_BISON_OPTION_PUSHDEFS AT_BISON_OPTION_PUSHDEFS
AT_DATA([input.y], [])
AT_BISON_CHECK([input.y], [1], [],
[[input.y:1.1: error: unexpected end of file
]])
AT_DATA([input.y], AT_DATA([input.y],
[{} [{}
@@ -2447,6 +2501,99 @@ input.y:5.19: error: invalid character after \-escape: \001
AT_CLEANUP AT_CLEANUP
## ------------------------ ##
## Unexpected end of file. ##
## ------------------------ ##
AT_SETUP([[Unexpected end of file]])
AT_DATA([input.y], [])
AT_BISON_CHECK([-fcaret input.y], [1], [],
[[input.y:1.1: error: unexpected end of file
]])
AT_DATA_NO_FINAL_EOL([char.y],
[[%token FOO ']])
AT_BISON_CHECK([-fcaret char.y], [1], [],
[[char.y:1.12: error: missing "'" at end of file
1 | %token FOO '
| ^
char.y:1.12: error: empty character literal
1 | %token FOO '
| ^
]])
AT_DATA_NO_FINAL_EOL([escape-in-char.y],
[[%token FOO '\]])
AT_BISON_CHECK([-fcaret escape-in-char.y], [1], [],
[[escape-in-char.y:1.12-13: error: missing '?\'' at end of file
1 | %token FOO '\
| ^~
escape-in-char.y:1.14: error: unexpected end of file
1 | %token FOO '\
| ^
]])
AT_DATA_NO_FINAL_EOL([string.y],
[[%token FOO "]])
AT_BISON_CHECK([-fcaret string.y], [1], [],
[[string.y:1.12: error: missing '"' at end of file
1 | %token FOO "
| ^
string.y:1.13: error: unexpected end of file
1 | %token FOO "
| ^
]])
AT_DATA_NO_FINAL_EOL([escape-in-string.y],
[[%token FOO "\]])
AT_BISON_CHECK([-fcaret escape-in-string.y], [1], [],
[[escape-in-string.y:1.12-13: error: missing '?"' at end of file
1 | %token FOO "\
| ^~
escape-in-string.y:1.14: error: unexpected end of file
1 | %token FOO "\
| ^
]])
AT_DATA_NO_FINAL_EOL([tstring.y],
[[%token FOO _("]])
AT_BISON_CHECK([-fcaret tstring.y], [1], [],
[[tstring.y:1.12-14: error: missing '")' at end of file
1 | %token FOO _("
| ^~~
tstring.y:1.15: error: unexpected end of file
1 | %token FOO _("
| ^
]])
AT_DATA_NO_FINAL_EOL([escape-in-tstring.y],
[[%token FOO _("\]])
AT_BISON_CHECK([-fcaret escape-in-tstring.y], [1], [],
[[escape-in-tstring.y:1.12-15: error: missing '?")' at end of file
1 | %token FOO _("\
| ^~~~
escape-in-tstring.y:1.16: error: unexpected end of file
1 | %token FOO _("\
| ^
]])
AT_CLEANUP
## ------------------------- ## ## ------------------------- ##
## LAC: Errors for %define. ## ## LAC: Errors for %define. ##
## ------------------------- ## ## ------------------------- ##
+1
View File
@@ -390,6 +390,7 @@ AT_LOCATION_TYPE_SPAN_IF(
AT_GLR_IF([AT_KEYWORDS([glr])]) AT_GLR_IF([AT_KEYWORDS([glr])])
AT_PUSH_IF([AT_KEYWORDS([push])])
])# _AT_BISON_OPTION_PUSHDEFS ])# _AT_BISON_OPTION_PUSHDEFS
+2 -2
View File
@@ -759,7 +759,7 @@ AT_TEST([x1],
]) ])
# Check the CPP guard and Doxyen comments. # Check the CPP guard and Doxyen comments.
AT_CHECK([sed -ne 's/#line [0-9]\+ "/#line "/p;/INCLUDED/p;/\\file/{p;n;p;}' out/include/ast/loc.hh], [], AT_CHECK([[sed -ne 's/#line [0-9][0-9]* "/#line "/p;/INCLUDED/p;/\\file/{p;n;p;}' out/include/ast/loc.hh]], [],
[[ ** \file bar/include/ast/loc.hh [[ ** \file bar/include/ast/loc.hh
** Define the x1::location class. ** Define the x1::location class.
#ifndef YY_YY_BAR_INCLUDE_AST_LOC_HH_INCLUDED #ifndef YY_YY_BAR_INCLUDE_AST_LOC_HH_INCLUDED
@@ -771,7 +771,7 @@ AT_CHECK([sed -ne 's/#line [0-9]\+ "/#line "/p;/INCLUDED/p;/\\file/{p;n;p;}' out
#endif // !YY_YY_BAR_INCLUDE_AST_LOC_HH_INCLUDED #endif // !YY_YY_BAR_INCLUDE_AST_LOC_HH_INCLUDED
]]) ]])
AT_CHECK([sed -ne 's/^#line [0-9]\+ "/#line "/p;/INCLUDED/p;/\\file/{p;n;p;}' out/x1.hh], [], AT_CHECK([[sed -ne 's/^#line [0-9][0-9]* "/#line "/p;/INCLUDED/p;/\\file/{p;n;p;}' out/x1.hh]], [],
[[ ** \file bar/x1.hh [[ ** \file bar/x1.hh
** Define the x1::parser class. ** Define the x1::parser class.
#ifndef YY_YY_BAR_X1_HH_INCLUDED #ifndef YY_YY_BAR_X1_HH_INCLUDED