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
# Can help understanding why we get "dirty" tarballs.
- git status
- git diff
- dist=$(echo bison*.xz)
# 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++'
- 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"
stage: check
os: linux
@@ -127,7 +130,7 @@ jobs:
- CC=icc
- CXX=icpc
install:
- source /opt/intel/inteloneapi/compiler/latest/env/vars.sh
- source /opt/intel/oneapi/compiler/latest/env/vars.sh
addons:
apt:
sources:
+52 -1
View File
@@ -1,5 +1,55 @@
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]
** Deprecated features
@@ -537,7 +587,8 @@ GNU Bison NEWS
\005) with incorrect styling. Fixes for similar issues with unexpectedly
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]
+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
`--color` and `--style` options.
To use them, install the libtextstyle library before configuring Bison. It
is available from https://alpha.gnu.org/gnu/gettext/, for instance
https://alpha.gnu.org/pub/gnu/gettext/libtextstyle-0.20.5.tar.gz.
To use them, install the libtextstyle library, 0.20.5 or newer, before
configuring Bison. It is available from https://alpha.gnu.org/gnu/gettext/,
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:
- 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`
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
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]
Kiyoshi Kanazawa [email protected]
Lars Maier [email protected]
Lars Wendler [email protected]
László Várady [email protected]
Laurent Mascherpa [email protected]
Lie Yan [email protected]
Maarten De Braekeleer [email protected]
Magnus Fromreide [email protected]
Marc Autret [email protected]
Marc Mendiola [email protected]
@@ -185,6 +187,7 @@ Simon Sobisch [email protected]
Stefano Lattarini [email protected]
Stephen Cameron [email protected]
Steve Murphy [email protected]
Suhwan Song [email protected]
Sum Wu [email protected]
Théophile Ranquet [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
*** Improve gnulib
Don't do this (counterexample.c):
@@ -48,13 +56,6 @@ Unless we play it dumb (little structure).
- 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
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_
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
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.
** %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
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
"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.
*** complain.*
Rename these guys as "diagnostics.*" (or "diagnose.*"), since that's the
name they have in gcc, clang, etc. Likewise for the complain_* series of
name they have in GCC, clang, etc. Likewise for the complain_* series of
functions.
*** ritem
states/nstates, rules/nrules, ..., ritem/nritems
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
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
@@ -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.
* Completion
Several features are not available in all the backends.
Several features are not available in all the back-ends.
- lac: D, Java (easy)
- 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.
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.
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.
-----
# 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:
mode: outline
coding: utf-8
fill-column: 76
ispell-dictionary: "american"
End:
-----
Copyright (C) 2001-2004, 2006, 2008-2015, 2018-2020 Free Software
Foundation, Inc.
+2
View File
@@ -45,6 +45,8 @@ gnulib_modules='
relocatable-prog relocatable-script
rename
spawn-pipe stdbool stpcpy stpncpy strdup-posix strerror strverscmp
sys_ioctl
termios
timevar
unicodeio unistd unistd-safer unlink unlocked-io
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 = \
(^ *\#|(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.
sc_space_before_open_paren:
@if $(VC_LIST_EXCEPT) | grep -l '\.[ch]$$' > /dev/null; then \
@@ -156,6 +156,7 @@ exclude = \
$(call exclude, \
bindtextdomain=^lib/main.c$$ \
cast_of_argument_to_free=^src/muscle-tab.c$$ \
error_message_uppercase=etc/bench.pl.in$$ \
po_check=^tests|(^po/POTFILES.in|.md)$$ \
preprocessor_indentation=^data/|^lib/|^src/parse-gram.[ch]$$ \
program_name=^lib/main.c$$ \
+3
View File
@@ -60,6 +60,9 @@ AC_PROG_CXX
# Gnulib (early checks).
gl_EARLY
# We want ostream_printf and hyperlink support.
gl_LIBTEXTSTYLE_OPTIONAL([0.20.5])
# Gnulib uses '#pragma GCC diagnostic push' to silence some
# warnings, but older gcc doesn't support this.
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
{
*yycdebug_ << (yykind < YYNTOKENS ? "token" : "nterm")
<< ' ' << yytname[yykind] << " ("]b4_locations_if([[
<< ' ' << yysymbol_name (yykind) << " ("]b4_locations_if([[
<< *yylocationp << ": "]])[;
yy_symbol_value_print_ (yykind, yyvaluep]b4_locations_if([[, yylocationp]])[);
*yycdebug_ << ')';
+2 -2
View File
@@ -1486,7 +1486,7 @@ yypstate_new (void)
yypstate *yyps;]b4_pure_if([], [[
if (yypstate_allocated)
return YY_NULLPTR;]])[
yyps = YY_CAST (yypstate *, malloc (sizeof *yyps));
yyps = YY_CAST (yypstate *, YYMALLOC (sizeof *yyps));
if (!yyps)
return YY_NULLPTR;]b4_pure_if([], [[
yypstate_allocated = 1;]])[
@@ -1515,7 +1515,7 @@ yypstate_delete (yypstate *yyps)
#endif]b4_lac_if([[
if (yyes != yyesa)
YYSTACK_FREE (yyes);]])[
free (yyps);]b4_pure_if([], [[
YYFREE (yyps);]b4_pure_if([], [[
yypstate_allocated = 0;]])[
}
}
+105 -79
View File
@@ -57,44 +57,57 @@
\gdef\colorPurple{%
\setcolor{\rgbPurple}%
}
\gdef\colorOff{%
\setcolor{\maincolor}%
}
\gdef\rgbError{0.80 0 0}
\gdef\colorError{%
\gdef\diagError{%
\setcolor{\rgbError}%
}
\gdef\rgbNotice{0 0 0.80}
\gdef\colorNotice{%
\gdef\diagNotice{%
\setcolor{\rgbNotice}%
}
\gdef\colorOff{%
\gdef\rgbWarning{0.50 0 0.50}
\gdef\diagWarning{%
\setcolor{\rgbWarning}%
}
\gdef\diagOff{%
\setcolor{\maincolor}%
}
@end tex
@ifnottex
@macro colorGreen
@inlineraw{html, <b style="color:green">}
@inlineraw{html, <span style="color:green">}
@end macro
@macro colorYellow
@inlineraw{html, <b style="color:#ff8000">}
@inlineraw{html, <span style="color:#ff8000">}
@end macro
@macro colorRed
@inlineraw{html, <b style="color:red">}
@inlineraw{html, <span style="color:red">}
@end macro
@macro colorBlue
@inlineraw{html, <b style="color:blue">}
@inlineraw{html, <span style="color:blue">}
@end macro
@macro colorPurple
@inlineraw{html, <b style="color:darkviolet">}
@end macro
@macro colorError
@inlineraw{html, <b style="color:red">}
@end macro
@macro colorNotice
@inlineraw{html, <b style="color:darkcyan">}
@inlineraw{html, <span style="color:darkviolet">}
@end macro
@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>}
@end macro
@end ifnottex
@@ -120,15 +133,15 @@
@end macro
@macro dwarning{text}
@purple{\text\}
@diagWarning{}\text\@diagOff{}
@end macro
@macro derror{text}
@colorError{}\text\@colorOff{}
@diagError{}\text\@diagOff{}
@end macro
@macro dnotice{text}
@colorNotice{}\text\@colorOff{}
@diagNotice{}\text\@diagOff{}
@end macro
@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 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 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
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.
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
@@ -8693,7 +8755,8 @@ maybeword:
@end example
@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{maybeword} and then into a @code{sequence} via the second rule.
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
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{"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 LALR
However, for historical reasons, Bison cannot by default handle all
LR(1) grammars.
This is because Bison does not handle all LR(1) grammars @emph{by default},
for historical reasons.
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
@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
@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
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
@pcite{Isradisaikul 2015}.
As a first example, see the example grammar of @ref{Shift/Reduce}, which
features on shift/reduce conflict:
As a first example, see the grammar of @ref{Shift/Reduce}, which features
one shift/reduce conflict:
@c see doc/if-then-else.y
@example
@@ -9901,49 +9969,14 @@ Let's rerun @command{bison} with the option
@option{-Wcex}/@option{-Wcounterexamples}@inlinefmt{info, (the following
output is actually in color)}:
@ifnottex
@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{↳ "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
@danglingElseCex
@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
demonstrates that the grammar is ambiguous.
This shows two different derivations for one single expression, which proves
that the grammar is ambiguous.
@sp 1
@@ -9966,13 +9999,13 @@ maybeword:
Bison generates the following counterexamples:
@ifnottex
@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
@ifnottex
@group
sequence.y: @dwarning{warning}: shift/reduce conflict on token "word" [@dwarning{-Wcounterexamples}]
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"); @}}
| @dwarning{^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
@end group
@end example
@end ifnottex
@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
sequence.y: @dwarning{warning}: shift/reduce conflict on token "word" [@dwarning{-Wcounterexamples}]
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"); @}}
| @dwarning{^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
@end group
@end example
@end iftex
@end example
Each of these three conflicts, again, prove that the grammar is ambiguous.
For instance, the second conflict (the reduce/reduce one) shows that the
@@ -10096,10 +10122,10 @@ expr: %empty | expr ID ','
@command{bison} reports:
@ifnottex
@example
ids.y: @dwarning{warning}: 1 shift/reduce conflict [@dwarning{-Wconflicts-sr}]
ids.y: @dwarning{warning}: shift/reduce conflict on token ID [@dwarning{-Wcounterexamples}]
@ifnottex
@group
First example: @purple{expr} @red{•} @purple{ID ','} @green{ID} @yellow{$end}
Shift derivation
@@ -10120,12 +10146,8 @@ ids.y:4.4-7: @dwarning{warning}: rule useless in parser due to conflicts [@dwarn
4 | a: expr
| ^~~~
@end group
@end example
@end ifnottex
@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
First example: @purple{expr} @red{•} @purple{ID ','} @green{ID} @yellow{$end}
Shift derivation
@@ -10146,8 +10168,8 @@ ids.y:4.4-7: @dwarning{warning}: rule useless in parser due to conflicts [@dwarn
4 | a: expr
| ^~~~
@end group
@end example
@end iftex
@end example
This conflict is caused by the parser not having enough information to know
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
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
parses; its existence proves that the grammar is ambiguous. When a unifying
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
# 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
$(AM_V_GEN) $(PERL) -pi.bak -0777 \
-e 's{(^ --.*\n(?: {10}.*\n)*)}' \
+41 -29
View File
@@ -185,13 +185,13 @@ my $verbose = 1;
=over 4
=item C<verbose($level, $message)>
=item C<verbose ($level, $message)>
Report the C<$message> is C<$level> E<lt>= C<$verbose>.
=cut
sub verbose($$)
sub verbose ($$)
{
my ($level, $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>.
=cut
sub directives($@)
sub directives ($@)
{
my ($bench, @directive) = @_;
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)>
Create a large triangular grammar which looks like :
@@ -389,18 +410,14 @@ sub generate_grammar_calc ($$@)
%define api.value.type union
$directives
%{
%code provides {
static int power (int base, int exponent);
/* yyerror receives the location if:
- %location & %pure & %glr
- %location & %pure & %yacc & %parse-param. */
static void yyerror (const char *s);
#if YYPURE
static int yylex (YYSTYPE* yylvalp);
#else
static int yylex (void);
#endif
%}
static int yylex (@{[is_pure (@directive) ? "YYSTYPE *yylvalp" : "void"]});
}
/* Bison Declarations */
%token
@@ -467,12 +484,7 @@ yyerror (const char *s)
}
static int
#if YYPURE
# define yylval (*yylvalp)
yylex (YYSTYPE* yylvalp)
#else
yylex (void)
#endif
yylex (@{[is_pure (@directive) ? "YYSTYPE *yylvalp" : "void"]})
{
int c;
@@ -498,7 +510,7 @@ yylex (void)
case '5': case '6': case '7': case '8': case '9':
{
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);
input += nchars - 1;
return NUM;
@@ -506,7 +518,7 @@ yylex (void)
default:
yyerror ("error: invalid character");
return yylex ();
return yylex (@{[is_pure (@directive) ? "yylvalp" : ""]});
}
}
EOF
@@ -592,10 +604,10 @@ $directives
// Prototype of the yylex function providing subsequent tokens.
static
#if USE_TOKEN_CTOR
yy::parser::symbol_type yylex();
yy::parser::symbol_type yylex ();
#else
yy::parser::token_type yylex(yy::parser::semantic_type* yylvalp,
yy::parser::location_type* yyllocp);
yy::parser::token_type yylex (yy::parser::semantic_type *yylvalp,
yy::parser::location_type *yyllocp);
#endif
// Conversion to string.
@@ -618,8 +630,8 @@ EOF
print $out <<'EOF';
%token <std::string> TEXT
%token <int> NUMBER
%printer { std::cerr << "Number: " << $$; } <int>
%printer { std::cerr << "Text: " << $$; } <std::string>
%printer { yyo << "Number: " << $$; } <int>
%printer { yyo << "Text: " << $$; } <std::string>
%type <std::string> text result
%%
@@ -641,8 +653,8 @@ EOF
%union {int ival; std::string* sval;}
%token <sval> TEXT
%token <ival> NUMBER
%printer { std::cerr << "Number: " << $$; } <ival>
%printer { std::cerr << "Text: " << *$$; } <sval>
%printer { yyo << "Number: " << $$; } <ival>
%printer { yyo << "Text: " << *$$; } <sval>
%type <sval> text result
%%
@@ -664,10 +676,10 @@ EOF
static
#if USE_TOKEN_CTOR
yy::parser::symbol_type yylex()
yy::parser::symbol_type yylex ()
#else
yy::parser::token_type yylex(yy::parser::semantic_type* yylvalp,
yy::parser::location_type* yyllocp)
yy::parser::token_type yylex (yy::parser::semantic_type *yylvalp,
yy::parser::location_type *yyllocp)
#endif
{
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: Entering state 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: $2 = token error (1.2-3: )
err: $3 = token ) (1.4: )
err: -> $$ = nterm exp (1.1-4: 666)
err: Entering state 7
err: Stack now 0 7
err: Entering state 8
err: Stack now 0 8
err: Return for a new token:
err: Reading a token
err: Now at end of input.
err: LAC: initial context established for end of file
err: LAC: checking lookahead end of file: R2 G8 S19
err: Reducing stack by rule 2 (line 126):
err: LAC: checking lookahead end of file: R2 G7 S14
err: Reducing stack by rule XX (line XXX):
err: $1 = nterm exp (1.1-4: 666)
err: -> $$ = nterm input (1.1-4: )
err: Entering state 8
err: Stack now 0 8
err: Entering state 7
err: Stack now 0 7
err: Now at end of input.
err: Shifting token end of file (1.5: )
err: LAC: initial context discarded due to shift
err: Entering state 19
err: Stack now 0 8 19
err: Stack now 0 8 19
err: Entering state 14
err: Stack now 0 7 14
err: Stack now 0 7 14
err: Cleanup: popping token end of file (1.5: )
err: Cleanup: popping nterm input (1.1-4: )' -p
+7
View File
@@ -31,6 +31,13 @@ endif FLEX_WORKS
%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
dist_lexcalc_DATA = %D%/parse.y %D%/scan.l %D%/Makefile %D%/README.md
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)
$(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
$(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)
$(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
$(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)
$(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
$(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
/locale.h
/locale.in.h
/localtime-buffer.c
/localtime-buffer.h
/lstat.c
/malloc.c
/malloca.c
@@ -338,8 +336,11 @@
/sys_types.in.h
/sys_wait.in.h
/sysexits.in.h
/termios.h
/termios.in.h
/textstyle.h
/textstyle.in.h
/thread-optim.h
/time.h
/time.in.h
/timespec.c
+4 -1
View File
@@ -97,7 +97,6 @@
/locale-ja.m4
/locale-zh.m4
/locale_h.m4
/localtime-buffer.m4
/lock.m4
/longlong.m4
/lstat.m4
@@ -117,6 +116,7 @@
/msvc-inval.m4
/msvc-nothrow.m4
/multiarch.m4
/musl.m4
/nls.m4
/nocrash.m4
/non-recursive-gnulib-prefix-hack.m4
@@ -128,6 +128,7 @@
/open.m4
/pathmax.m4
/perror.m4
/pid_t.m4
/pipe2.m4
/po.m4
/posix_spawn.m4
@@ -184,6 +185,7 @@
/strndup.m4
/strnlen.m4
/strverscmp.m4
/sys_ioctl_h.m4
/sys_resource_h.m4
/sys_socket_h.m4
/sys_stat_h.m4
@@ -191,6 +193,7 @@
/sys_times_h.m4
/sys_types_h.m4
/sys_wait_h.m4
/termios_h.m4
/threadlib.m4
/time_h.m4
/timespec.m4
+12 -17
View File
@@ -113,13 +113,8 @@ free_counterexample (counterexample *cex)
free (cex);
}
static int max (int a, int b)
{
return a < b ? b : a;
}
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 char *example1_label
@@ -131,8 +126,8 @@ print_counterexample (const counterexample *cex, FILE *out, const char *prefix)
const char *deriv2_label
= cex->shift_reduce ? _("Reduce derivation") : _("Second reduce derivation");
const int width =
max (max (mbswidth (example1_label, 0), mbswidth (example2_label, 0)),
max (mbswidth (deriv1_label, 0), mbswidth (deriv2_label, 0)));
max_int (max_int (mbswidth (example1_label, 0), mbswidth (example2_label, 0)),
max_int (mbswidth (deriv1_label, 0), mbswidth (deriv2_label, 0)));
if (flat)
fprintf (out, " %s%s%*s ", prefix,
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);
state_item_list_next (&it, &sip);
)
print_state_item (sip, stderr, "");
state_item_print (sip, stderr, "");
}
return result;
}
@@ -717,10 +712,10 @@ ssb_equals (const search_state_bundle *s1, const search_state_bundle *s2)
typedef gl_list_t ssb_list;
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)
+ parse_state_hasher (ss->states[1], maximum)) % maximum;
return (parse_state_hasher (ss->states[0], max)
+ parse_state_hasher (ss->states[1], max)) % max;
}
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);
gl_list_free (shortest_path);
print_counterexample (cex, out, prefix);
counterexample_print (cex, out, prefix);
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.
if (out != stderr || trace_flag & trace_cex)
{
print_state_item (&state_items[itm1], out, prefix);
print_state_item (&state_items[itm2], out, prefix);
state_item_print (&state_items[itm1], out, prefix);
state_item_print (&state_items[itm2], 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.
if (out != stderr || trace_flag & trace_cex)
{
print_state_item (&state_items[itm1], out, prefix);
print_state_item (&state_items[itm2], out, prefix);
state_item_print (&state_items[itm1], out, prefix);
state_item_print (&state_items[itm2], out, prefix);
}
counterexample_report (itm1, itm2, bitset_first (conflict_syms),
false, out, prefix);
+8 -14
View File
@@ -76,12 +76,12 @@ void derivation_list_free (derivation_list dl)
derivation *
derivation_new (symbol_number sym, derivation_list children)
{
derivation *deriv = xmalloc (sizeof (derivation));
deriv->sym = sym;
deriv->children = children;
deriv->reference_count = 0;
deriv->color = -1;
return deriv;
derivation *res = xmalloc (sizeof *res);
res->sym = sym;
res->children = children;
res->reference_count = 0;
res->color = -1;
return res;
}
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.
static int
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);
derivation_list_next (&it, &child);
)
res = max (res, derivation_depth (child));
res = max_int (res, derivation_depth (child));
return res + 1;
}
else
@@ -237,7 +231,7 @@ derivation_width (const derivation *deriv)
// No separator at the beginning.
children_width -= derivation_separator_width;
}
return max (self_width, children_width);
return max_int (self_width, children_width);
}
else if (deriv == &d_dot)
{
+9 -1
View File
@@ -112,7 +112,15 @@ static struct obstack obstack_for_string;
# define STRING_1GROW(Char) \
obstack_1grow (&obstack_for_string, Char)
# define STRING_FREE() \
# ifdef NDEBUG
# define STRING_FREE() \
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
+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. */
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];
*predecessor;
++predecessor)
-1
View File
@@ -143,7 +143,6 @@ src_bison_LDADD = \
$(LIB_SETLOCALE_NULL) \
$(LIBICONV) \
$(LIBINTL) \
$(LIBREADLINE) \
$(LIBTEXTSTYLE)
+3 -13
View File
@@ -40,18 +40,6 @@
location const empty_loc = EMPTY_LOCATION_INIT;
static int
min_int (int a, int b)
{
return a < b ? a : b;
}
static int
max_int (int a, int b)
{
return a >= b ? a : b;
}
/* The terminal width. Not less than 40. */
static int
columns (void)
@@ -167,7 +155,9 @@ int
location_print (location loc, FILE *out)
{
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 += 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);
const void *sip;
while (gl_list_iterator_next (&it, &sip, NULL))
print_state_item ((state_item *) sip, stdout, "");
state_item_print ((state_item *) sip, stdout, "");
}
return res;
}
+4 -4
View File
@@ -249,7 +249,7 @@ prepare_symbol_names (char const *muscle_name)
if (i)
obstack_1grow (&format_obstack, ' ');
if (translatable)
obstack_sgrow (&format_obstack, "]b4_symbol_translate([");
obstack_sgrow (&format_obstack, "]b4_symbol_translate""([");
obstack_escape (&format_obstack, cp);
if (translatable)
obstack_sgrow (&format_obstack, "])[");
@@ -554,7 +554,7 @@ prepare_symbol_definitions (void)
/* Map "orig NUM" to new numbers. See data/README. */
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);
MUSCLE_INSERT_INT (key, nterm_map ? nterm_map[i - ntokens] : i);
}
@@ -565,12 +565,12 @@ prepare_symbol_definitions (void)
const char *key;
#define SET_KEY(Entry) \
obstack_printf (&format_obstack, "symbol(%d, %s)", \
obstack_printf (&format_obstack, "symbol""(%d, %s)", \
i, Entry); \
key = obstack_finish0 (&format_obstack);
#define SET_KEY2(Entry, Suffix) \
obstack_printf (&format_obstack, "symbol(%d, %s_%s)", \
obstack_printf (&format_obstack, "symbol""(%d, %s_%s)", \
i, Entry, Suffix); \
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
@@ -49,7 +49,7 @@
#define YYBISON 1
/* Bison version. */
#define YYBISON_VERSION "3.6.90"
#define YYBISON_VERSION "3.7.14-eb26-dirty"
/* Skeleton name. */
#define YYSKELETON_NAME "yacc.c"
@@ -149,7 +149,7 @@ enum yysymbol_kind_t
YYSYMBOL_BRACED_CODE = 41, /* "{...}" */
YYSYMBOL_BRACED_PREDICATE = 42, /* "%?{...}" */
YYSYMBOL_BRACKETED_ID = 43, /* "[identifier]" */
YYSYMBOL_CHAR = 44, /* "character literal" */
YYSYMBOL_CHAR_LITERAL = 44, /* "character literal" */
YYSYMBOL_COLON = 45, /* ":" */
YYSYMBOL_EPILOGUE = 46, /* "epilogue" */
YYSYMBOL_EQUAL = 47, /* "=" */
@@ -162,7 +162,7 @@ enum yysymbol_kind_t
YYSYMBOL_TAG = 54, /* "<tag>" */
YYSYMBOL_TAG_ANY = 55, /* "<*>" */
YYSYMBOL_TAG_NONE = 56, /* "<>" */
YYSYMBOL_INT = 57, /* "integer literal" */
YYSYMBOL_INT_LITERAL = 57, /* "integer literal" */
YYSYMBOL_PERCENT_PARAM = 58, /* "%param" */
YYSYMBOL_PERCENT_UNION = 59, /* "%union" */
YYSYMBOL_PERCENT_EMPTY = 60, /* "%empty" */
@@ -1115,8 +1115,8 @@ tron (yyo);
{ fprintf (yyo, "[%s]", ((*yyvaluep).BRACKETED_ID)); }
break;
case YYSYMBOL_CHAR: /* "character literal" */
{ fputs (char_name (((*yyvaluep).CHAR)), yyo); }
case YYSYMBOL_CHAR_LITERAL: /* "character literal" */
{ fputs (char_name (((*yyvaluep).CHAR_LITERAL)), yyo); }
break;
case YYSYMBOL_EPILOGUE: /* "epilogue" */
@@ -1139,8 +1139,8 @@ tron (yyo);
{ fprintf (yyo, "<%s>", ((*yyvaluep).TAG)); }
break;
case YYSYMBOL_INT: /* "integer literal" */
{ fprintf (yyo, "%d", ((*yyvaluep).INT)); }
case YYSYMBOL_INT_LITERAL: /* "integer literal" */
{ fprintf (yyo, "%d", ((*yyvaluep).INT_LITERAL)); }
break;
case YYSYMBOL_PERCENT_PARAM: /* "%param" */
@@ -2087,11 +2087,11 @@ yyreduce:
break;
case 12: /* prologue_declaration: "%expect" "integer literal" */
{ expected_sr_conflicts = (yyvsp[0].INT); }
{ expected_sr_conflicts = (yyvsp[0].INT_LITERAL); }
break;
case 13: /* prologue_declaration: "%expect-rr" "integer literal" */
{ expected_rr_conflicts = (yyvsp[0].INT); }
{ expected_rr_conflicts = (yyvsp[0].INT_LITERAL); }
break;
case 14: /* prologue_declaration: "%file-prefix" "string" */
@@ -2339,13 +2339,13 @@ yyreduce:
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;
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;
@@ -2396,13 +2396,13 @@ yyreduce:
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;
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;
@@ -2431,13 +2431,13 @@ yyreduce:
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;
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;
@@ -2506,7 +2506,7 @@ yyreduce:
break;
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;
case 106: /* rhs: rhs "%merge" "<tag>" */
@@ -2514,11 +2514,11 @@ yyreduce:
break;
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;
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;
case 109: /* named_ref.opt: %empty */
@@ -2566,9 +2566,9 @@ yyreduce:
location loc = muscle_percent_define_get_loc (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_code_set ((yyval.id), (yyvsp[0].CHAR), (yylsp[0]));
symbol_code_set ((yyval.id), (yyvsp[0].CHAR_LITERAL), (yylsp[0]));
}
break;
@@ -3147,8 +3147,7 @@ char_name (char c)
}
}
static
void
static void
current_lhs (symbol *sym, location loc, named_ref *ref)
{
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
@@ -123,7 +123,7 @@ extern int gram_debug;
BRACED_CODE = 41, /* "{...}" */
BRACED_PREDICATE = 42, /* "%?{...}" */
BRACKETED_ID = 43, /* "[identifier]" */
CHAR = 44, /* "character literal" */
CHAR_LITERAL = 44, /* "character literal" */
COLON = 45, /* ":" */
EPILOGUE = 46, /* "epilogue" */
EQUAL = 47, /* "=" */
@@ -136,7 +136,7 @@ extern int gram_debug;
TAG = 54, /* "<tag>" */
TAG_ANY = 55, /* "<*>" */
TAG_NONE = 56, /* "<>" */
INT = 57, /* "integer literal" */
INT_LITERAL = 57, /* "integer literal" */
PERCENT_PARAM = 58, /* "%param" */
PERCENT_UNION = 59, /* "%union" */
PERCENT_EMPTY = 60 /* "%empty" */
@@ -156,7 +156,7 @@ union GRAM_STYPE
char* EPILOGUE; /* "epilogue" */
char* PROLOGUE; /* "%{...%}" */
code_props_type code_props_type; /* code_props_type */
int INT; /* "integer literal" */
int INT_LITERAL; /* "integer literal" */
int yykind_82; /* int.opt */
named_ref* yykind_95; /* named_ref.opt */
param_type PERCENT_PARAM; /* "%param" */
@@ -188,7 +188,7 @@ union GRAM_STYPE
uniqstr yykind_74; /* tag.opt */
uniqstr tag; /* tag */
uniqstr variable; /* variable */
unsigned char CHAR; /* "character literal" */
unsigned char CHAR_LITERAL; /* "character literal" */
value_type value; /* value */
+17 -18
View File
@@ -214,7 +214,7 @@
BRACED_CODE "{...}"
BRACED_PREDICATE "%?{...}"
BRACKETED_ID _("[identifier]")
CHAR _("character literal")
CHAR_LITERAL _("character literal")
COLON ":"
EPILOGUE _("epilogue")
EQUAL "="
@@ -232,7 +232,7 @@
%code pre-printer {tron (yyo);}
%code post-printer {troff (yyo);}
%type <unsigned char> CHAR
%type <unsigned char> CHAR_LITERAL
%printer { fputs (char_name ($$), yyo); } <unsigned char>
%type <char*> "{...}" "%?{...}" "%{...%}" EPILOGUE STRING TSTRING
@@ -249,7 +249,7 @@
%printer { fprintf (yyo, "%%%s", $$); } PERCENT_FLAG
%printer { fprintf (yyo, "<%s>", $$); } TAG tag
%token <int> INT _("integer literal")
%token <int> INT_LITERAL _("integer literal")
%printer { fprintf (yyo, "%d", $$); } <int>
%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" STRING { handle_defines ($2); }
| "%error-verbose" { handle_error_verbose (&@$, $1); }
| "%expect" INT { expected_sr_conflicts = $2; }
| "%expect-rr" INT { expected_rr_conflicts = $2; }
| "%expect" INT_LITERAL { expected_sr_conflicts = $2; }
| "%expect-rr" INT_LITERAL { expected_rr_conflicts = $2; }
| "%file-prefix" STRING { handle_file_prefix (&@$, &@1, $1, $2); }
| "%glr-parser"
{
@@ -532,11 +532,11 @@ token_decls:
}
| 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]
{
$$ = 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;
int.opt:
%empty { $$ = -1; }
| INT
| INT_LITERAL
;
%type <symbol*> alias;
@@ -592,11 +592,11 @@ token_decls_for_prec:
}
| 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]
{
$$ = 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]
{
$$ = symbol_list_type_set ($syms, $TAG, @TAG);
$$ = symbol_list_type_set ($syms, $TAG);
}
| 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); }
| rhs "%prec" symbol
{ grammar_current_rule_prec_set ($3, @3); }
| rhs "%dprec" INT
| rhs "%dprec" INT_LITERAL
{ grammar_current_rule_dprec_set ($3, @3); }
| rhs "%merge" TAG
{ grammar_current_rule_merge_set ($3, @3); }
| rhs "%expect" INT
| rhs "%expect" INT_LITERAL
{ grammar_current_rule_expect_sr ($3, @3); }
| rhs "%expect-rr" INT
| rhs "%expect-rr" INT_LITERAL
{ grammar_current_rule_expect_rr ($3, @3); }
;
@@ -765,7 +765,7 @@ value:
id:
ID
{ $$ = symbol_from_uniqstr ($1, @1); }
| CHAR
| CHAR_LITERAL
{
const char *var = "api.token.raw";
if (current_class == nterm_sym)
@@ -1158,8 +1158,7 @@ char_name (char c)
}
}
static
void
static void
current_lhs (symbol *sym, location loc, named_ref *ref)
{
current_lhs_symbol = sym;
+15 -19
View File
@@ -28,19 +28,19 @@
#include "lssi.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
{
// elements newly added in this chunk
// Elements newly added in this chunk.
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 *tail_elt;
size_t total_size;
} state_items;
// list of derivations of the symbols
// List of derivations of the symbols.
struct deriv_chunk
{
derivation_list contents;
@@ -50,18 +50,15 @@ typedef struct parse_state
} derivs;
struct parse_state *parent;
int reference_count;
// incremented during productions,
// decremented during reductions
// Incremented during productions, decremented during reductions.
int depth;
// whether the contents of the chunks should be
// prepended or appended to the list the chunks
// represent
// Whether the contents of the chunks should be prepended or
// appended to the list the chunks represent.
bool prepend;
// causes chunk contents to be freed when the
// reference count is one. Used when only the chunk metadata
// will be needed.
// Causes chunk contents to be freed when the reference count is
// one. Used when only the chunk metadata will be needed.
bool free_contents_early;
} parse_state;
};
static void
@@ -438,9 +435,8 @@ simulate_transition (parse_state *ps)
// symbols into account.
parse_state_list result = parse_state_list_new ();
state_item_number si_next = si->trans;
// check for disabled transition, shouldn't happen
// as any state_items that lead to these should be
// disabled.
// Check for disabled transition, shouldn't happen as any
// state_items that lead to these should be disabled.
if (si_next < 0)
return result;
parse_state *next_ps = copy_parse_state (false, ps);
@@ -594,8 +590,8 @@ print_parse_state (parse_state *ps)
FILE *out = stderr;
fprintf (out, "(size %zu depth %d rc %d)\n",
ps->state_items.total_size, ps->depth, ps->reference_count);
print_state_item (ps->state_items.head_elt, out, "");
print_state_item (ps->state_items.tail_elt, out, "");
state_item_print (ps->state_items.head_elt, out, "");
state_item_print (ps->state_items.tail_elt, out, "");
if (ps->derivs.total_size > 0)
derivation_print (ps->derivs.head_elt, out, "");
putc ('\n', out);
+8 -5
View File
@@ -406,8 +406,8 @@ grammar_midrule_action (void)
action. Create the MIDRULE. */
location dummy_loc = current_rule->action_props.location;
symbol *dummy = dummy_symbol_get (dummy_loc);
symbol_type_set(dummy,
current_rule->action_props.type, current_rule->action_props.location);
symbol_type_set (dummy,
current_rule->action_props.type, current_rule->action_props.location);
symbol_list *midrule = symbol_list_sym_new (dummy, dummy_loc);
/* Remember named_ref of previous action. */
@@ -804,7 +804,7 @@ check_and_convert_grammar (void)
$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->next = symbol_list_sym_new (startsymbol, empty_loc);
p->next->next = symbol_list_sym_new (eoftoken, empty_loc);
@@ -815,8 +815,11 @@ check_and_convert_grammar (void)
grammar = p;
}
aver (nsyms <= SYMBOL_NUMBER_MAXIMUM);
aver (nsyms == ntokens + nnterms);
if (SYMBOL_NUMBER_MAXIMUM - nnterms < ntokens)
complain (NULL, fatal, "too many symbols in input grammar (limit is %d)",
SYMBOL_NUMBER_MAXIMUM);
nsyms = ntokens + nnterms;
/* Assign the symbols their symbol numbers. */
symbols_pack ();
+4 -4
View File
@@ -160,9 +160,9 @@ inaccessable_symbols (void)
bitset Pp = bitset_create (nrules, BITSET_FIXED);
/* 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)
{
@@ -301,7 +301,7 @@ nonterminals_reduce (void)
for (item_number *rhsp = rules[r].rhs; 0 <= *rhsp; ++rhsp)
if (ISVAR (*rhsp))
*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;
@@ -381,7 +381,7 @@ reduce_grammar (void)
{
reduce_print ();
if (!bitset_test (N, accept->content->number - ntokens))
if (!bitset_test (N, acceptsymbol->content->number - ntokens))
complain (&startsymbol_loc, fatal,
_("start symbol %s does not derive any sentence"),
startsymbol->tag);
+21 -12
View File
@@ -322,8 +322,8 @@ eqopt ({sp}=)?
BEGIN SC_AFTER_IDENTIFIER;
}
{int} RETURN_VALUE (INT, scan_integer (yytext, 10, *loc));
{xint} RETURN_VALUE (INT, scan_integer (yytext, 16, *loc));
{int} RETURN_VALUE (INT_LITERAL, scan_integer (yytext, 10, *loc));
{xint} RETURN_VALUE (INT_LITERAL, scan_integer (yytext, 16, *loc));
/* Identifiers may not start with a digit. Yet, don't silently
accept "1FOO" as "1 FOO". */
@@ -403,6 +403,7 @@ eqopt ({sp}=)?
{
\0 {
complain (loc, complaint, _("invalid null character"));
STRING_FINISH ();
STRING_FREE ();
return GRAM_error;
}
@@ -566,6 +567,8 @@ eqopt ({sp}=)?
_("POSIX Yacc does not support string literals"));
RETURN_VALUE (STRING, last_string);
}
<<EOF>> unexpected_eof (token_start, "\"");
"\n" unexpected_newline (token_start, "\"");
}
<SC_ESCAPED_TSTRING>
@@ -579,13 +582,10 @@ eqopt ({sp}=)?
_("POSIX Yacc does not support string literals"));
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 ();
BEGIN INITIAL;
loc->start = token_start;
val->CHAR = last_string[0];
if (last_string[0] == '\0')
{
@@ -615,8 +614,9 @@ eqopt ({sp}=)?
}
else
{
val->CHAR_LITERAL = last_string[0];
STRING_FREE ();
return CHAR;
return CHAR_LITERAL;
}
}
{eol} unexpected_newline (token_start, "'");
@@ -691,6 +691,15 @@ eqopt ({sp}=)?
p);
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
handle_syncline (char *args, location loc)
+3 -3
View File
@@ -475,7 +475,7 @@ prune_disabled_paths (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);
item_print (si->item, NULL, out);
@@ -506,7 +506,7 @@ state_items_report (void)
if (si->trans >= 0)
{
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 };
@@ -521,7 +521,7 @@ state_items_report (void)
BITSET_FOR_EACH (biter, b, sin, 0)
{
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 print_state_item (const state_item *si, FILE *out, const char *prefix);
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);
// 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_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)
symbol_type_set (l->content.sym, type_name, loc);
symbol_type_set (l->content.sym, type_name, l->sym_loc);
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.
** \returns \c syms */
symbol_list *symbol_list_type_set (symbol_list *syms,
uniqstr type_name, location loc);
symbol_list *symbol_list_type_set (symbol_list *syms, uniqstr type_name);
/** Print this list.
+33 -36
View File
@@ -59,7 +59,7 @@ static semantic_type **semantic_types_sorted = NULL;
symbol *errtoken = NULL;
symbol *undeftoken = NULL;
symbol *eoftoken = NULL;
symbol *accept = NULL;
symbol *acceptsymbol = NULL;
symbol *startsymbol = NULL;
location startsymbol_loc;
@@ -137,11 +137,6 @@ symbol_new (uniqstr tag, location loc)
res->alias = NULL;
res->content = sym_content_new (res);
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;
}
@@ -182,11 +177,11 @@ symbol_free (void *ptr)
*/
static void
symbols_sort (symbol **first, symbol **second)
symbols_sort (const symbol **first, const symbol **second)
{
if (0 < location_cmp ((*first)->location, (*second)->location))
{
symbol* tmp = *first;
const symbol* tmp = *first;
*first = *second;
*second = tmp;
}
@@ -243,7 +238,11 @@ semantic_type_new (uniqstr tag, const location *loc)
| 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) \
fprintf (f, " %s { %s }", #Attr, s->content->Attr)
@@ -264,7 +263,11 @@ symbol_print (symbol const *s, FILE *f)
: c == nterm_sym ? "nterm"
: NULL, /* abort. */
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 (printer);
}
@@ -371,7 +374,7 @@ symbol_from_uniqstr_fuzzy (const uniqstr key)
}
static void
complain_symbol_undeclared (symbol *sym)
complain_symbol_undeclared (const symbol *sym)
{
assert (sym->content->status != declared);
const symbol *best = symbol_from_uniqstr_fuzzy (sym->tag);
@@ -398,7 +401,10 @@ void
symbol_location_as_lhs_set (symbol *sym, location loc)
{
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)
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;
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
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)
{
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;
}
}
@@ -621,9 +619,11 @@ symbol_check_defined (symbol *sym)
{
complain_symbol_undeclared (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
&& sym->tag[0] == '"'
&& !sym->is_alias)
@@ -742,7 +742,7 @@ symbol_pack (symbol *sym)
}
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);
complain (&second->location, complaint,
@@ -758,13 +758,11 @@ complain_code_redeclared (int num, symbol *first, symbol *second)
`-------------------------------------------------*/
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]
!= undeftoken->content->number)
complain_code_redeclared
@@ -849,10 +847,10 @@ symbols_new (void)
hash_symbol_comparator,
symbol_free);
/* Construct the accept symbol. */
accept = symbol_get ("$accept", empty_loc);
accept->content->class = nterm_sym;
accept->content->number = nnterms++;
/* Construct the acceptsymbol symbol. */
acceptsymbol = symbol_get ("$accept", empty_loc);
acceptsymbol->content->class = nterm_sym;
acceptsymbol->content->number = nnterms++;
/* Construct the YYerror/"error" token */
errtoken = symbol_get ("YYerror", empty_loc);
@@ -969,7 +967,6 @@ dummy_symbol_get (location loc)
assure (len < sizeof buf);
symbol *sym = symbol_get (buf, loc);
sym->content->class = nterm_sym;
sym->content->number = nnterms++;
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
TABLE, sorted (alphabetically) by tag. */
TABLE, sorted by order of appearance (i.e., by location). */
static void
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,
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);
@@ -245,7 +245,7 @@ extern symbol *eoftoken;
/** The genuine start symbol.
$accept: start-symbol $end */
extern symbol *accept;
extern symbol *acceptsymbol;
/** The user start symbol. */
extern symbol *startsymbol;
+16
View File
@@ -131,6 +131,22 @@ typedef size_t uintptr_t;
# 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. |
+6
View File
@@ -915,6 +915,12 @@ AT_BISON_OPTION_PUSHDEFS([$1])
AT_DATA_CALC_Y([$1])
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(
[# Verify that this is a push parser.
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.
@@ -78,10 +78,13 @@ AT_CLEANUP
## Invalid inputs. ##
## ---------------- ##
# The truly bad guys no human would write, but easily uncovered by
# fuzzers.
AT_SETUP([Invalid inputs])
AT_DATA([input.y],
[[\000\001\002\377?
"\000"
%%
?
default: 'a' }
@@ -92,21 +95,50 @@ default: 'a' }
]])
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:3.1: error: invalid character: '?'
input.y:4.14: error: invalid character: '}'
input.y:5.1: error: invalid character: '%'
input.y:5.2: error: invalid character: '&'
input.y:6.1-17: error: invalid directive: '%a-does-not-exist'
input.y:7.1: error: invalid character: '%'
input.y:7.2: error: invalid character: '-'
input.y:8.1-9.0: error: missing '%}' at end of file
1 | \x00\xff?
| ^~
input.y:2.2: error: invalid null character
2 | "\x00"
| ^
input.y:4.1: error: invalid character: '?'
4 | ?
| ^
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
## ------------------------ ##
## Invalid inputs with {}. ##
## ------------------------ ##
AT_SETUP([Invalid inputs with {}])
# We used to SEGV here. See
@@ -788,6 +820,33 @@ input.y:3.8-10: note: previous declaration
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. ##
## --------------------------- ##
@@ -1224,12 +1283,12 @@ AT_TEST([[%token foo "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
| ^~~~~
input.y:2.7-11: note: previous declaration
| ^~~
input.y:2.13-17: note: previous declaration
2 | %type <bar> "foo"
| ^~~~~
| ^~~~~
]])
AT_TEST([[%token foo "foo"
@@ -1336,11 +1395,6 @@ AT_CLEANUP
AT_SETUP([Torturing the Scanner])
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],
[{}
@@ -2447,6 +2501,99 @@ input.y:5.19: error: invalid character after \-escape: \001
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. ##
## ------------------------- ##
+1
View File
@@ -390,6 +390,7 @@ AT_LOCATION_TYPE_SPAN_IF(
AT_GLR_IF([AT_KEYWORDS([glr])])
AT_PUSH_IF([AT_KEYWORDS([push])])
])# _AT_BISON_OPTION_PUSHDEFS
+2 -2
View File
@@ -759,7 +759,7 @@ AT_TEST([x1],
])
# 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
** Define the x1::location class.
#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
]])
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
** Define the x1::parser class.
#ifndef YY_YY_BAR_X1_HH_INCLUDED