Compare commits

...
131 Commits
Author SHA1 Message Date
Akim Demaille 7a11a9308c version 3.7.4
* NEWS: Record release date.
2020-11-14 12:04:26 +01:00
Akim Demaille d8cc6b073e c++: shorten the assertions that check whether tokens are correct
Before:

    YY_ASSERT (tok == token::YYEOF || tok == token::YYerror || tok == token::YYUNDEF || tok == 120 || tok == 49 || tok == 50 || tok == 51 || tok == 52 || tok == 53 || tok == 54 || tok == 55 || tok == 56 || tok == 57 || tok == 97 || tok == 98);

After:

    YY_ASSERT (tok == token::YYEOF
               || (token::YYerror <= tok && tok <= token::YYUNDEF)
               || tok == 120
               || (49 <= tok && tok <= 57)
               || (97 <= tok && tok <= 98));

Clauses are now also wrapped on several lines.  This is nicer to read
and diff, but also avoids pushing Visual C++ to its arbitrary
limits (640K and lines of 16380 bytes ought to be enough for anybody,
otherwise make an C2026 error).

The useless parens are there for the dummy warnings about
precedence (in the future, will we also have to put parens in
`1+2*3`?).

* data/skeletons/variant.hh (_b4_filter_tokens, b4_tok_in, b4_tok_in):
New.
(_b4_token_constructor_define): Use them.
2020-11-13 06:17:52 +01:00
Akim Demaille 0264b4bca0 c++: don't glue functions together
* data/skeletons/bison.m4 (b4_type_foreach): Accept a separator.
* data/skeletons/c++.m4: Use it.
And fix an incorrect comment.
2020-11-13 06:17:52 +01:00
Akim Demaille 8b424b865e lalr1.cc: YY_ASSERT should use api.prefix
Working on the previous commit I realized that YY_ASSERT was used in
the generated headers, so must follow api.prefix to avoid clashes when
multiple C++ parser with variants are used.

Actually many more macros should obey api.prefix (YY_CPLUSPLUS,
YY_COPY, etc.).  There was no complaint so far, so it's not urgent
enough for 3.7.4, but it should be addressed in 3.8.

* data/skeletons/variant.hh (b4_assert): New.
Use it.
* tests/local.at (AT_YYLEX_RETURN): Fix.
* tests/headers.at: Make sure variant-based C++ parsers are checked
too.
This test did find that YY_ASSERT escaped renaming (before the fix in
this commit).
2020-11-13 06:17:52 +01:00
Akim Demaille f4431ea115 c++: don't use YY_ASSERT at all if parse.assert is disabled
In some extreme situations (about 800 tokens), we generate a
single-line assertion long enough for Visual C++ to discard the end of
the line, thus falling into parse ends for the missing `);`.  On a
shorter example:

    YY_ASSERT (tok == token::TOK_YYEOF || tok == token::TOK_YYerror || tok == token::TOK_YYUNDEF || tok == token::TOK_ASSIGN || tok == token::TOK_MINUS || tok == token::TOK_PLUS || tok == token::TOK_STAR || tok == token::TOK_SLASH || tok == token::TOK_LPAREN || tok == token::TOK_RPAREN);

Whether NDEBUG is used or not is irrelevant, the parser dies anyway.

Reported by Jot Dot <[email protected]>.
https://lists.gnu.org/r/bug-bison/2020-11/msg00002.html

We should avoid emitting lines so long.

We probably should also use a range-based assertion (with extraneous
parens to pacify fascist compilers):

    YY_ASSERT ((token::TOK_YYEOF <= tok && tok <= token::TOK_YYUNDEF)
               || (token::TOK_ASSIGN <= tok && ...)

But anyway, we should simply not emit this assertion at all when not
asked for.

* data/skeletons/variant.hh: Do not define, nor use, YY_ASSERT when it
is not enabled.
2020-11-13 06:17:52 +01:00
Akim Demaille fe8c36ddca c++: style: follow the Bison m4 quoting pattern
* data/skeletons/variant.hh: here.
2020-11-13 06:17:24 +01:00
Akim Demaille 21c147b6e5 yacc.c: provide the Bison version as an integral macro
Suggested by Balazs Scheidler.
https://github.com/akimd/bison/issues/55

* src/muscle-tab.c (muscle_init): Move/rename `b4_version` to/as...
* src/output.c (prepare): `b4_version_string`.
Also define `b4_version`.
* data/skeletons/bison.m4, data/skeletons/c.m4, data/skeletons/d.m4,
* data/skeletons/java.m4: Adjust.
* doc/bison.texi: Document it.
2020-11-11 09:08:57 +01:00
Akim Demaille d3c575a6c6 regen 2020-11-11 08:47:23 +01:00
Akim Demaille d8b49e2b73 style: make conversion of version string to int public
* src/parse-gram.y (str_to_version): Rename as/move to...
* src/strversion.h, src/strversion.c (strversion_to_int): these new
files.
2020-11-11 08:47:23 +01:00
Akim Demaille 14c65a35f0 %require: accept version numbers with three parts ("3.7.4")
* src/parse-gram.y (str_to_version): Support three parts.
* data/skeletons/location.cc, data/skeletons/stack.hh:
Adjust.
2020-11-11 08:47:23 +01:00
Todd C. MillerandAkim Demaille c47bb87f9f yacc.c: fix #definition of YYEMPTY
When generating a C parser, YYEMPTY is present in enum yytokentype but
there is no corresponding #define like there is for the other values.
There is a special case for YYEMPTY in b4_token_enums but no
corresponding case in b4_token_defines.

* data/skeletons/c.m4 (b4_token_defines): Do define YYEMPTY.
2020-11-11 08:47:21 +01:00
Akim Demaille 98c35e0025 gnulib: update 2020-11-10 07:56:13 +01:00
Akim Demaille bd6b046ce7 doc: fix incorrect section title
Reported by Gaurav Singh <[email protected]>.
https://lists.gnu.org/r/bug-bison/2020-11/msg00000.html

* doc/bison.texi (Rpcalc Expr): Rename as...
(Rpcalc Exp): this, as the nterm is named 'exp'.
2020-11-01 09:12:27 +01:00
Nick GassonandAkim Demaille 7c6e7bd300 doc: minor grammar fixes in counterexamples section
* doc/bison.texi: Minor fixes in counterexamples section.
2020-10-28 06:36:43 +01:00
Akim Demaille 3cba59dd7f doc: fix typo
* README: here.
2020-10-14 21:12:04 +02:00
Akim Demaille a15879c623 maint: post-release administrivia
* NEWS: Add header line for next release.
* .prev-version: Record previous version.
* cfg.mk (old_NEWS_hash): Auto-update.
2020-10-13 07:23:28 +02:00
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
Akim Demaille 6675d36e25 version 3.7
* NEWS: Record release date.
2020-07-23 19:58:16 +02:00
Akim Demaille d0bec3175f style: avoid warnings with GCC 4.6
With have a clash with the "max" function.

    src/counterexample.c: In function 'visited_hasher':
    src/counterexample.c:720:48: error: declaration of 'max' shadows a global declaration [-Werror=shadow]
    src/counterexample.c:116:12: error: shadowed declaration is here [-Werror=shadow]

* src/counterexample.c (visited_hasher): Alpha conversion.
2020-07-23 19:55:24 +02:00
Akim Demaille 79e68b6c4d doc: fix definition of -Wall
* doc/bison.texi (Diagnostics): here.
2020-07-23 09:17:18 +02:00
Akim Demaille 5cb74cacd8 gnulib: update
* bootstrap.conf: We need stpncpy.
2020-07-23 06:56:25 +02:00
Akim Demaille 9c8e6e05b6 tests: fixes
Fix 6b78e50cef, "cex: make "rerun with
'-Wcex'" a note instead of a warning"

* tests/conflicts.at (-W versus %expect and %expect-rr): Fix
expectations.
2020-07-23 06:33:30 +02:00
Akim Demaille 431774d1f6 cex: update NEWS for 3.7
* NEWS: Update to the current style of cex display.
2020-07-22 07:36:02 +02:00
Akim Demaille 7d5474e979 doc: catch up with the current display of cex
Unfortunately I found no way to use the ↳ glyph in Texinfo, so I used
@arrow{} instead, which has a different width, so we have to have all
the examples doubled, once for TeX, another for the rest of the world.

* doc/bison.texi: Use the current display in the examples.
* doc/calc.y, doc/ids.y, doc/if-then-else.y, doc/sequence.y: New.
2020-07-22 07:36:02 +02:00
Akim Demaille 6b78e50cef cex: make "rerun with '-Wcex'" a note instead of a warning
Currently the suggestion to rerun is a -Wother warning:

    warning: 2 shift/reduce conflicts [-Wconflicts-sr]
    warning: rerun with option '-Wcounterexamples' to generate conflict counterexamples [-Wother]

Instead, let's attach it as a subnote of the diagnostic (in the
current case, -Wconflicts-sr):

    warning: 2 shift/reduce conflicts [-Wconflicts-sr]
    note: rerun with option '-Wcounterexamples' to generate conflict counterexamples

* src/conflicts.c (conflicts_print): Do that.
Adjust the test suite.
2020-07-21 18:57:56 +02:00
Akim Demaille 28769d608e 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-20 07:58:03 +02:00
Akim Demaille a22588bcb9 version 3.6.93
* NEWS: Record release date.
2020-07-20 07:37:47 +02:00
Akim Demaille b8c5e5609f cex: label all the derivations by their initial action
From

    input.y: warning: reduce/reduce conflict on token $end [-Wcounterexamples]
      Example: A b .
      First derivation
        a
        `-> A b .
      Second derivation
        a
        `-> A b
              `-> b .

to

    input.y: warning: reduce/reduce conflict on token $end [-Wcounterexamples]
      Example: A b .
      First reduce derivation
        a
        `-> A b .
      Second reduce derivation
        a
        `-> A b
              `-> b .

* src/counterexample.c (print_counterexample): here.
Compute the width of the labels to properly align the values.
* tests/conflicts.at, tests/counterexample.at, tests/diagnostics.at,
* tests/report.at: Adjust.
2020-07-20 07:36:38 +02:00
Akim Demaille b81229e1f9 cex: improve readability of the subsections
Now that the derivation is no longer printed on one line, aligning the
example and the derivation is no longer useful.  It can actually be
harmful, as it makes the overall structure less clear.

* src/derivation.h, src/derivation.c (derivation_print_leaves): Remove
the `prefix` argument.
* src/counterexample.c (print_counterexample): Put the example next to
its label.
* tests/conflicts.at, tests/counterexample.at, tests/diagnostics.at,
* tests/report.at: Adjust.
2020-07-20 07:09:31 +02:00
Akim Demaille 815a76f558 cex: don't issue an empty line between counterexamples
Now that we use complain, the "sections" are clearer.

* src/counterexample.c (print_counterexample): Use the empty line only
in reports.
* tests/counterexample.at, tests/diagnostics.at, tests/report.at: Adjust.
2020-07-20 06:45:31 +02:00
Akim Demaille ea138cd1f1 cex: use usual routines for diagnostics about S/R conflicts
See previous commit.  We go from

    input.y: warning: 3 reduce/reduce conflicts [-Wconflicts-rr]
    Shift/reduce conflict on token "⊕":
      Example              exp "+" exp • "⊕" exp
      Shift derivation
        exp
        ↳ exp "+" exp
                  ↳ exp • "⊕" exp

to

    input.y: warning: 3 reduce/reduce conflicts [-Wconflicts-rr]
    input.y: warning: shift/reduce conflict on token "⊕" [-Wcounterexamples]
      Example              exp "+" exp • "⊕" exp
      Shift derivation
        exp
        ↳ exp "+" exp
                  ↳ exp • "⊕" exp

with an hyperlink on -Wcounterexamples.

* src/counterexample.c (counterexample_report_shift_reduce):
Use complain.
* tests/counterexample.at, tests/diagnostics.at, tests/report.at:
Adjust.
2020-07-20 06:45:27 +02:00
Akim Demaille 9922f1f877 cex: use usual routines for diagnostics about R/R conflicts
This is more consistent, and brings benefits: users know that these
diagnostics are attached to -Wcounterexamples, and they can also click
on the hyperlink if permitted by their terminal.

We go from

    warning: 1 reduce/reduce conflict [-Wconflicts-rr]
    Reduce/reduce conflict on token $end:
      Example              A b .
      First derivation     a -> [ A b . ]
      Second derivation    a -> [ A b -> [ b . ] ]

to

    warning: 1 reduce/reduce conflict [-Wconflicts-rr]
    input.y: warning: reduce/reduce conflict on token $end [-Wcounterexamples]
      Example              A b .
      First derivation     a -> [ A b . ]
      Second derivation    a -> [ A b -> [ b . ] ]

with an hyperlink on -Wcounterexamples.

* src/counterexample.c (counterexample_report_reduce_reduce):
Use complain.
* tests/counterexample.at, tests/diagnostics.at, tests/report.at:
Adjust.
2020-07-20 06:45:21 +02:00
Akim Demaille 1438b79e80 diagnostics: use hyperlinks to point to the only documentation
* src/complain.c (begin_hyperlink, end_hyperlink): New.
(warnings_print_categories): Use them.
* tests/local.at (AT_SET_ENV): Disable hyperlinks in the tests, they
contain random id's, and brackets (which is not so nice for M4).
2020-07-19 19:26:47 +02:00
Akim Demaille 01f3e2969b doc: add anchors for warnings
Unfortunately Texinfo somewhat mangles anchors such as `-Werror` into
`g_t_002dWerror`, so let's not include the dash.

* doc/bison.texi (Diagnostics): here.
2020-07-19 17:28:45 +02:00
Akim Demaille 744da03955 glyphs: fix types
The code was written on top of buffers of `char[26]`, and then was
changed to use `char *`, yet was still using `sizeof buf`, which
became `sizeof (char *)` instead of `sizeof (char[26])`.

Reported by Dagobert Michelsen.
https://lists.gnu.org/r/bug-bison/2020-07/msg00023.html

* src/glyphs.h, src/glyphs.c: Get rid of uses of `char *`, use only
glyph_buffer_t.
2020-07-19 17:09:01 +02:00
Akim Demaille b28d67b6b0 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-19 09:45:36 +02:00
Akim Demaille cf890692f1 version 3.6.92
* NEWS: Record release date.
2020-07-19 09:24:57 +02:00
Akim Demaille 6932023f4d style: avoid strncpy
syntax-check seems to dislike strncpy.  The GNU Coreutils replaced
their uses of strncpy with stpncpy.

strlcpy is not an option.
  http://sources.redhat.com/ml/libc-alpha/2002-01/msg00159.html
  http://sources.redhat.com/ml/libc-alpha/2002-01/msg00011.html
  http://lists.gnu.org/archive/html/bug-gnulib/2004-09/msg00181.html

* src/glyphs.c: Use stpncpy.
2020-07-19 09:23:42 +02:00
Akim Demaille fff17fe8fe cex: display derivations as trees
Sometimes, understanding the derivations is difficult, because they
are serialized to fit in one line.  For instance, the example taken
from the NEWS file:

    %token ID
    %%
    s: a ID
    a: expr
    expr: expr ID ',' | "expr"

gave

    First example        expr • ID ',' ID $end
    Shift derivation     $accept → [ s → [ a → [ expr → [ expr • ID ',' ] ] ID ] $end ]
    Second example       expr • ID $end
    Reduce derivation    $accept → [ s → [ a → [ expr • ] ID ] $end ]

Printing as trees, it gives:

    First example        expr • ID ',' ID $end
    Shift derivation
      $accept
      ↳ s                      $end
        ↳ a                 ID
          ↳ expr
            ↳ expr • ID ','
    Second example       expr • ID $end
    Reduce derivation
      $accept
      ↳ s             $end
        ↳ a        ID
          ↳ expr •

* src/glyphs.h, src/glyphs.c (down_arrow, empty, derivation_separator):
New.
* src/derivation.c (derivation_print, derivation_print_impl): Rename
as...
(derivation_print_flat, derivation_print_flat_impl): These.
(fputs_if, derivation_depth, derivation_width, derivation_print_tree)
(derivation_print_tree_impl, derivation_print): New.
* src/counterexample.c (print_counterexample): Adjust.
* tests/conflicts.at, tests/counterexample.at, tests/diagnostics.at,
* tests/report.at: Adjust.
2020-07-18 07:54:02 +02:00
Akim Demaille 5544615a59 cex: use the glyphs
* src/derivation.c: here.
* src/gram.h, src/gram.c (print_arrow, print_dot, print_fallback):
Remove.
2020-07-16 07:31:25 +02:00
Akim Demaille 346ba14f15 cex: factor the handling of graphical symbols
* src/glyphs.h, src/glyphs.c: New.
2020-07-16 07:31:24 +02:00
Akim Demaille 4d18195ebc cex: style changes
* src/counterexample.c: here.
2020-07-15 06:41:07 +02:00
Akim Demaille dd3e7b3895 cex: simplify tests
* tests/counterexample.at (AT_BISON_CHECK_CEX): Handle the keyword.
Simplify the signature.
2020-07-15 06:38:36 +02:00
Akim Demaille 64a3b6546a cex: more colors
Provided by Daniela Becker.

* data/bison-default.css: More colors.
2020-07-15 06:38:36 +02:00
Akim Demaille bad07a7f66 style: comments changes
* src/print.c: here.
2020-07-14 14:26:02 +02:00
Akim Demaille 88bd814bf1 doc: update GLR sections
Reported by Christian Schoenebeck.

* doc/bison.texi (GLR Parsers): Minor fixes.
(Compiler Requirements for GLR): Remove, quite useless today.
2020-07-14 06:56:15 +02:00
Akim Demaille 4f9ae5de07 cex: display shifts before reductions
When reporting counterexamples for s/r conflicts, put the shift first.
This is more natural, and displays the default resolution first, which
is also what happens for r/r conflicts where the smallest rule number
is displayed first, and "wins".

* src/counterexample.c (counterexample): Add a shift_reduce member.
(new_counterexample): Adjust.
Swap the derivations when this is a s/r conflict.
(print_counterexample): For s/r conflicts, prefer "Shift derivation"
and "Reduce derivation" rather than "First/Second derivation".

* tests/conflicts.at, tests/counterexample.at, tests/report.at: Adjust.
* NEWS, doc/bison.texi: Ditto.
2020-07-14 06:48:48 +02:00
Akim Demaille 78f72a4516 style: s/lookahead_tokens/lookaheads/g
Currently we use both names.  Let's stick to the short one.

* src/AnnotationList.c, src/conflicts.c, src/counterexample.c,
* src/getargs.c, src/getargs.h, src/graphviz.c, src/ielr.c,
* src/lalr.c, src/print-graph.c, src/print-xml.c, src/print.c,
* src/state-item.c, src/state.c, src/state.h, src/tables.c:
s/lookahead_token/lookahead/gi.
2020-07-14 06:48:48 +02:00
Akim Demaille c04693d651 cex: factor memory allocation
* src/counterexample.c (counterexample_report_state): Allocate once
per conflicted state, instead of once per r/r conflict.
2020-07-14 06:48:48 +02:00
Akim Demaille 12191911ba cex: use state_item_number consistently
* src/counterexample.c, src/state-item.c: here.
(counterexample_report_state): While at it, prefer c2 to j/k, to match
c1.
2020-07-14 06:48:48 +02:00
Akim Demaille d7f27477f4 cex: more consistent memory allocation/copy
* src/counterexample.c, src/parse-simulation.c: It is more usual in
Bison to use sizeof on expressions than on types, especially for
allocation.
Let the compiler do it's job instead of calling memcpy ourselves.
2020-07-14 06:48:48 +02:00
Akim Demaille 5bad15d7ea cex: minor renaming
* src/counterexample.c (has_common_prefix): Rename as...
(have_common_prefix): this.
2020-07-14 06:48:48 +02:00
Akim Demaille cd099edf2d cex: use better type names
There are too many gl_list_t in there, it's hard to understand what is
going on.  Introduce and use more precise types.  I sure can be wrong
in some places, it's hard to tell without proper tool support.

* src/counterexample.c, src/lssi.c, src/lssi.h, src/parse-simulation.c,
* src/parse-simulation.h, src/state-item.c, src/state-item.h
(si_bfs_node_list, search_state_list, ssb_list, lssi_list)
(state_item_list): New.
2020-07-14 06:48:48 +02:00
Akim Demaille 1e12219775 cex: minor style changes
* src/counterexample.h, src/derivation.h, src/derivation.c:
More comments.
Use `out` for FILE*, as elsewhere.
2020-07-14 06:48:48 +02:00
Akim Demaille d8c2af56c1 tests: beware of version numbers from git describe
* tests/report.at: Be robust to version numbers such as
3.6.4.133-fbac-dirty.
2020-07-14 06:48:48 +02:00
Akim Demaille cc11bb037c tests: fix expectations
Broken in ee86ea8839.

* tests/diagnostics.at: here.
2020-07-14 06:48:48 +02:00
Akim Demaille 121dd98508 doc: makeinfo wants @arrow{}, not @arrow
* doc/bison.texi: here.
2020-07-12 08:15:44 +02:00
Akim Demaille 2eddbd0ac4 gnulib: update 2020-07-11 19:11:19 +02:00
Akim Demaille ee86ea8839 cex: prefer → to ::=
It does not make a lot of sense to use ::= in our counterexamples,
that's not something that belongs to the Bison "vocabulary".  Using
the colon makes sense, but it's too discreet.  Let's use the arrow,
which we already use in some reports (HTML and Dot).

* src/gram.h (print_dot_fallback): Generalize into...
(print_fallback): this.
(print_arrow): New.
* src/derivation.c: Use it.

* NEWS, tests/conflicts.at, tests/counterexample.at,
* tests/diagnostics.at, tests/report.at: Adjust.
* doc/bison.texi: Ditto.
Unfortunately the literal `→` is output as `↦`.  So we need to use
@arrow.
2020-07-11 18:43:46 +02:00
Akim Demaille a2ad33dca6 style: cex: prefer the array notation
Prefer `&foos[i]` to `foos + i` when `foos` is an array.  IMHO, it
makes the semantics clearer.

* src/counterexample.c, src/lssi.c, src/parse-simulation.c,
* src/state-item.c: With arrays, prefer the array notation rather than
the pointer one.
2020-07-11 18:07:09 +02:00
Akim Demaille 5b2b7b1ffb style: cex: remove variables that don't make it simpler to read
* src/counterexample.c: With arrays, prefer the array notation rather
than the pointer one.
2020-07-11 18:07:09 +02:00
Akim Demaille dc72b3566d bistromathic: demonstrate caret-diagnostics
* examples/c/bistromathic/parse.y (user_context): We need the current
line.
(yyreport_syntax_error): Quote the guilty line, with squiggles.
* examples/c/bistromathic/bistromathic.test: Adjust.
2020-07-11 18:06:45 +02:00
Akim Demaille c47e1174d4 bistromathic: do not display parse errors on completion
Currently autocompletion on a line with errors leaks the error
messages.  It can be useful to let the user know, but GNU Readline
does not provide us with an nice way to display the error.  So we
actually break into the current line of the user.

So instead, do not show these errors.

* examples/c/bistromathic/parse.y (user_context): New.
Use %param to pass it to the parser and scanner.
Keep quiet when in computing autocompletion.
2020-07-11 18:05:50 +02:00
Akim Demaille 093eeb27e9 bistromathic: don't stupidly reset the location for each token
That quite defeats the whole point of locations...  But anyway, we
should not see these messages at all.

* examples/c/bistromathic/parse.y (expected_tokens): Fix (useless)
location tracking.
2020-07-11 18:05:41 +02:00
Akim Demaille dab23c4a21 bistromathic: promote yytoken_kind_t
* examples/c/bistromathic/parse.y: Use yytoken_kind_t rather than int.
2020-07-11 18:05:35 +02:00
Akim Demaille 38a169bec1 html: capitalize titles
* data/xslt/xml2xhtml.xsl: Use "State 0", not "state 0".
As we do in text reports.
2020-07-11 12:58:45 +02:00
Akim Demaille dc77d6500f html: don't define several times the same anchors
Currently when we output useless rules, they appear before the
grammar, but using the same invocation.  As a result, the anchor is
defined twice, and the wrong one, being first, is honored.

* data/xslt/xml2xhtml.xsl (rule): Take a new 'anchor' parameter to
decide whether being an anchor, or a target.
Let it be true when output the grammar.
* tests/report.at: Adjust.
2020-07-11 12:58:44 +02:00
Akim Demaille 8262c7dc22 html: simplify
* data/xslt/xml2xhtml.xsl: Merge two identical when-clauses.
2020-07-11 12:58:44 +02:00
Akim Demaille 44f28d10ee reports: let html reports catch up with --report and --graph
* data/xslt/xml2xhtml.xsl: Show the symbol types.
* tests/report.at: Adjust.
2020-07-11 12:58:44 +02:00
Akim Demaille 44ad466a32 reports: let xml reports catch up with --report and --graph
The text and Dot reports are expected to be identical when generated
directly (--report, --graph) or indirectly (via XML).  The xml
testsuite had not be run for ages, let it catch up a bit.

* src/print-xml.c: Pass the type of the symbols.
* data/xslt/xml2text.xsl
Catch up with the new layout.
Display the symbol types.
Use '•', not '.'
* tests/local.at: Smash '•' to '.' when matching against the direct
text report.
* tests/report.at: Adjust XML expectations.
2020-07-11 12:58:44 +02:00
Akim Demaille a839f4c461 reports: update html ouput
* data/xslt/xml2xhtml.xsl: Improve indentation.
Use ul/li rather that pre.
2020-07-11 12:58:44 +02:00
Akim Demaille 9a51c6a128 tests: check html
* tests/report.at: here.
2020-07-11 12:58:44 +02:00
Akim Demaille 2608b0cf12 style: factor complex expressions
* src/print-xml.c, src/print.c: Introduce a variable pointing to the
current symbol.
2020-07-11 12:58:44 +02:00
Akim Demaille aa766d1560 maint: make it easier to update expectations
* tests/local.mk (update-tests): New.
2020-07-11 12:58:44 +02:00
Akim Demaille a7ed13b25f 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-09 21:38:23 +02:00
Akim Demaille 2d90916067 version 3.6.91
* NEWS: Record release date.
2020-07-09 21:10:23 +02:00
Akim Demaille 91e5a23ff2 news: update 2020-07-09 20:29:24 +02:00
Akim Demaille d4ae66c371 gnulib: update 2020-07-09 20:26:16 +02:00
Akim Demaille 70fb574717 examples: add license headers
Prompted by Rici Lake.
https://stackoverflow.com/questions/62658368/#comment110853985_62661621
Discussed with Paul Eggert.

* doc/bison.texi, examples/c/bistromathic/parse.y,
* examples/c/lexcalc/parse.y, examples/c/lexcalc/scan.l,
* examples/c/pushcalc/calc.y, examples/c/reccalc/parse.y,
* examples/c/reccalc/scan.l, examples/d/calc.y,
* examples/java/calc/Calc.y, examples/java/simple/Calc.y:
Install the GPL3+ header.
2020-07-08 22:19:37 +02:00
Akim Demaille 0820f16ca8 style: update comments
* src/reader.c: action_obstack was removed in 2002...
* src/parse-gram.y: Better names.
* src/scan-code.h: More comments.
2020-07-05 09:59:45 +02:00
Akim Demaille 49f1e5f428 style: update comments in the skeletons
* data/skeletons/c++.m4, data/skeletons/glr.c, data/skeletons/lalr1.d,
* data/skeletons/lalr1.java, data/skeletons/yacc.c:
Be more accurate about yychar and yytoken.
Don't name local variables as if they were members.
2020-07-05 09:59:25 +02:00
Akim Demaille 238692ad77 doc: more details about symbols in m4
* data/README.md: here.
* README-hacking.md (Vocabulary): More.
2020-07-05 09:18:27 +02:00
Akim Demaille 5f95583da7 regen 2020-07-05 08:18:51 +02:00
Akim Demaille 964fb2aa6f examples: include the generated header
* examples/c/bistromathic/parse.y, examples/c/lexcalc/parse.y,
* examples/c/reccalc/parse.y: here.
Add some comments.

* src/parse-gram.y (api_version): Pull out of handle_require.
Bump to 3.7.
2020-07-05 08:18:51 +02:00
Akim Demaille 7c0d36b760 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-04 12:37:45 +02:00
116 changed files with 4683 additions and 1452 deletions
+1 -1
View File
@@ -1 +1 @@
3.6.4 3.7.3
+4 -1
View File
@@ -50,6 +50,7 @@ jobs:
- make -j2 dist-xz - make -j2 dist-xz
# Can help understanding why we get "dirty" tarballs. # Can help understanding why we get "dirty" tarballs.
- git status - git status
- git diff
- dist=$(echo bison*.xz) - dist=$(echo bison*.xz)
# Unfortunately we cannot deterministically know the name of the tarball without the full # Unfortunately we cannot deterministically know the name of the tarball without the full
@@ -119,6 +120,8 @@ jobs:
- CXX='clang++-10 -fsanitize=address -stdlib=libc++' - CXX='clang++-10 -fsanitize=address -stdlib=libc++'
- PART=2 - PART=2
# See https://github.com/simd-everywhere/simde/blob/master/.travis.yml
# and https://software.intel.com/content/www/us/en/develop/documentation/get-started-with-intel-oneapi-render-linux/top/configure-your-system.html.
- name: "ICC" - name: "ICC"
stage: check stage: check
os: linux os: linux
@@ -127,7 +130,7 @@ jobs:
- CC=icc - CC=icc
- CXX=icpc - CXX=icpc
install: install:
- source /opt/intel/inteloneapi/compiler/latest/env/vars.sh - source /opt/intel/oneapi/compiler/latest/env/vars.sh
addons: addons:
apt: apt:
sources: sources:
+201 -18
View File
@@ -1,6 +1,84 @@
GNU Bison NEWS GNU Bison NEWS
* Noteworthy changes in release 3.6.90 (2020-07-04) [beta] * Noteworthy changes in release 3.7.4 (2020-11-14) [stable]
** Bug fixes
*** Bug fixes in yacc.c
In Yacc mode, all the tokens are defined twice: once as an enum, and then
as a macro. YYEMPTY was missing its macro.
*** Bug fixes in lalr1.cc
The lalr1.cc skeleton used to emit internal assertions (using YY_ASSERT)
even when the `parse.assert` %define variable is not enabled. It no
longer does.
The private internal macro YY_ASSERT now obeys the `api.prefix` %define
variable.
When there is a very large number of tokens, some assertions could be long
enough to hit arbitrary limits in Visual C++. They have been rewritten to
work around this limitation.
** Changes
The YYBISON macro in generated "regular C parsers" (from the "yacc.c"
skeleton) used to be defined to 1. It is now defined to the version of
Bison as an integer (e.g., 30704 for version 3.7.4).
* 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 ** Deprecated features
@@ -18,28 +96,115 @@ GNU Bison NEWS
Contributed by Vincent Imbimbo. Contributed by Vincent Imbimbo.
When given `--report=counterexamples` or `-Wcounterexamples`, bison will When given `-Wcounterexamples`/`-Wcex`, bison will now output
now output counterexamples for conflicts in the grammar. These are counterexamples for conflicts.
strings in the grammar which can be parsed in two ways due to the
conflict. For example:
Example exp '+' exp • '/' exp **** Unifying Counterexamples
First derivation exp ::=[ exp ::=[ exp '+' exp • ] '/' exp ]
Second derivation exp ::=[ exp '+' exp ::=[ exp • '/' exp ] ]
This is a shift/reduce conflict caused by none of the operators having Unifying counterexamples are strings which can be parsed in two ways due
precedence, so the example can be parsed in the two ways shown. When to the conflict. For example on a grammar that contains the usual
bison cannot find an example that can be derived in two ways, it instead "dangling else" ambiguity:
generates two examples that are the same up until the dot:
First example expr • ID $end $ bison else.y
First derivation $accept ::=[ s ::=[ a ::=[ expr • ] ID ] $end ] else.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
Second example expr • ID ',' ID $end else.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples
Second derivation $accept ::=[ s ::=[ a ::=[ expr ::=[ expr • ID ',' ] ] ID ] $end ]
$ bison else.y -Wcex
else.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
else.y: warning: shift/reduce conflict on token "else" [-Wcounterexamples]
Example: "if" exp "then" "if" exp "then" exp • "else" exp
Shift derivation
exp
↳ "if" exp "then" exp
↳ "if" exp "then" exp • "else" exp
Example: "if" exp "then" "if" exp "then" exp • "else" exp
Reduce derivation
exp
↳ "if" exp "then" exp "else" exp
↳ "if" exp "then" exp •
When text styling is enabled, colors are used in the examples and the
derivations to highlight the structure of both analyses. In this case,
"if" exp "then" [ "if" exp "then" exp • ] "else" exp
vs.
"if" exp "then" [ "if" exp "then" exp • "else" exp ]
The counterexamples are "focused", in two different ways. First, they do
not clutter the output with all the derivations from the start symbol,
rather they start on the "conflicted nonterminal". They go straight to the
point. Second, they don't "expand" nonterminal symbols uselessly.
**** Nonunifying Counterexamples
In the case of the dangling else, Bison found an example that can be
parsed in two ways (therefore proving that the grammar is ambiguous).
When it cannot find such an example, it instead generates two examples
that are the same up until the dot:
$ bison foo.y
foo.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
foo.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples
foo.y:4.4-7: warning: rule useless in parser due to conflicts [-Wother]
4 | a: expr
| ^~~~
$ bison -Wcex foo.y
foo.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
foo.y: warning: shift/reduce conflict on token ID [-Wcounterexamples]
First example: expr • ID ',' ID $end
Shift derivation
$accept
↳ s $end
↳ a ID
↳ expr
↳ expr • ID ','
Second example: expr • ID $end
Reduce derivation
$accept
↳ s $end
↳ a ID
↳ expr •
foo.y:4.4-7: warning: rule useless in parser due to conflicts [-Wother]
4 | a: expr
| ^~~~
In these cases, the parser usually doesn't have enough lookahead to In these cases, the parser usually doesn't have enough lookahead to
differentiate the two given examples. differentiate the two given examples.
**** Reports
Counterexamples are also included in the report when given
`--report=counterexamples`/`-rcex` (or `--report=all`), with more
technical details:
State 7
1 exp: "if" exp "then" exp • [$end, "then", "else"]
2 | "if" exp "then" exp • "else" exp
"else" shift, and go to state 8
"else" [reduce using rule 1 (exp)]
$default reduce using rule 1 (exp)
shift/reduce conflict on token "else":
1 exp: "if" exp "then" exp •
2 exp: "if" exp "then" exp • "else" exp
Example: "if" exp "then" "if" exp "then" exp • "else" exp
Shift derivation
exp
↳ "if" exp "then" exp
↳ "if" exp "then" exp • "else" exp
Example: "if" exp "then" "if" exp "then" exp • "else" exp
Reduce derivation
exp
↳ "if" exp "then" exp "else" exp
↳ "if" exp "then" exp •
*** File prefix mapping *** File prefix mapping
Contributed by Joshua Watt. Contributed by Joshua Watt.
@@ -52,6 +217,11 @@ GNU Bison NEWS
** Changes ** Changes
*** Diagnostics
When text styling is enabled and the terminal supports it, the warnings
now include hyperlinks to the documentation.
*** Relocatable installation *** Relocatable installation
When installed to be relocatable (via `configure --enable-relocatable`), When installed to be relocatable (via `configure --enable-relocatable`),
@@ -92,6 +262,18 @@ GNU Bison NEWS
Now the parser state can be examined when parsing is finished. The parser Now the parser state can be examined when parsing is finished. The parser
state is reset when starting a new parse. state is reset when starting a new parse.
** Documentation
*** Examples
The bistromathic demonstrates %param and how to quote sources in the error
messages:
> 123 456
1.5-7: syntax error: expected end of file or + or - or * or / or ^ before number
1 | 123 456
| ^~~
** Bug fixes ** Bug fixes
*** Include the generated header (yacc.c) *** Include the generated header (yacc.c)
@@ -433,7 +615,8 @@ GNU Bison NEWS
\005) with incorrect styling. Fixes for similar issues with unexpectedly \005) with incorrect styling. Fixes for similar issues with unexpectedly
short lines (e.g., the file was changed between parsing and diagnosing). short lines (e.g., the file was changed between parsing and diagnosing).
Several unlikely crashes found by fuzzing have been fixed. Some unlikely crashes found by fuzzing have been fixed. This is only
about bison itself, not the generated parsers.
* Noteworthy changes in release 3.5.2 (2020-02-13) [stable] * Noteworthy changes in release 3.5.2 (2020-02-13) [stable]
@@ -4357,7 +4540,7 @@ LocalWords: yysymbol yytnamerr yyreport ctx ARGMAX yysyntax stderr LPAREN
LocalWords: symrec yypcontext TOKENMAX yyexpected YYEMPTY yypstate YYEOF LocalWords: symrec yypcontext TOKENMAX yyexpected YYEMPTY yypstate YYEOF
LocalWords: autocompletion bistromathic submessages Cayuela lexcalc hoc LocalWords: autocompletion bistromathic submessages Cayuela lexcalc hoc
LocalWords: yytoken YYUNDEF YYerror basename Automake's UTF ifdef ffile LocalWords: yytoken YYUNDEF YYerror basename Automake's UTF ifdef ffile
LocalWords: gotos readline Imbimbo Wcounterexamples LocalWords: gotos readline Imbimbo Wcounterexamples Wcex Nonunifying rcex
Local Variables: Local Variables:
ispell-dictionary: "american" ispell-dictionary: "american"
+13 -4
View File
@@ -27,7 +27,7 @@ Bison from the git repo. Roughly, run:
then proceed with the usual `configure && make` steps. then proceed with the usual `configure && make` steps.
## Build from tarball ## Build from tarball
See the [INSTALL file](INSTALL] for generic compilation and installation See the [INSTALL file](INSTALL) for generic compilation and installation
instructions. instructions.
Bison requires GNU m4 1.4.6 or later. See Bison requires GNU m4 1.4.6 or later. See
@@ -42,9 +42,11 @@ installing it. In that case, do not use `src/bison`: it would use the
As an experimental feature, diagnostics are now colored, controlled by the As an experimental feature, diagnostics are now colored, controlled by the
`--color` and `--style` options. `--color` and `--style` options.
To use them, install the libtextstyle library before configuring Bison. It To use them, install the libtextstyle library, 0.20.5 or newer, before
is available from https://alpha.gnu.org/gnu/gettext/, for instance configuring Bison. It is available from https://alpha.gnu.org/gnu/gettext/,
https://alpha.gnu.org/pub/gnu/gettext/libtextstyle-0.20.5.tar.gz. for instance https://alpha.gnu.org/gnu/gettext/libtextstyle-0.20.5.tar.gz,
or as part of Gettext 0.21 or newer, for instance
https://ftp.gnu.org/gnu/gettext/gettext-0.21.tar.gz.
The option --color supports the following arguments: The option --color supports the following arguments:
- always, yes: Enable colors. - always, yes: Enable colors.
@@ -61,6 +63,13 @@ To customize the styles, create a CSS file, say `bison-bw.css`, similar to
then invoke bison with `--style=bison-bw.css`, or set the `BISON_STYLE` then invoke bison with `--style=bison-bw.css`, or set the `BISON_STYLE`
environment variable to `bison-bw.css`. environment variable to `bison-bw.css`.
In some diagnostics, bison uses libtextstyle to emit special escapes to
generate clickable hyperlinks. The environment variable
`NO_TERM_HYPERLINKS` can be used to suppress them. This may be useful for
terminal emulators which produce garbage output when they receive the escape
sequence for a hyperlink. Currently (as of 2020), this affects some versions
of emacs, guake, konsole, lxterminal, rxvt, yakuake.
## Relocatability ## Relocatability
If you pass `--enable-relocatable` to `configure`, Bison is relocatable. If you pass `--enable-relocatable` to `configure`, Bison is relocatable.
+3 -1
View File
@@ -211,6 +211,8 @@ assert/abort), and all the --trace output which is meant for the maintainers
only. only.
## Vocabulary ## Vocabulary
- "lookahead", not "look-ahead".
- "midrule", not "mid-rule".
- "nonterminal", not "variable" or "non-terminal" or "non terminal". - "nonterminal", not "variable" or "non-terminal" or "non terminal".
Abbreviated as "nterm". Abbreviated as "nterm".
- "shift/reduce" and "reduce/reduce", not "shift-reduce" or "shift reduce", - "shift/reduce" and "reduce/reduce", not "shift-reduce" or "shift reduce",
@@ -442,7 +444,7 @@ added the `[-Wother]` part to all the warnings). Part of the update can be
done with a crude tool: `build-aux/update-test`. done with a crude tool: `build-aux/update-test`.
Once you ran the test suite, and therefore have many `testsuite.log` files, Once you ran the test suite, and therefore have many `testsuite.log` files,
run, from the source tree: run `make update-tests`. Or, by hand, from the *source* tree:
$ ./build-aux/update-test $build/tests/testsuite.dir/*/testsuite.log $ ./build-aux/update-test $build/tests/testsuite.dir/*/testsuite.log
+4
View File
@@ -45,6 +45,7 @@ Csaba Raduly [email protected]
Dagobert Michelsen [email protected] Dagobert Michelsen [email protected]
Daniel Frużyński [email protected] Daniel Frużyński [email protected]
Daniel Galloway [email protected] Daniel Galloway [email protected]
Daniela Becker [email protected]
Daniel Hagerty [email protected] Daniel Hagerty [email protected]
David Barto [email protected] David Barto [email protected]
David J. MacKenzie [email protected] David J. MacKenzie [email protected]
@@ -105,9 +106,11 @@ Keith Browne [email protected]
Ken Moffat [email protected] Ken Moffat [email protected]
Kiyoshi Kanazawa [email protected] Kiyoshi Kanazawa [email protected]
Lars Maier [email protected] Lars Maier [email protected]
Lars Wendler [email protected]
László Várady [email protected] László Várady [email protected]
Laurent Mascherpa [email protected] Laurent Mascherpa [email protected]
Lie Yan [email protected] Lie Yan [email protected]
Maarten De Braekeleer [email protected]
Magnus Fromreide [email protected] Magnus Fromreide [email protected]
Marc Autret [email protected] Marc Autret [email protected]
Marc Mendiola [email protected] Marc Mendiola [email protected]
@@ -184,6 +187,7 @@ Simon Sobisch [email protected]
Stefano Lattarini [email protected] Stefano Lattarini [email protected]
Stephen Cameron [email protected] Stephen Cameron [email protected]
Steve Murphy [email protected] Steve Murphy [email protected]
Suhwan Song [email protected]
Sum Wu [email protected] Sum Wu [email protected]
Théophile Ranquet [email protected] Théophile Ranquet [email protected]
Thiru Ramakrishnan [email protected] Thiru Ramakrishnan [email protected]
+306 -18
View File
@@ -1,4 +1,12 @@
* Bison 3.7 * Soon
** gnulib
Bruno notes:
> I haven't looked deeply, but it strikes me that gnulib/lib/bitset/array.c
> does not make use of the 'ffsl' function, nor or the 'integer_length_l'
> function. Maybe because in Bison, all bitsets are so dense that it does
> not give a performance advantage?
** Cex ** Cex
*** Improve gnulib *** Improve gnulib
Don't do this (counterexample.c): Don't do this (counterexample.c):
@@ -36,8 +44,6 @@ Unless we play it dumb (little structure).
- How about not evaluating incomplete lines when the text is not finished - How about not evaluating incomplete lines when the text is not finished
(as shells do). (as shells do).
- Caret diagnostics
** Questions ** Questions
*** Java *** Java
- Should i18n be part of the Lexer? Currently it's a static method of - Should i18n be part of the Lexer? Currently it's a static method of
@@ -50,13 +56,6 @@ Unless we play it dumb (little structure).
- promote YYEOF rather than EOF. - promote YYEOF rather than EOF.
*** D
- is there a way to attach yysymbol_name to the enum itself? As we did
in Java.
- It would be better to have TokenKind as return value. Can we use
reflection to support both output types?
** YYerror ** YYerror
https://git.savannah.gnu.org/gitweb/?p=gettext.git;a=blob;f=gettext-runtime/intl/plural.y;h=a712255af4f2f739c93336d4ff6556d932a426a5;hb=HEAD https://git.savannah.gnu.org/gitweb/?p=gettext.git;a=blob;f=gettext-runtime/intl/plural.y;h=a712255af4f2f739c93336d4ff6556d932a426a5;hb=HEAD
@@ -69,7 +68,7 @@ Stop hard-coding "Calc". Adjust local.at (look for FIXME).
** A dev warning for b4_ ** A dev warning for b4_
Maybe we should check for m4_ and b4_ leaking out of the m4 processing, as Maybe we should check for m4_ and b4_ leaking out of the m4 processing, as
Autoconf does. It would have caught overquotation issues. Autoconf does. It would have caught over-quotation issues.
** doc ** doc
I feel it's ugly to use the GNU style to declare functions in the doc. It I feel it's ugly to use the GNU style to declare functions in the doc. It
@@ -90,7 +89,7 @@ push parsers on top of pull parser. Which is currently not relevant, since
push parsers are measurably slower. push parsers are measurably slower.
** %define parse.error formatted ** %define parse.error formatted
How about pushing bistromathics' yyreport_syntax_error as another standard How about pushing Bistromathic's yyreport_syntax_error as another standard
way to generate the error message, and leave to the user the task of way to generate the error message, and leave to the user the task of
providing the message formats? Currently in bistro, it reads: providing the message formats? Currently in bistro, it reads:
@@ -204,18 +203,282 @@ The "automaton" and "set" categories are not so useful. We should probably
introduce lr(0) and lalr, just the way we have ielr categories. The introduce lr(0) and lalr, just the way we have ielr categories. The
"closure" function is too verbose, it should probably have its own category. "closure" function is too verbose, it should probably have its own category.
"set" can still be used for summariring the important sets. That would make "set" can still be used for summarizing the important sets. That would make
tests easy to maintain. tests easy to maintain.
*** complain.* *** complain.*
Rename these guys as "diagnostics.*" (or "diagnose.*"), since that's the Rename these guys as "diagnostics.*" (or "diagnose.*"), since that's the
name they have in gcc, clang, etc. Likewise for the complain_* series of name they have in GCC, clang, etc. Likewise for the complain_* series of
functions. functions.
*** ritem *** ritem
states/nstates, rules/nrules, ..., ritem/nritems states/nstates, rules/nrules, ..., ritem/nritems
Fix the latter. Fix the latter.
* D programming language
There's a number of features that are missing, here sorted in _suggested_
order of implementation.
When copying code from other skeletons, keep the comments exactly as they
are. Keep the same variable names. If you change the wording in one place,
do it in the others too. In other words: make sure to keep the
maintenance *simple* by avoiding any gratuitous difference.
** Rename the D example
Move the current content of examples/d into examples/d/simple.
** Create a second example
Duplicate examples/d/simple into examples/d/calc.
** Add location tracking to d/calc
Look at the examples in the other languages to see how to do that.
** yysymbol_name
The SymbolKind is an enum. For a given SymbolKind we want to get its string
representation. Currently it's a separate table in the parser that does
that:
/* Symbol kinds. */
public enum SymbolKind
{
S_YYEMPTY = -2, /* No symbol. */
S_YYEOF = 0, /* "end of file" */
S_YYerror = 1, /* error */
S_YYUNDEF = 2, /* "invalid token" */
S_EQ = 3, /* "=" */
...
S_input = 14, /* input */
S_line = 15, /* line */
S_exp = 16, /* exp */
};
...
/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
First, the terminals, then, starting at \a yyntokens_, nonterminals. */
private static immutable string[] yytname_ =
[
"\"end of file\"", "error", "\"invalid token\"", "\"=\"", "\"+\"",
"\"-\"", "\"*\"", "\"/\"", "\"(\"", "\")\"", "\"end of line\"",
"\"number\"", "UNARY", "$accept", "input", "line", "exp", null
];
...
So to get a symbol kind, one runs `yytname_[yykind]`.
Is there a way to attach this conversion to string to SymbolKind? In Java
for instance, we have:
public enum SymbolKind
{
S_YYEOF(0), /* "end of file" */
S_YYerror(1), /* error */
S_YYUNDEF(2), /* "invalid token" */
...
S_input(16), /* input */
S_line(17), /* line */
S_exp(18); /* exp */
private final int yycode_;
SymbolKind (int n) {
this.yycode_ = n;
}
...
/* YYNAMES_[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
First, the terminals, then, starting at \a YYNTOKENS_, nonterminals. */
private static final String[] yynames_ = yynames_init();
private static final String[] yynames_init()
{
return new String[]
{
i18n("end of file"), i18n("error"), i18n("invalid token"), "!", "+", "-", "*",
"/", "^", "(", ")", "=", i18n("end of line"), i18n("number"), "NEG",
"$accept", "input", "line", "exp", null
};
}
/* The user-facing name of this symbol. */
public final String getName() {
return yynames_[yycode_];
}
};
which allows to write more naturally `yykind.getName()` rather than
`yytname_[yykind]`. Is there something comparable in (idiomatic) D?
** Change the return value of yylex
Historically people were allowed to return any int from the scanner (which
is convenient and allows `return '+'` from the scanner). Akim tends to see
this as an error, we should restrict the return values to TokenKind (not to
be confused with SymbolKind).
In the case of D, without the history, we have the choice to support or not
`int`. If we want to _keep_ `int`, is there a way, say via introspection,
to support both signatures of yylex? If we don't keep `int`, just move to
TokenKind.
** Documentation
Write documentation about D support in doc/bison.texi. Imitate the Java
documentation. You should be more succinct IMHO.
** Complete Symbols
The current interface from the scanner to the parser is somewhat clumsy: the
token kind is returned by yylex, but the value and location are stored in
the scanner. This reflects the fact that the implementation of the parser
uses three variables to deal with each parsed symbol: its kind, its value,
its location.
So today the scanner of examples/d/calc.d (no locations) looks like:
if (input.front.isNumber)
{
import std.conv : parse;
semanticVal_.ival = input.parse!int;
return TokenKind.NUM;
}
and the generated parser:
/* Read a lookahead token. */
if (yychar == TokenKind.YYEMPTY)
{
yychar = yylex ();
yylval = yylexer.semanticVal;
}
The parser class should feature a `Symbol` type which binds together kind,
value and location, and the scanner should be able to return an instance of
that type. Something like
if (input.front.isNumber)
{
import std.conv : parse;
return parser.Symbol (TokenKind.NUM, input.parse!int);
}
** Token Constructors
In the previous example it is possible to mix incorrectly kinds and values,
and for instance:
return parser.Symbol (TokenKind.NUM, "Hello, World!\n");
attaches a string value to NUM kind (wrong, of course). When
api.token.constructor is set, in C++, Bison generated "token constructors":
parser.make_NUM. parser.make_PLUS, parser.make_STRING, etc. The previous
example becomes
return parser.make_NUM ("Hello, World!\n");
which would easily be caught by the type checker.
** Lookahead Correction
Add support for LAC to the D skeleton. It should not be too hard: look how
this is done in lalr1.cc, and mock it.
** Push Parser
Add support for push parser. Do not start a nice skeleton, just enhance the
current one to support push parsers. This is going to be a tougher nut to
crack.
First, you need to understand well how the push parser is expected to work.
To this end:
- read the doc
- look at examples/c/pushcalc
- create an example of a Java push parser.
- have a look at the generated parser in Java, which has the advantage of
being already based on a parser object, instead of just a function.
The C case is harder to read, but it may help too. Keep in mind that
because there's no object to maintain state, the C push parser uses some
struct (yypstate) to preserve this state. We don't need this in D, the
parser object will suffice.
I think working directly on the skeleton to add push-parser support is not
the simplest path. I suggest that you (1) transform a generated parser into
a push parser by hand, and then (2) transform lalr1.d to generate such a
parser.
Use `git commit` frequently to make sure you keep track of your progress.
*** (1.a) Prepare pull parser by hand
Copy again one of the D examples into say examples/d/pushcalc. Also
check-in the generated parser to facilitate experimentation.
- find local variables of yyparse should become members of the parser object
(so that we preserve state from one call to the next).
- do it in your generated D parser. We don't need an equivalent for
yypstate, because we already have it: that the parser object itself.
- have your *pull*-parser (i.e., the good old yy::parser::parse()) work
properly this way. Write and run tests. That's one of the reasons I
suggest using examples/d/calc as a starting point: it already has tests,
you can/should add more.
At this point you have a pull-parser which you prepared to turn into a
push-parser.
*** (1.b) Turn pull parser into push parser by hand
- look again at how push parsers are implemented in Java/C to see what needs
to change in yyparse so that the control is inverted: parse() will
be *given* the tokens, instead of having to call yylex itself. When I say
"look at C", I think your best option are (i) yacc.c (look for b4_push_if)
and (ii) examples/c/pushcalc.
- rename parse() as push_parse(Symbol yyla) (or push_parse(TokenKind, Value,
Location)) that takes the symbol as argument. That's the push parser we
are looking for.
- define a new parse() function which has the same signature as the usual
pull-parser, that repeatedly calls the push_parse function. Something
like this:
int parse ()
{
int status = 0;
do {
status = this->push_parse (yylex());
} while (status == YYPUSH_MORE);
return status;
}
- show me that parser, so that we can validate the approach.
*** (2) Port that into the skeleton
- once we agree on the API of the push parser, implement it into lalr1.d.
You will probaby need help on this regard, but imitation, again, should
help.
- have example/d/pushcalc work properly and pass tests
- add tests in the "real" test suite. Do that in tests/calc.at. I can
help.
- document
** GLR Parser
This is very ambitious. That's the final boss. There are currently no
"clean" implementation to get inspiration from.
glr.c is very clean but:
- is low-level C
- is a different skeleton from yacc.c
glr.cc is (currently) an ugly hack: a C++ shell around glr.c. Valentin
Tolmer is currently rewriting glr.cc to be clean C++, but he is not
finished. There will be a lot a common code between lalr1.cc and glr.cc, so
eventually I would like them to be fused into a single skeleton, supporting
both deterministic and generalized parsing.
It would be great for D to also support this.
The basic ideas of GLR are explained here:
https://www.codeproject.com/Articles/5259825/GLR-Parsing-in-Csharp-How-to-Use-The-Most-Powerful
* Better error messages * Better error messages
The users are not provided with enough tools to forge their error messages. The users are not provided with enough tools to forge their error messages.
See for instance "Is there an option to change the message produced by See for instance "Is there an option to change the message produced by
@@ -233,7 +496,7 @@ and older C++ compilers. Currently the code defaults to defining it to
define it to the same type as the C ptrdiff_t type. define it to the same type as the C ptrdiff_t type.
* Completion * Completion
Several features are not available in all the backends. Several features are not available in all the back-ends.
- lac: D, Java (easy) - lac: D, Java (easy)
- push parsers: glr.c, glr.cc, lalr1.cc (not very difficult) - push parsers: glr.c, glr.cc, lalr1.cc (not very difficult)
@@ -303,7 +566,7 @@ opposite side we have some use of \l, which is graphviz-specific, in what
should be generic code. should be generic code.
Little effort seems to have been given to factoring these files and their Little effort seems to have been given to factoring these files and their
rint{,-xml} counterpart. We would very much like to re-use the pretty format print{,-xml} counterpart. We would very much like to re-use the pretty format
of states from .output for the graphs, etc. of states from .output for the graphs, etc.
Since graphviz dies on medium-to-big grammars, maybe consider an other tool? Since graphviz dies on medium-to-big grammars, maybe consider an other tool?
@@ -581,14 +844,39 @@ to bison. If you're interested, I'll work on a patch.
Equip the parser with a means to create the (visual) parse tree. Equip the parser with a means to create the (visual) parse tree.
-----
# LocalWords: Cex gnulib gl Bistromathic TokenKinds yylex enum YYEOF EOF
# LocalWords: YYerror gettext af hb YYERRCODE undef calc FIXME dev yyerror
# LocalWords: Autoconf YYUNDEFTOK lexemes parsers Bistromathic's yyreport
# LocalWords: const argc yacc yyclearin lookahead destructor Rici incluent
# LocalWords: yydestruct yydiscardin catégories d'avertissements sr activé
# LocalWords: conflits défaut rr l'alias chaîne n'est attaché un symbole
# LocalWords: obsolète règle vide midrule valeurs de intermédiaire ou avec
# LocalWords: définies inutilisées priorité associativité inutiles POSIX
# LocalWords: incompatibilités tous les autres avertissements sauf dans rp
# LocalWords: désactiver CATEGORIE traiter comme des erreurs glr Akim bool
# LocalWords: Demaille arith lalr goto struct pathlen nullable ntokens lr
# LocalWords: nterm bitsetv ielr ritem nstates nrules nritems yysymbol EQ
# LocalWords: SymbolKind YYEMPTY YYUNDEF YYTNAME NUM yyntokens yytname sed
# LocalWords: nonterminals yykind yycode YYNAMES yynames init getName conv
# LocalWords: TokenKind semanticVal ival yychar yylval yylexer Tolmer hoc
# LocalWords: Sobisch YYPTRDIFF ptrdiff Autotest YYPRINT toknum yytoknum
# LocalWords: sym Wother stderr FP fixits xgettext fdiagnostics Graphviz
# LocalWords: graphviz VCG bitset xml bw maint yytoken YYABORT deps
# LocalWords: YYACCEPT yytranslate nonnegative destructors yyerrlab repo
# LocalWords: backends stmt expr yy Mardle baz qux Vadim Maslow CPP cpp
# LocalWords: yydebug gcc UCHAR EBCDIC gung PDP NUL Pre Florian Krohm utf
# LocalWords: YYACT YYLLOC YYLSP yyval yyvsp yylen yyloc yylsp endif
# LocalWords: ispell american
Local Variables: Local Variables:
mode: outline mode: outline
coding: utf-8 coding: utf-8
fill-column: 76 fill-column: 76
ispell-dictionary: "american"
End: End:
-----
Copyright (C) 2001-2004, 2006, 2008-2015, 2018-2020 Free Software Copyright (C) 2001-2004, 2006, 2008-2015, 2018-2020 Free Software
Foundation, Inc. Foundation, Inc.
+3 -1
View File
@@ -44,7 +44,9 @@ gnulib_modules='
realloc-posix realloc-posix
relocatable-prog relocatable-script relocatable-prog relocatable-script
rename rename
spawn-pipe stdbool stpcpy strdup-posix strerror strverscmp spawn-pipe stdbool stpcpy stpncpy strdup-posix strerror strverscmp
sys_ioctl
termios
timevar timevar
unicodeio unistd unistd-safer unlink unlocked-io unicodeio unistd unistd-safer unlink unlocked-io
update-copyright unsetenv verify update-copyright unsetenv verify
+2 -1
View File
@@ -126,7 +126,7 @@ _sed_rm_comments_q = $(subst ','\'',$(_sed_remove_comments))
_space_before_paren_exempt =? \\n\\$$ _space_before_paren_exempt =? \\n\\$$
_space_before_paren_exempt = \ _space_before_paren_exempt = \
(^ *\#|(LA)?LR\([01]\)|percent_(code|define)|b4_syncline|m4_(define|init)|symbol) (^ *\#|(LA)?LR\([01]\)|percent_(code|define)|b4_syncline|m4_(define|init))
# Ensure that there is a space before each open parenthesis in C code. # Ensure that there is a space before each open parenthesis in C code.
sc_space_before_open_paren: sc_space_before_open_paren:
@if $(VC_LIST_EXCEPT) | grep -l '\.[ch]$$' > /dev/null; then \ @if $(VC_LIST_EXCEPT) | grep -l '\.[ch]$$' > /dev/null; then \
@@ -156,6 +156,7 @@ exclude = \
$(call exclude, \ $(call exclude, \
bindtextdomain=^lib/main.c$$ \ bindtextdomain=^lib/main.c$$ \
cast_of_argument_to_free=^src/muscle-tab.c$$ \ cast_of_argument_to_free=^src/muscle-tab.c$$ \
error_message_uppercase=etc/bench.pl.in$$ \
po_check=^tests|(^po/POTFILES.in|.md)$$ \ po_check=^tests|(^po/POTFILES.in|.md)$$ \
preprocessor_indentation=^data/|^lib/|^src/parse-gram.[ch]$$ \ preprocessor_indentation=^data/|^lib/|^src/parse-gram.[ch]$$ \
program_name=^lib/main.c$$ \ program_name=^lib/main.c$$ \
+3
View File
@@ -60,6 +60,9 @@ AC_PROG_CXX
# Gnulib (early checks). # Gnulib (early checks).
gl_EARLY gl_EARLY
# We want ostream_printf and hyperlink support.
gl_LIBTEXTSTYLE_OPTIONAL([0.20.5])
# Gnulib uses '#pragma GCC diagnostic push' to silence some # Gnulib uses '#pragma GCC diagnostic push' to silence some
# warnings, but older gcc doesn't support this. # warnings, but older gcc doesn't support this.
AC_CACHE_CHECK([whether pragma GCC diagnostic push works], AC_CACHE_CHECK([whether pragma GCC diagnostic push works],
+3 -3
View File
@@ -86,7 +86,7 @@ The macro `b4_symbol(NUM, FIELD)` gives access to the following FIELDS:
- `has_id`: 0 or 1 - `has_id`: 0 or 1
Whether the symbol has an `id`. Whether the symbol has an `id`.
- `id`: string - `id`: string (e.g., `exp`, `NUM`, or `TOK_NUM` with api.token.prefix)
If `has_id`, the name of the token kind (prefixed by api.token.prefix if If `has_id`, the name of the token kind (prefixed by api.token.prefix if
defined), otherwise empty. Guaranteed to be usable as a C identifier. defined), otherwise empty. Guaranteed to be usable as a C identifier.
This is used to define the token kind (i.e., the enum used by the return This is used to define the token kind (i.e., the enum used by the return
@@ -105,9 +105,9 @@ The macro `b4_symbol(NUM, FIELD)` gives access to the following FIELDS:
- `is_token`: 0 or 1 - `is_token`: 0 or 1
Whether this is a terminal symbol. Whether this is a terminal symbol.
- `kind_base`: string - `kind_base`: string (e.g., `YYSYMBOL_exp`, `YYSYMBOL_NUM`)
The base of the symbol kind, i.e., the enumerator of this symbol (token or The base of the symbol kind, i.e., the enumerator of this symbol (token or
nonterminal) which is mapping to its `number`. nonterminal) which is mapped to its `number`.
- `kind`: string - `kind`: string
Same as `kind_base`, but possibly with a prefix in some languages. E.g., Same as `kind_base`, but possibly with a prefix in some languages. E.g.,
+4
View File
@@ -49,6 +49,10 @@
.cex-5 { color: orange; } .cex-5 { color: orange; }
.cex-6 { color: brown; } .cex-6 { color: brown; }
.cex-7 { color: mauve; } .cex-7 { color: mauve; }
.cex-8 { color: #013220; } /* Dark green. */
.cex-9 { color: #e75480; } /* Dark pink. */
.cex-10 { color: cyan; }
.cex-11 { color: orange; }
/* Cex: derivation rewriting steps. */ /* Cex: derivation rewriting steps. */
.cex-step { font-style: italic; } .cex-step { font-style: italic; }
+4 -4
View File
@@ -49,7 +49,7 @@ m4_define([m4_shift4], [m4_shift(m4_shift(m4_shift(m4_shift($@))))])
# b4_generated_by # b4_generated_by
# --------------- # ---------------
m4_define([b4_generated_by], m4_define([b4_generated_by],
[b4_comment([A Bison parser, made by GNU Bison b4_version.]) [b4_comment([A Bison parser, made by GNU Bison b4_version_string.])
]) ])
# b4_copyright(TITLE, [YEARS]) # b4_copyright(TITLE, [YEARS])
@@ -633,11 +633,11 @@ m4_define([_b4_type_action],
])]) ])])
# b4_type_foreach(MACRO) # b4_type_foreach(MACRO, [SEP])
# ---------------------- # -----------------------------
# Invoke MACRO(SYMBOL-NUMS) for each set of SYMBOL-NUMS for each type set. # Invoke MACRO(SYMBOL-NUMS) for each set of SYMBOL-NUMS for each type set.
m4_define([b4_type_foreach], m4_define([b4_type_foreach],
[m4_map([$1], m4_defn([b4_type_names]))]) [m4_map_sep([$1], [$2], m4_defn([b4_type_names]))])
+6 -4
View File
@@ -321,8 +321,9 @@ m4_define([b4_symbol_type_define],
/// Copy constructor. /// Copy constructor.
basic_symbol (const basic_symbol& that);]b4_variant_if([[ basic_symbol (const basic_symbol& that);]b4_variant_if([[
/// Constructor for valueless symbols, and symbols from each type. /// Constructors for typed symbols.
]b4_type_foreach([b4_basic_symbol_constructor_define])], [[ ]b4_type_foreach([b4_basic_symbol_constructor_define], [
])], [[
/// Constructor for valueless symbols. /// Constructor for valueless symbols.
basic_symbol (typename Base::kind_type t]b4_locations_if([, basic_symbol (typename Base::kind_type t]b4_locations_if([,
YY_MOVE_REF (location_type) l])[); YY_MOVE_REF (location_type) l])[);
@@ -594,11 +595,12 @@ m4_define([b4_yytranslate_define],
{ {
]b4_translate[ ]b4_translate[
}; };
const int code_max_ = ]b4_code_max[; // Last valid token kind.
const int code_max = ]b4_code_max[;
if (t <= 0) if (t <= 0)
return symbol_kind::]b4_symbol_prefix[YYEOF; return symbol_kind::]b4_symbol_prefix[YYEOF;
else if (t <= code_max_) else if (t <= code_max)
return YY_CAST (symbol_kind_type, translate_table[t]); return YY_CAST (symbol_kind_type, translate_table[t]);
else else
return symbol_kind::]b4_symbol_prefix[YYUNDEF;]])[ return symbol_kind::]b4_symbol_prefix[YYUNDEF;]])[
+8 -7
View File
@@ -58,11 +58,11 @@ m4_define([b4_cpp_guard_close],
# b4_pull_flag if they use the values of the %define variables api.pure or # b4_pull_flag if they use the values of the %define variables api.pure or
# api.push-pull. # api.push-pull.
m4_define([b4_identification], m4_define([b4_identification],
[[/* Identify Bison output. */ [[/* Identify Bison output, and Bison version. */
#define YYBISON 1 #define YYBISON ]b4_version[
/* Bison version. */ /* Bison version string. */
#define YYBISON_VERSION "]b4_version[" #define YYBISON_VERSION "]b4_version_string["
/* Skeleton name. */ /* Skeleton name. */
#define YYSKELETON_NAME ]b4_skeleton[]m4_ifdef([b4_pure_flag], [[ #define YYSKELETON_NAME ]b4_skeleton[]m4_ifdef([b4_pure_flag], [[
@@ -509,10 +509,11 @@ m4_define([b4_token_define],
# ---------------- # ----------------
# Output the definition of the tokens. # Output the definition of the tokens.
m4_define([b4_token_defines], m4_define([b4_token_defines],
[b4_any_token_visible_if([/* Token kinds. */ [[/* Token kinds. */
m4_join([ #define ]b4_symbol([-2], [id])[ -2
]m4_join([
], b4_symbol_map([b4_token_define])) ], b4_symbol_map([b4_token_define]))
])]) ])
# b4_token_enum(TOKEN-NUM) # b4_token_enum(TOKEN-NUM)
+4 -4
View File
@@ -103,12 +103,12 @@ m4_define([b4_location_type_if],
# b4_identification # b4_identification
# ----------------- # -----------------
m4_define([b4_identification], m4_define([b4_identification],
[/** Version number for the Bison executable that generated this parser. */ [[/** Version number for the Bison executable that generated this parser. */
public static immutable string yy_bison_version = "b4_version"; public static immutable string yy_bison_version = "]b4_version_string[";
/** Name of the skeleton that generated this parser. */ /** Name of the skeleton that generated this parser. */
public static immutable string yy_bison_skeleton = b4_skeleton; public static immutable string yy_bison_skeleton = ]b4_skeleton[;
]) ]])
## ------------ ## ## ------------ ##
+1 -1
View File
@@ -333,7 +333,7 @@ static YYLTYPE yyloc_default][]b4_yyloc_default;])[
accessed by $0, $-1, etc., in any rule. */ accessed by $0, $-1, etc., in any rule. */
#define YYMAXLEFT ]b4_max_left_semantic_context[ #define YYMAXLEFT ]b4_max_left_semantic_context[
/* YYMAXUTOK -- Last valid token number (for yychar). */ /* YYMAXUTOK -- Last valid token kind. */
#define YYMAXUTOK ]b4_code_max[ #define YYMAXUTOK ]b4_code_max[
/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM /* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM
+1 -1
View File
@@ -172,7 +172,7 @@ m4_pushdef([b4_parse_param], m4_defn([b4_parse_param_orig]))dnl
const location_type* yylocationp]])[) const const location_type* yylocationp]])[) const
{ {
*yycdebug_ << (yykind < YYNTOKENS ? "token" : "nterm") *yycdebug_ << (yykind < YYNTOKENS ? "token" : "nterm")
<< ' ' << yytname[yykind] << " ("]b4_locations_if([[ << ' ' << yysymbol_name (yykind) << " ("]b4_locations_if([[
<< *yylocationp << ": "]])[; << *yylocationp << ": "]])[;
yy_symbol_value_print_ (yykind, yyvaluep]b4_locations_if([[, yylocationp]])[); yy_symbol_value_print_ (yykind, yyvaluep]b4_locations_if([[, yylocationp]])[);
*yycdebug_ << ')'; *yycdebug_ << ')';
+4 -4
View File
@@ -71,12 +71,12 @@ m4_define([b4_lexer_if],
# b4_identification # b4_identification
# ----------------- # -----------------
m4_define([b4_identification], m4_define([b4_identification],
[ /** Version number for the Bison executable that generated this parser. */ [[ /** Version number for the Bison executable that generated this parser. */
public static final String bisonVersion = "b4_version"; public static final String bisonVersion = "]b4_version_string[";
/** Name of the skeleton that generated this parser. */ /** Name of the skeleton that generated this parser. */
public static final String bisonSkeleton = b4_skeleton; public static final String bisonSkeleton = ]b4_skeleton[;
]) ]])
## ------------ ## ## ------------ ##
+5 -3
View File
@@ -428,8 +428,9 @@ b4_locations_if([, ref ]b4_location_type[ yylocationp])[)
*/ */
public bool parse () public bool parse ()
{ {
/// Lookahead and lookahead in internal form. // Lookahead token kind.
int yychar = TokenKind.YYEMPTY; int yychar = TokenKind.YYEMPTY;
// Lookahead symbol kind.
SymbolKind yytoken = ]b4_symbol(-2, kind)[; SymbolKind yytoken = ]b4_symbol(-2, kind)[;
/* State. */ /* State. */
@@ -841,11 +842,12 @@ m4_popdef([b4_at_dollar])])dnl
]b4_translate[ ]b4_translate[
@}; @};
immutable int code_max_ = ]b4_code_max[; // Last valid token kind.
immutable int code_max = ]b4_code_max[;
if (t <= 0) if (t <= 0)
return ]b4_symbol(0, kind)[; return ]b4_symbol(0, kind)[;
else if (t <= code_max_) else if (t <= code_max)
{ {
import std.conv : to; import std.conv : to;
return to!SymbolKind (translate_table[t]); return to!SymbolKind (translate_table[t]);
+6 -4
View File
@@ -53,8 +53,9 @@ b4_use_push_for_pull_if([
# allows them to be defined either in parse() when doing pull parsing, # allows them to be defined either in parse() when doing pull parsing,
# or as class instance variable when doing push parsing. # or as class instance variable when doing push parsing.
m4_define([b4_define_state],[[ m4_define([b4_define_state],[[
/* Lookahead and lookahead in internal form. */ /* Lookahead token kind. */
int yychar = YYEMPTY_; int yychar = YYEMPTY_;
/* Lookahead symbol kind. */
SymbolKind yytoken = null; SymbolKind yytoken = null;
/* State. */ /* State. */
@@ -1078,17 +1079,18 @@ b4_dollar_popdef[]dnl
/* YYTRANSLATE_(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM /* YYTRANSLATE_(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM
as returned by yylex, with out-of-bounds checking. */ as returned by yylex, with out-of-bounds checking. */
private static final SymbolKind yytranslate_ (int t) private static final SymbolKind yytranslate_(int t)
]b4_api_token_raw_if(dnl ]b4_api_token_raw_if(dnl
[[ { [[ {
return SymbolKind.get(t); return SymbolKind.get(t);
} }
]], ]],
[[ { [[ {
int code_max_ = ]b4_code_max[; // Last valid token kind.
int code_max = ]b4_code_max[;
if (t <= 0) if (t <= 0)
return ]b4_symbol(0, kind)[; return ]b4_symbol(0, kind)[;
else if (t <= code_max_) else if (t <= code_max)
return SymbolKind.get(yytranslate_table_[t]); return SymbolKind.get(yytranslate_table_[t]);
else else
return ]b4_symbol(2, kind)[; return ]b4_symbol(2, kind)[;
+1 -1
View File
@@ -22,7 +22,7 @@ m4_pushdef([b4_copyright_years],
# b4_position_file # b4_position_file
# ---------------- # ----------------
# Name of the file containing the position class, if we want this file. # Name of the file containing the position class, if we want this file.
b4_defines_if([b4_required_version_if([302], [], b4_defines_if([b4_required_version_if([30200], [],
[m4_define([b4_position_file], [position.hh])])])]) [m4_define([b4_position_file], [position.hh])])])])
+1 -1
View File
@@ -19,7 +19,7 @@
# b4_stack_file # b4_stack_file
# ------------- # -------------
# Name of the file containing the stack class, if we want this file. # Name of the file containing the stack class, if we want this file.
b4_defines_if([b4_required_version_if([302], [], b4_defines_if([b4_required_version_if([30200], [],
[m4_define([b4_stack_file], [stack.hh])])]) [m4_define([b4_stack_file], [stack.hh])])])
+101 -41
View File
@@ -20,6 +20,13 @@
## variant. ## ## variant. ##
## --------- ## ## --------- ##
# b4_assert
# ---------
# The name of YY_ASSERT.
m4_define([b4_assert],
[b4_api_PREFIX[]_ASSERT])
# b4_symbol_variant(YYTYPE, YYVAL, ACTION, [ARGS]) # b4_symbol_variant(YYTYPE, YYVAL, ACTION, [ARGS])
# ------------------------------------------------ # ------------------------------------------------
# Run some ACTION ("build", or "destroy") on YYVAL of symbol type # Run some ACTION ("build", or "destroy") on YYVAL of symbol type
@@ -71,12 +78,12 @@ m4_map([ b4_symbol_tag_comment], [$@])dnl
# ------------------- # -------------------
# The needed includes for variants support. # The needed includes for variants support.
m4_define([b4_variant_includes], m4_define([b4_variant_includes],
[b4_parse_assert_if([[#include <typeinfo>]])[ [b4_parse_assert_if([[#include <typeinfo>
#ifndef YY_ASSERT #ifndef ]b4_assert[
# include <cassert> # include <cassert>
# define YY_ASSERT assert # define ]b4_assert[ assert
#endif #endif
]]) ]])])
@@ -110,8 +117,8 @@ m4_define([b4_value_type_declare],
template <typename T> template <typename T>
semantic_type (YY_RVREF (T) t)]b4_parse_assert_if([ semantic_type (YY_RVREF (T) t)]b4_parse_assert_if([
: yytypeid_ (&typeid (T))])[ : yytypeid_ (&typeid (T))])[
{ {]b4_parse_assert_if([[
YY_ASSERT (sizeof (T) <= size); ]b4_assert[ (sizeof (T) <= size);]])[
new (yyas_<T> ()) T (YY_MOVE (t)); new (yyas_<T> ()) T (YY_MOVE (t));
} }
@@ -125,7 +132,7 @@ m4_define([b4_value_type_declare],
/// Destruction, allowed only if empty. /// Destruction, allowed only if empty.
~semantic_type () YY_NOEXCEPT ~semantic_type () YY_NOEXCEPT
{]b4_parse_assert_if([ {]b4_parse_assert_if([
YY_ASSERT (!yytypeid_); ]b4_assert[ (!yytypeid_);
])[} ])[}
# if 201103L <= YY_CPLUSPLUS # if 201103L <= YY_CPLUSPLUS
@@ -133,10 +140,10 @@ m4_define([b4_value_type_declare],
template <typename T, typename... U> template <typename T, typename... U>
T& T&
emplace (U&&... u) emplace (U&&... u)
{]b4_parse_assert_if([ {]b4_parse_assert_if([[
YY_ASSERT (!yytypeid_); ]b4_assert[ (!yytypeid_);
YY_ASSERT (sizeof (T) <= size); ]b4_assert[ (sizeof (T) <= size);
yytypeid_ = & typeid (T);])[ yytypeid_ = & typeid (T);]])[
return *new (yyas_<T> ()) T (std::forward <U>(u)...); return *new (yyas_<T> ()) T (std::forward <U>(u)...);
} }
# else # else
@@ -144,10 +151,10 @@ m4_define([b4_value_type_declare],
template <typename T> template <typename T>
T& T&
emplace () emplace ()
{]b4_parse_assert_if([ {]b4_parse_assert_if([[
YY_ASSERT (!yytypeid_); ]b4_assert[ (!yytypeid_);
YY_ASSERT (sizeof (T) <= size); ]b4_assert[ (sizeof (T) <= size);
yytypeid_ = & typeid (T);])[ yytypeid_ = & typeid (T);]])[
return *new (yyas_<T> ()) T (); return *new (yyas_<T> ()) T ();
} }
@@ -155,10 +162,10 @@ m4_define([b4_value_type_declare],
template <typename T> template <typename T>
T& T&
emplace (const T& t) emplace (const T& t)
{]b4_parse_assert_if([ {]b4_parse_assert_if([[
YY_ASSERT (!yytypeid_); ]b4_assert[ (!yytypeid_);
YY_ASSERT (sizeof (T) <= size); ]b4_assert[ (sizeof (T) <= size);
yytypeid_ = & typeid (T);])[ yytypeid_ = & typeid (T);]])[
return *new (yyas_<T> ()) T (t); return *new (yyas_<T> ()) T (t);
} }
# endif # endif
@@ -185,10 +192,10 @@ m4_define([b4_value_type_declare],
template <typename T> template <typename T>
T& T&
as () YY_NOEXCEPT as () YY_NOEXCEPT
{]b4_parse_assert_if([ {]b4_parse_assert_if([[
YY_ASSERT (yytypeid_); ]b4_assert[ (yytypeid_);
YY_ASSERT (*yytypeid_ == typeid (T)); ]b4_assert[ (*yytypeid_ == typeid (T));
YY_ASSERT (sizeof (T) <= size);])[ ]b4_assert[ (sizeof (T) <= size);]])[
return *yyas_<T> (); return *yyas_<T> ();
} }
@@ -196,10 +203,10 @@ m4_define([b4_value_type_declare],
template <typename T> template <typename T>
const T& const T&
as () const YY_NOEXCEPT as () const YY_NOEXCEPT
{]b4_parse_assert_if([ {]b4_parse_assert_if([[
YY_ASSERT (yytypeid_); ]b4_assert[ (yytypeid_);
YY_ASSERT (*yytypeid_ == typeid (T)); ]b4_assert[ (*yytypeid_ == typeid (T));
YY_ASSERT (sizeof (T) <= size);])[ ]b4_assert[ (sizeof (T) <= size);]])[
return *yyas_<T> (); return *yyas_<T> ();
} }
@@ -214,9 +221,9 @@ m4_define([b4_value_type_declare],
template <typename T> template <typename T>
void void
swap (self_type& that) YY_NOEXCEPT swap (self_type& that) YY_NOEXCEPT
{]b4_parse_assert_if([ {]b4_parse_assert_if([[
YY_ASSERT (yytypeid_); ]b4_assert[ (yytypeid_);
YY_ASSERT (*yytypeid_ == *that.yytypeid_);])[ ]b4_assert[ (*yytypeid_ == *that.yytypeid_);]])[
std::swap (as<T> (), that.as<T> ()); std::swap (as<T> (), that.as<T> ());
} }
@@ -388,11 +395,67 @@ m4_define([_b4_token_maker_define],
])]) ])])
m4_define([_b4_type_clause], # b4_token_kind(SYMBOL-NUM)
[b4_symbol_if([$1], [is_token], # -------------------------
[b4_symbol_if([$1], [has_id], # Some tokens don't have an ID.
[tok == token::b4_symbol([$1], [id])], m4_define([b4_token_kind],
[tok == b4_symbol([$1], [code])])])]) [b4_symbol_if([$1], [has_id],
[token::b4_symbol([$1], [id])],
[b4_symbol([$1], [code])])])
# _b4_tok_in(SYMBOL-NUM, ...)
# ---------------------------
# See b4_tok_in below. The SYMBOL-NUMs... are tokens only.
#
# We iterate over the tokens to group them by "range" of token numbers (not
# symbols numbers!).
#
# b4_fst is the start of that range.
# b4_prev is the previous value.
# b4_val is the current value.
# If b4_val is the successor of b4_prev in token numbers, update the latter,
# otherwise emit the code for range b4_fst .. b4_prev.
# $1 is also used as a terminator in the foreach, but it will not be printed.
#
m4_define([_b4_tok_in],
[m4_pushdef([b4_prev], [$1])dnl
m4_pushdef([b4_fst], [$1])dnl
m4_pushdef([b4_sep], [])dnl
m4_foreach([b4_val], m4_dquote(m4_shift($@, $1)),
[m4_if(b4_symbol(b4_val, [code]), m4_eval(b4_symbol(b4_prev, [code]) + 1), [],
[b4_sep[]m4_if(b4_fst, b4_prev,
[tok == b4_token_kind(b4_fst)],
[(b4_token_kind(b4_fst) <= tok && tok <= b4_token_kind(b4_prev))])[]dnl
m4_define([b4_fst], b4_val)dnl
m4_define([b4_sep], [
|| ])])dnl
m4_define([b4_prev], b4_val)])dnl
m4_popdef([b4_sep])dnl
m4_popdef([b4_fst])dnl
m4_popdef([b4_prev])dnl
])
# _b4_filter_tokens(SYMBOL-NUM, ...)
# ----------------------------------
# Expand as the list of tokens amongst SYMBOL-NUM.
m4_define([_b4_filter_tokens],
[m4_pushdef([b4_sep])dnl
m4_foreach([b4_val], [$@],
[b4_symbol_if(b4_val, [is_token], [b4_sep[]b4_val[]m4_define([b4_sep], [,])])])dnl
m4_popdef([b4_sep])dnl
])
# b4_tok_in(SYMBOL-NUM, ...)
# ---------------------------
# A C++ conditional that checks that `tok` is a member of this list of symbol
# numbers.
m4_define([b4_tok_in],
[_$0(_b4_filter_tokens($@))])
# _b4_token_constructor_define(SYMBOL-NUM...) # _b4_token_constructor_define(SYMBOL-NUM...)
@@ -410,9 +473,6 @@ m4_define([_b4_token_constructor_define],
: super_type(]b4_join([token_type (tok)], : super_type(]b4_join([token_type (tok)],
b4_symbol_if([$1], [has_type], [std::move (v)]), b4_symbol_if([$1], [has_type], [std::move (v)]),
b4_locations_if([std::move (l)]))[) b4_locations_if([std::move (l)]))[)
{
YY_ASSERT (]m4_join([ || ], m4_map_sep([_b4_type_clause], [, ], [$@]))[);
}
#else #else
symbol_type (]b4_join( symbol_type (]b4_join(
[int tok], [int tok],
@@ -422,10 +482,10 @@ m4_define([_b4_token_constructor_define],
: super_type(]b4_join([token_type (tok)], : super_type(]b4_join([token_type (tok)],
b4_symbol_if([$1], [has_type], [v]), b4_symbol_if([$1], [has_type], [v]),
b4_locations_if([l]))[) b4_locations_if([l]))[)
{
YY_ASSERT (]m4_join([ || ], m4_map_sep([_b4_type_clause], [, ], [$@]))[);
}
#endif #endif
{]b4_parse_assert_if([[
]b4_assert[ (]b4_tok_in($@)[);
]])[}
]])]) ]])])
+9 -4
View File
@@ -48,6 +48,10 @@ m4_define([b4_pure_if],
## api.push-pull. ## ## api.push-pull. ##
## --------------- ## ## --------------- ##
# b4_pull_if, b4_push_if
# ----------------------
# Whether the pull/push APIs are needed. Both can be enabled.
b4_percent_define_default([[api.push-pull]], [[pull]]) b4_percent_define_default([[api.push-pull]], [[pull]])
b4_percent_define_check_values([[[[api.push-pull]], b4_percent_define_check_values([[[[api.push-pull]],
[[pull]], [[push]], [[both]]]]) [[pull]], [[push]], [[both]]]])
@@ -155,7 +159,7 @@ m4_define([b4_rhs_location],
# Declare the variables that are global, or local to YYPARSE if # Declare the variables that are global, or local to YYPARSE if
# pure-parser. # pure-parser.
m4_define([b4_declare_scanner_communication_variables], [[ m4_define([b4_declare_scanner_communication_variables], [[
/* The lookahead symbol. */ /* Lookahead token kind. */
int yychar; int yychar;
]b4_pure_if([[ ]b4_pure_if([[
@@ -571,6 +575,7 @@ union yyalloc
/* YYNSTATES -- Number of states. */ /* YYNSTATES -- Number of states. */
#define YYNSTATES ]b4_states_number[ #define YYNSTATES ]b4_states_number[
/* YYMAXUTOK -- Last valid token kind. */
#define YYMAXUTOK ]b4_code_max[ #define YYMAXUTOK ]b4_code_max[
@@ -1481,7 +1486,7 @@ yypstate_new (void)
yypstate *yyps;]b4_pure_if([], [[ yypstate *yyps;]b4_pure_if([], [[
if (yypstate_allocated) if (yypstate_allocated)
return YY_NULLPTR;]])[ return YY_NULLPTR;]])[
yyps = YY_CAST (yypstate *, malloc (sizeof *yyps)); yyps = YY_CAST (yypstate *, YYMALLOC (sizeof *yyps));
if (!yyps) if (!yyps)
return YY_NULLPTR;]b4_pure_if([], [[ return YY_NULLPTR;]b4_pure_if([], [[
yypstate_allocated = 1;]])[ yypstate_allocated = 1;]])[
@@ -1510,7 +1515,7 @@ yypstate_delete (yypstate *yyps)
#endif]b4_lac_if([[ #endif]b4_lac_if([[
if (yyes != yyesa) if (yyes != yyesa)
YYSTACK_FREE (yyes);]])[ YYSTACK_FREE (yyes);]])[
free (yyps);]b4_pure_if([], [[ YYFREE (yyps);]b4_pure_if([], [[
yypstate_allocated = 0;]])[ yypstate_allocated = 0;]])[
} }
} }
@@ -1544,7 +1549,7 @@ yyparse (]m4_ifset([b4_parse_param], [b4_formals(b4_parse_param)], [void])[)]])[
int yyn; int yyn;
/* The return value of yyparse. */ /* The return value of yyparse. */
int yyresult; int yyresult;
/* Lookahead token as an internal (translated) token number. */ /* Lookahead symbol kind. */
yysymbol_kind_t yytoken = ]b4_symbol(-2, kind)[; yysymbol_kind_t yytoken = ]b4_symbol(-2, kind)[;
/* The variables used to return semantic value and location from the /* The variables used to return semantic value and location from the
action routines. */ action routines. */
+14 -6
View File
@@ -52,7 +52,7 @@
<xsl:if test="nonterminal[@usefulness='useless-in-grammar']"> <xsl:if test="nonterminal[@usefulness='useless-in-grammar']">
<xsl:text>Nonterminals useless in grammar&#10;&#10;</xsl:text> <xsl:text>Nonterminals useless in grammar&#10;&#10;</xsl:text>
<xsl:for-each select="nonterminal[@usefulness='useless-in-grammar']"> <xsl:for-each select="nonterminal[@usefulness='useless-in-grammar']">
<xsl:text> </xsl:text> <xsl:text> </xsl:text>
<xsl:value-of select="@name"/> <xsl:value-of select="@name"/>
<xsl:text>&#10;</xsl:text> <xsl:text>&#10;</xsl:text>
</xsl:for-each> </xsl:for-each>
@@ -65,7 +65,7 @@
<xsl:text>Terminals unused in grammar&#10;&#10;</xsl:text> <xsl:text>Terminals unused in grammar&#10;&#10;</xsl:text>
<xsl:for-each select="terminal[@usefulness='unused-in-grammar']"> <xsl:for-each select="terminal[@usefulness='unused-in-grammar']">
<xsl:sort select="@symbol-number" data-type="number"/> <xsl:sort select="@symbol-number" data-type="number"/>
<xsl:text> </xsl:text> <xsl:text> </xsl:text>
<xsl:value-of select="@name"/> <xsl:value-of select="@name"/>
<xsl:text>&#10;</xsl:text> <xsl:text>&#10;</xsl:text>
</xsl:for-each> </xsl:for-each>
@@ -136,6 +136,7 @@
</xsl:template> </xsl:template>
<xsl:template match="terminal"> <xsl:template match="terminal">
<xsl:text> </xsl:text>
<xsl:value-of select="@name"/> <xsl:value-of select="@name"/>
<xsl:call-template name="line-wrap"> <xsl:call-template name="line-wrap">
<xsl:with-param name="first-line-length"> <xsl:with-param name="first-line-length">
@@ -148,6 +149,9 @@
</xsl:with-param> </xsl:with-param>
<xsl:with-param name="line-length" select="66" /> <xsl:with-param name="line-length" select="66" />
<xsl:with-param name="text"> <xsl:with-param name="text">
<xsl:if test="string-length(@type) != 0">
<xsl:value-of select="concat(' &lt;', @type, '&gt;')"/>
</xsl:if>
<xsl:value-of select="concat(' (', @token-number, ')')"/> <xsl:value-of select="concat(' (', @token-number, ')')"/>
<xsl:for-each select="key('bison:ruleByRhs', @name)"> <xsl:for-each select="key('bison:ruleByRhs', @name)">
<xsl:value-of select="concat(' ', @number)"/> <xsl:value-of select="concat(' ', @number)"/>
@@ -157,14 +161,18 @@
</xsl:template> </xsl:template>
<xsl:template match="nonterminal"> <xsl:template match="nonterminal">
<xsl:text> </xsl:text>
<xsl:value-of select="@name"/> <xsl:value-of select="@name"/>
<xsl:if test="string-length(@type) != 0">
<xsl:value-of select="concat(' &lt;', @type, '&gt;')"/>
</xsl:if>
<xsl:value-of select="concat(' (', @symbol-number, ')')"/> <xsl:value-of select="concat(' (', @symbol-number, ')')"/>
<xsl:text>&#10;</xsl:text> <xsl:text>&#10;</xsl:text>
<xsl:variable name="output"> <xsl:variable name="output">
<xsl:call-template name="line-wrap"> <xsl:call-template name="line-wrap">
<xsl:with-param name="line-length" select="66" /> <xsl:with-param name="line-length" select="66" />
<xsl:with-param name="text"> <xsl:with-param name="text">
<xsl:text> </xsl:text> <xsl:text> </xsl:text>
<xsl:if test="key('bison:ruleByLhs', @name)"> <xsl:if test="key('bison:ruleByLhs', @name)">
<xsl:text>on@left:</xsl:text> <xsl:text>on@left:</xsl:text>
<xsl:for-each select="key('bison:ruleByLhs', @name)"> <xsl:for-each select="key('bison:ruleByLhs', @name)">
@@ -173,7 +181,7 @@
</xsl:if> </xsl:if>
<xsl:if test="key('bison:ruleByRhs', @name)"> <xsl:if test="key('bison:ruleByRhs', @name)">
<xsl:if test="key('bison:ruleByLhs', @name)"> <xsl:if test="key('bison:ruleByLhs', @name)">
<xsl:text>, </xsl:text> <xsl:text>&#10; </xsl:text>
</xsl:if> </xsl:if>
<xsl:text>on@right:</xsl:text> <xsl:text>on@right:</xsl:text>
<xsl:for-each select="key('bison:ruleByRhs', @name)"> <xsl:for-each select="key('bison:ruleByRhs', @name)">
@@ -348,11 +356,11 @@
<!-- RHS --> <!-- RHS -->
<xsl:for-each select="rhs/*"> <xsl:for-each select="rhs/*">
<xsl:if test="position() = $dot + 1"> <xsl:if test="position() = $dot + 1">
<xsl:text> .</xsl:text> <xsl:text> </xsl:text>
</xsl:if> </xsl:if>
<xsl:apply-templates select="."/> <xsl:apply-templates select="."/>
<xsl:if test="position() = last() and position() = $dot"> <xsl:if test="position() = last() and position() = $dot">
<xsl:text> .</xsl:text> <xsl:text> </xsl:text>
</xsl:if> </xsl:if>
</xsl:for-each> </xsl:for-each>
<xsl:if test="$lookaheads"> <xsl:if test="$lookaheads">
+72 -48
View File
@@ -227,6 +227,7 @@
<xsl:text>&#10;</xsl:text> <xsl:text>&#10;</xsl:text>
<p class="pre"> <p class="pre">
<xsl:call-template name="style-rule-set"> <xsl:call-template name="style-rule-set">
<xsl:with-param name="anchor" select="'true'" />
<xsl:with-param <xsl:with-param
name="rule-set" select="rules/rule[@usefulness!='useless-in-grammar']" name="rule-set" select="rules/rule[@usefulness!='useless-in-grammar']"
/> />
@@ -238,9 +239,11 @@
</xsl:template> </xsl:template>
<xsl:template name="style-rule-set"> <xsl:template name="style-rule-set">
<xsl:param name="anchor"/>
<xsl:param name="rule-set"/> <xsl:param name="rule-set"/>
<xsl:for-each select="$rule-set"> <xsl:for-each select="$rule-set">
<xsl:apply-templates select="."> <xsl:apply-templates select=".">
<xsl:with-param name="anchor" select="$anchor"/>
<xsl:with-param name="pad" select="'3'"/> <xsl:with-param name="pad" select="'3'"/>
<xsl:with-param name="prev-lhs"> <xsl:with-param name="prev-lhs">
<xsl:if test="position()>1"> <xsl:if test="position()>1">
@@ -306,9 +309,10 @@
<xsl:text> Terminals, with rules where they appear</xsl:text> <xsl:text> Terminals, with rules where they appear</xsl:text>
</h3> </h3>
<xsl:text>&#10;&#10;</xsl:text> <xsl:text>&#10;&#10;</xsl:text>
<p class="pre"> <ul>
<xsl:text>&#10;</xsl:text>
<xsl:apply-templates select="terminal"/> <xsl:apply-templates select="terminal"/>
</p> </ul>
<xsl:text>&#10;&#10;</xsl:text> <xsl:text>&#10;&#10;</xsl:text>
</xsl:template> </xsl:template>
@@ -318,41 +322,64 @@
<xsl:text> Nonterminals, with rules where they appear</xsl:text> <xsl:text> Nonterminals, with rules where they appear</xsl:text>
</h3> </h3>
<xsl:text>&#10;&#10;</xsl:text> <xsl:text>&#10;&#10;</xsl:text>
<p class="pre"> <ul>
<xsl:text>&#10;</xsl:text>
<xsl:apply-templates <xsl:apply-templates
select="nonterminal[@usefulness!='useless-in-grammar']" select="nonterminal[@usefulness!='useless-in-grammar']"
/> />
</p> </ul>
</xsl:template> </xsl:template>
<xsl:template match="terminal"> <xsl:template match="terminal">
<b><xsl:value-of select="@name"/></b> <xsl:text> </xsl:text>
<xsl:value-of select="concat(' (', @token-number, ')')"/> <li>
<xsl:for-each select="key('bison:ruleByRhs', @name)"> <b><xsl:value-of select="@name"/></b>
<xsl:apply-templates select="." mode="number-link"/> <xsl:if test="string-length(@type) != 0">
</xsl:for-each> <xsl:value-of select="concat(' &lt;', @type, '&gt;')"/>
</xsl:if>
<xsl:value-of select="concat(' (', @token-number, ')')"/>
<xsl:for-each select="key('bison:ruleByRhs', @name)">
<xsl:apply-templates select="." mode="number-link"/>
</xsl:for-each>
</li>
<xsl:text>&#10;</xsl:text> <xsl:text>&#10;</xsl:text>
</xsl:template> </xsl:template>
<xsl:template match="nonterminal"> <xsl:template match="nonterminal">
<b><xsl:value-of select="@name"/></b> <xsl:text> </xsl:text>
<xsl:value-of select="concat(' (', @symbol-number, ')')"/> <li>
<xsl:text>&#10; </xsl:text> <b><xsl:value-of select="@name"/></b>
<xsl:if test="key('bison:ruleByLhs', @name)"> <xsl:if test="string-length(@type) != 0">
<xsl:text>on left:</xsl:text> <xsl:value-of select="concat(' &lt;', @type, '&gt;')"/>
<xsl:for-each select="key('bison:ruleByLhs', @name)">
<xsl:apply-templates select="." mode="number-link"/>
</xsl:for-each>
</xsl:if>
<xsl:if test="key('bison:ruleByRhs', @name)">
<xsl:if test="key('bison:ruleByLhs', @name)">
<xsl:text>&#10; </xsl:text>
</xsl:if> </xsl:if>
<xsl:text>on right:</xsl:text> <xsl:value-of select="concat(' (', @symbol-number, ')')"/>
<xsl:for-each select="key('bison:ruleByRhs', @name)"> <xsl:text>&#10; </xsl:text>
<xsl:apply-templates select="." mode="number-link"/> <ul>
</xsl:for-each> <xsl:text>&#10;</xsl:text>
</xsl:if> <xsl:if test="key('bison:ruleByLhs', @name)">
<xsl:text> </xsl:text>
<li>
<xsl:text>on left:</xsl:text>
<xsl:for-each select="key('bison:ruleByLhs', @name)">
<xsl:apply-templates select="." mode="number-link"/>
</xsl:for-each>
</li>
<xsl:text>&#10;</xsl:text>
</xsl:if>
<xsl:if test="key('bison:ruleByRhs', @name)">
<xsl:text> </xsl:text>
<li>
<xsl:text>on right:</xsl:text>
<xsl:for-each select="key('bison:ruleByRhs', @name)">
<xsl:apply-templates select="." mode="number-link"/>
</xsl:for-each>
</li>
<xsl:text>&#10;</xsl:text>
</xsl:if>
<xsl:text> </xsl:text>
</ul>
<xsl:text>&#10; </xsl:text>
</li>
<xsl:text>&#10;</xsl:text> <xsl:text>&#10;</xsl:text>
</xsl:template> </xsl:template>
@@ -385,7 +412,7 @@
<xsl:value-of select="concat('state_', @number)"/> <xsl:value-of select="concat('state_', @number)"/>
</xsl:attribute> </xsl:attribute>
</a> </a>
<xsl:text>state </xsl:text> <xsl:text>State </xsl:text>
<xsl:value-of select="@number"/> <xsl:value-of select="@number"/>
</h3> </h3>
<xsl:text>&#10;&#10;</xsl:text> <xsl:text>&#10;&#10;</xsl:text>
@@ -464,7 +491,12 @@
</xsl:apply-templates> </xsl:apply-templates>
</xsl:template> </xsl:template>
<!--
anchor = 'true': define as an <a> anchor.
itemset = 'true': show the items.
-->
<xsl:template match="rule"> <xsl:template match="rule">
<xsl:param name="anchor"/>
<xsl:param name="itemset"/> <xsl:param name="itemset"/>
<xsl:param name="pad"/> <xsl:param name="pad"/>
<xsl:param name="prev-lhs"/> <xsl:param name="prev-lhs"/>
@@ -475,17 +507,21 @@
<xsl:text>&#10;</xsl:text> <xsl:text>&#10;</xsl:text>
</xsl:if> </xsl:if>
<xsl:if test="$itemset != 'true'">
<a>
<xsl:attribute name="name">
<xsl:value-of select="concat('rule_', @number)"/>
</xsl:attribute>
</a>
</xsl:if>
<xsl:text> </xsl:text> <xsl:text> </xsl:text>
<xsl:choose> <xsl:choose>
<xsl:when test="$itemset = 'true'"> <xsl:when test="$anchor = 'true'">
<a>
<xsl:attribute name="name">
<xsl:value-of select="concat('rule_', @number)"/>
</xsl:attribute>
<xsl:call-template name="lpad">
<xsl:with-param name="str" select="string(@number)"/>
<xsl:with-param name="pad" select="number($pad)"/>
</xsl:call-template>
</a>
</xsl:when>
<xsl:otherwise>
<a> <a>
<xsl:attribute name="href"> <xsl:attribute name="href">
<xsl:value-of select="concat('#rule_', @number)"/> <xsl:value-of select="concat('#rule_', @number)"/>
@@ -495,25 +531,13 @@
<xsl:with-param name="pad" select="number($pad)"/> <xsl:with-param name="pad" select="number($pad)"/>
</xsl:call-template> </xsl:call-template>
</a> </a>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="lpad">
<xsl:with-param name="str" select="string(@number)"/>
<xsl:with-param name="pad" select="number($pad)"/>
</xsl:call-template>
</xsl:otherwise> </xsl:otherwise>
</xsl:choose> </xsl:choose>
<xsl:text> </xsl:text> <xsl:text> </xsl:text>
<!-- LHS --> <!-- LHS -->
<xsl:choose> <xsl:choose>
<xsl:when test="$itemset != 'true' and $prev-lhs = lhs[text()]"> <xsl:when test="$prev-lhs = lhs[text()]">
<xsl:call-template name="lpad">
<xsl:with-param name="str" select="'|'"/>
<xsl:with-param name="pad" select="number(string-length(lhs[text()])) + 2"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="$itemset = 'true' and $prev-lhs = lhs[text()]">
<xsl:call-template name="lpad"> <xsl:call-template name="lpad">
<xsl:with-param name="str" select="'|'"/> <xsl:with-param name="str" select="'|'"/>
<xsl:with-param name="pad" select="number(string-length(lhs[text()])) + 2"/> <xsl:with-param name="pad" select="number(string-length(lhs[text()])) + 2"/>
+548 -156
View File
File diff suppressed because it is too large Load Diff
+23
View File
@@ -0,0 +1,23 @@
%union
{
int ival;
const char *sval;
}
%token <ival> NUM
%nterm <ival> exp
%token <sval> STR
%nterm <sval> useless
%left '+' '-'
%left '*'
%%
exp:
exp '+' exp
| exp '-' exp
| exp '*' exp
| exp '/' exp
| NUM
;
useless: STR;
+5
View File
@@ -0,0 +1,5 @@
%token ID
%%
s: a ID
a: expr
expr: %empty | expr ID ','
+13
View File
@@ -0,0 +1,13 @@
%%
stmt:
expr
| if_stmt
;
if_stmt:
"if" expr "then" stmt
| "if" expr "then" stmt "else" stmt
;
expr:
"identifier"
+1 -1
View File
@@ -57,7 +57,7 @@ MAINTAINERCLEANFILES = $(CROSS_OPTIONS_TEXI)
# Fix Info's @code in @deftype # Fix Info's @code in @deftype
# https://lists.gnu.org/archive/html/help-texinfo/2019-11/msg00004.html # https://lists.gnu.org/archive/html/help-texinfo/2019-11/msg00004.html
all: $(srcdir)/$(%C%_bison).info.bak all-local: $(srcdir)/$(%C%_bison).info.bak
$(srcdir)/$(%C%_bison).info.bak: $(srcdir)/$(%C%_bison).info $(srcdir)/$(%C%_bison).info.bak: $(srcdir)/$(%C%_bison).info
$(AM_V_GEN) $(PERL) -pi.bak -0777 \ $(AM_V_GEN) $(PERL) -pi.bak -0777 \
-e 's{(^ --.*\n(?: {10}.*\n)*)}' \ -e 's{(^ --.*\n(?: {10}.*\n)*)}' \
+10
View File
@@ -0,0 +1,10 @@
%%
sequence:
%empty
| maybeword
| sequence "word"
;
maybeword:
%empty
| "word"
;
+41 -29
View File
@@ -185,13 +185,13 @@ my $verbose = 1;
=over 4 =over 4
=item C<verbose($level, $message)> =item C<verbose ($level, $message)>
Report the C<$message> is C<$level> E<lt>= C<$verbose>. Report the C<$message> is C<$level> E<lt>= C<$verbose>.
=cut =cut
sub verbose($$) sub verbose ($$)
{ {
my ($level, $message) = @_; my ($level, $message) = @_;
print STDERR $message print STDERR $message
@@ -201,13 +201,13 @@ sub verbose($$)
###################################################################### ######################################################################
=item C<directives($bench, @directive)> =item C<directives ($bench, @directive)>
Format the list of directives for Bison for bench named C<$bench>. Format the list of directives for Bison for bench named C<$bench>.
=cut =cut
sub directives($@) sub directives ($@)
{ {
my ($bench, @directive) = @_; my ($bench, @directive) = @_;
my $res = "/* Directives for bench '$bench'. */\n"; my $res = "/* Directives for bench '$bench'. */\n";
@@ -218,6 +218,27 @@ sub directives($@)
###################################################################### ######################################################################
=item C<is_pure (@directive)>
Whether api.pure is set.
=cut
sub is_pure (@)
{
my (@directive) = @_;
for my $dir (@directive)
{
if ($dir =~ /\A%define api.pure/)
{
return 1;
}
}
return 0;
}
######################################################################
=item C<generate_grammar_triangular ($base, $max, @directive)> =item C<generate_grammar_triangular ($base, $max, @directive)>
Create a large triangular grammar which looks like : Create a large triangular grammar which looks like :
@@ -389,18 +410,14 @@ sub generate_grammar_calc ($$@)
%define api.value.type union %define api.value.type union
$directives $directives
%{ %code provides {
static int power (int base, int exponent); static int power (int base, int exponent);
/* yyerror receives the location if: /* yyerror receives the location if:
- %location & %pure & %glr - %location & %pure & %glr
- %location & %pure & %yacc & %parse-param. */ - %location & %pure & %yacc & %parse-param. */
static void yyerror (const char *s); static void yyerror (const char *s);
#if YYPURE static int yylex (@{[is_pure (@directive) ? "YYSTYPE *yylvalp" : "void"]});
static int yylex (YYSTYPE* yylvalp); }
#else
static int yylex (void);
#endif
%}
/* Bison Declarations */ /* Bison Declarations */
%token %token
@@ -467,12 +484,7 @@ yyerror (const char *s)
} }
static int static int
#if YYPURE yylex (@{[is_pure (@directive) ? "YYSTYPE *yylvalp" : "void"]})
# define yylval (*yylvalp)
yylex (YYSTYPE* yylvalp)
#else
yylex (void)
#endif
{ {
int c; int c;
@@ -498,7 +510,7 @@ yylex (void)
case '5': case '6': case '7': case '8': case '9': case '5': case '6': case '7': case '8': case '9':
{ {
int nchars = 0; int nchars = 0;
int n = sscanf (input - 1, "%d%n", &yylval.NUM, &nchars); int n = sscanf (input - 1, "%d%n", &@{[is_pure (@directive) ? "yylvalp->" : "yylval."]}NUM, &nchars);
assert (n == 1); assert (n == 1);
input += nchars - 1; input += nchars - 1;
return NUM; return NUM;
@@ -506,7 +518,7 @@ yylex (void)
default: default:
yyerror ("error: invalid character"); yyerror ("error: invalid character");
return yylex (); return yylex (@{[is_pure (@directive) ? "yylvalp" : ""]});
} }
} }
EOF EOF
@@ -592,10 +604,10 @@ $directives
// Prototype of the yylex function providing subsequent tokens. // Prototype of the yylex function providing subsequent tokens.
static static
#if USE_TOKEN_CTOR #if USE_TOKEN_CTOR
yy::parser::symbol_type yylex(); yy::parser::symbol_type yylex ();
#else #else
yy::parser::token_type yylex(yy::parser::semantic_type* yylvalp, yy::parser::token_type yylex (yy::parser::semantic_type *yylvalp,
yy::parser::location_type* yyllocp); yy::parser::location_type *yyllocp);
#endif #endif
// Conversion to string. // Conversion to string.
@@ -618,8 +630,8 @@ EOF
print $out <<'EOF'; print $out <<'EOF';
%token <std::string> TEXT %token <std::string> TEXT
%token <int> NUMBER %token <int> NUMBER
%printer { std::cerr << "Number: " << $$; } <int> %printer { yyo << "Number: " << $$; } <int>
%printer { std::cerr << "Text: " << $$; } <std::string> %printer { yyo << "Text: " << $$; } <std::string>
%type <std::string> text result %type <std::string> text result
%% %%
@@ -641,8 +653,8 @@ EOF
%union {int ival; std::string* sval;} %union {int ival; std::string* sval;}
%token <sval> TEXT %token <sval> TEXT
%token <ival> NUMBER %token <ival> NUMBER
%printer { std::cerr << "Number: " << $$; } <ival> %printer { yyo << "Number: " << $$; } <ival>
%printer { std::cerr << "Text: " << *$$; } <sval> %printer { yyo << "Text: " << *$$; } <sval>
%type <sval> text result %type <sval> text result
%% %%
@@ -664,10 +676,10 @@ EOF
static static
#if USE_TOKEN_CTOR #if USE_TOKEN_CTOR
yy::parser::symbol_type yylex() yy::parser::symbol_type yylex ()
#else #else
yy::parser::token_type yylex(yy::parser::semantic_type* yylvalp, yy::parser::token_type yylex (yy::parser::semantic_type *yylvalp,
yy::parser::location_type* yyllocp) yy::parser::location_type *yyllocp)
#endif #endif
{ {
typedef yy::parser::location_type location_type; typedef yy::parser::location_type location_type;
+10 -1
View File
@@ -53,7 +53,9 @@ push-parser model.
This example demonstrates best practices when using Bison. This example demonstrates best practices when using Bison.
- Its hand-written scanner tracks locations. - Its hand-written scanner tracks locations.
- Its interface is pure. - Its interface is pure.
- It uses the `error` token to get error recovery. - It uses %params to pass user information to the parser and scanner.
- Its scanner uses the `error` token to signal lexical errors and enter
error recovery.
- Its interface is "incremental", well suited for interaction: it uses the - Its interface is "incremental", well suited for interaction: it uses the
push-parser API to feed the parser with the incoming tokens. push-parser API to feed the parser with the incoming tokens.
- It features an interactive command line with completion based on the - It features an interactive command line with completion based on the
@@ -62,6 +64,13 @@ This example demonstrates best practices when using Bison.
messages. messages.
- It uses a custom syntax error with location, lookahead correction and - It uses a custom syntax error with location, lookahead correction and
token internationalization. token internationalization.
- Error messages quote the source with squiggles that underline the error:
```
> 123 456
1.5-7: syntax error: expected end of file or + or - or * or / or ^ before number
1 | 123 456
| ^~~
```
- It supports debug traces with semantic values. - It supports debug traces with semantic values.
- It uses named references instead of the traditional $1, $2, etc. - It uses named references instead of the traditional $1, $2, etc.
+10 -1
View File
@@ -2,7 +2,9 @@
This example demonstrates best practices when using Bison. This example demonstrates best practices when using Bison.
- Its hand-written scanner tracks locations. - Its hand-written scanner tracks locations.
- Its interface is pure. - Its interface is pure.
- It uses the `error` token to get error recovery. - It uses %params to pass user information to the parser and scanner.
- Its scanner uses the `error` token to signal lexical errors and enter
error recovery.
- Its interface is "incremental", well suited for interaction: it uses the - Its interface is "incremental", well suited for interaction: it uses the
push-parser API to feed the parser with the incoming tokens. push-parser API to feed the parser with the incoming tokens.
- It features an interactive command line with completion based on the - It features an interactive command line with completion based on the
@@ -11,6 +13,13 @@ This example demonstrates best practices when using Bison.
messages. messages.
- It uses a custom syntax error with location, lookahead correction and - It uses a custom syntax error with location, lookahead correction and
token internationalization. token internationalization.
- Error messages quote the source with squiggles that underline the error:
```
> 123 456
1.5-7: syntax error: expected end of file or + or - or * or / or ^ before number
1 | 123 456
| ^~~
```
- It supports debug traces with semantic values. - It supports debug traces with semantic values.
- It uses named references instead of the traditional $1, $2, etc. - It uses named references instead of the traditional $1, $2, etc.
+50 -19
View File
@@ -101,14 +101,28 @@ cat >input <<EOF
EOF EOF
run 0 '> * run 0 '> *
> '' > ''
err: 1.1: syntax error: expected end of file or - or ( or exit or number or function etc., before *' err: 1.1: syntax error: expected end of file or - or ( or exit or number or function etc., before *
err: 1 | *
err: | ^'
# Underline long errors.
cat >input <<EOF
123 123456
EOF
run 0 '> 123 123456
> ''
err: 1.5-10: syntax error: expected end of file or + or - or * or / or ^ before number
err: 1 | 123 123456
err: | ^~~~~~'
cat >input <<EOF cat >input <<EOF
1 + 2 * * 3 1 + 2 * * 3
EOF EOF
run 0 '> 1 + 2 * * 3 run 0 '> 1 + 2 * * 3
> '' > ''
err: 1.9: syntax error: expected - or ( or number or function or variable before *' err: 1.9: syntax error: expected - or ( or number or function or variable before *
err: 1 | 1 + 2 * * 3
err: | ^'
cat >input <<EOF cat >input <<EOF
1 / 0 1 / 0
@@ -132,8 +146,14 @@ run 0 '> ((1 ++ 2) ** 3)
1332 1332
> '' > ''
err: 1.6: syntax error: expected - or ( or number or function or variable before + err: 1.6: syntax error: expected - or ( or number or function or variable before +
err: 1 | ((1 ++ 2) ** 3)
err: | ^
err: 2.5: syntax error: expected - or ( or number or function or variable before + err: 2.5: syntax error: expected - or ( or number or function or variable before +
err: 2.16: syntax error: expected - or ( or number or function or variable before *' err: 2 | (1 ++ 2) + (3 ** 4)
err: | ^
err: 2.16: syntax error: expected - or ( or number or function or variable before *
err: 2 | (1 ++ 2) + (3 ** 4)
err: | ^'
# The rule "( error )" should work even if there are no tokens between "(" and ")". # The rule "( error )" should work even if there are no tokens between "(" and ")".
cat >input <<EOF cat >input <<EOF
@@ -142,7 +162,9 @@ EOF
run 0 '> () run 0 '> ()
666 666
> '' > ''
err: 1.2: syntax error: expected - or ( or number or function or variable before )' err: 1.2: syntax error: expected - or ( or number or function or variable before )
err: 1 | ()
err: | ^'
cat >input <<EOF cat >input <<EOF
@@ -189,6 +211,8 @@ err: LAC: checking lookahead function: S5
err: LAC: checking lookahead variable: S6 err: LAC: checking lookahead variable: S6
err: LAC: checking lookahead NEG: Err err: LAC: checking lookahead NEG: Err
err: 1.2: syntax error: expected - or ( or number or function or variable before + err: 1.2: syntax error: expected - or ( or number or function or variable before +
err: 1 | (+_)
err: | ^
err: LAC: initial context discarded due to error recovery err: LAC: initial context discarded due to error recovery
err: Shifting token error (1.2: ) err: Shifting token error (1.2: )
err: Entering state 10 err: Entering state 10
@@ -227,29 +251,29 @@ err: Next token is token ) (1.4: )
err: Shifting token ) (1.4: ) err: Shifting token ) (1.4: )
err: Entering state 20 err: Entering state 20
err: Stack now 0 2 10 20 err: Stack now 0 2 10 20
err: Reducing stack by rule 15 (line 151): err: Reducing stack by rule XX (line XXX):
err: $1 = token ( (1.1: ) err: $1 = token ( (1.1: )
err: $2 = token error (1.2-3: ) err: $2 = token error (1.2-3: )
err: $3 = token ) (1.4: ) err: $3 = token ) (1.4: )
err: -> $$ = nterm exp (1.1-4: 666) err: -> $$ = nterm exp (1.1-4: 666)
err: Entering state 7 err: Entering state 8
err: Stack now 0 7 err: Stack now 0 8
err: Return for a new token: err: Return for a new token:
err: Reading a token err: Reading a token
err: Now at end of input. err: Now at end of input.
err: LAC: initial context established for end of file err: LAC: initial context established for end of file
err: LAC: checking lookahead end of file: R2 G8 S19 err: LAC: checking lookahead end of file: R2 G7 S14
err: Reducing stack by rule 2 (line 126): err: Reducing stack by rule XX (line XXX):
err: $1 = nterm exp (1.1-4: 666) err: $1 = nterm exp (1.1-4: 666)
err: -> $$ = nterm input (1.1-4: ) err: -> $$ = nterm input (1.1-4: )
err: Entering state 8 err: Entering state 7
err: Stack now 0 8 err: Stack now 0 7
err: Now at end of input. err: Now at end of input.
err: Shifting token end of file (1.5: ) err: Shifting token end of file (1.5: )
err: LAC: initial context discarded due to shift err: LAC: initial context discarded due to shift
err: Entering state 19 err: Entering state 14
err: Stack now 0 8 19 err: Stack now 0 7 14
err: Stack now 0 8 19 err: Stack now 0 7 14
err: Cleanup: popping token end of file (1.5: ) err: Cleanup: popping token end of file (1.5: )
err: Cleanup: popping nterm input (1.1-4: )' -p err: Cleanup: popping nterm input (1.1-4: )' -p
@@ -286,7 +310,9 @@ run 0 '> (1+
( - atan cos exp ln number sin sqrt ( - atan cos exp ln number sin sqrt
> (1+ > (1+
> '' > ''
err: 1.4: syntax error: expected - or ( or number or function or variable before end of file' err: 1.4: syntax error: expected - or ( or number or function or variable before end of file
err: 1 | (1+
err: | ^'
# Check the completion of a word. # Check the completion of a word.
sed -e 's/\\t/ /g' >input <<EOF sed -e 's/\\t/ /g' >input <<EOF
@@ -294,7 +320,9 @@ sed -e 's/\\t/ /g' >input <<EOF
EOF EOF
run 0 '> (atan ( '' run 0 '> (atan ( ''
> '' > ''
err: 1.9: syntax error: expected - or ( or number or function or variable before end of file' err: 1.9: syntax error: expected - or ( or number or function or variable before end of file
err: 1 | (atan ( ''
err: | ^'
# Check the completion at the very beginning. # Check the completion at the very beginning.
sed -e 's/\\t/ /g' >input <<EOF sed -e 's/\\t/ /g' >input <<EOF
@@ -313,8 +341,9 @@ sed -e 's/\\t/ /g' >input <<EOF
EOF EOF
run -n 0 '> 1++ '' run -n 0 '> 1++ ''
> '' > ''
err: 1.1: syntax error: expected - or ( or number or function or variable before +
err: 1.3: syntax error: expected - or ( or number or function or variable before + err: 1.3: syntax error: expected - or ( or number or function or variable before +
err: 1 | 1++ ''
err: | ^
' '
# And even when the error was recovered from. # And even when the error was recovered from.
@@ -323,8 +352,10 @@ sed -e 's/\\t/ /g' >input <<EOF
EOF EOF
run -n 0 '> (1++2) + 3 + '' run -n 0 '> (1++2) + 3 + ''
> '' > ''
err: 1.1: syntax error: expected - or ( or number or function or variable before +
err: 1.1: syntax error: expected - or ( or number or function or variable before +
err: 1.4: syntax error: expected - or ( or number or function or variable before + err: 1.4: syntax error: expected - or ( or number or function or variable before +
err: 1 | (1++2) + 3 + ''
err: | ^
err: 1.15: syntax error: expected - or ( or number or function or variable before end of file err: 1.15: syntax error: expected - or ( or number or function or variable before end of file
err: 1 | (1++2) + 3 + ''
err: | ^
' '
+78 -16
View File
@@ -1,5 +1,25 @@
%require "3.6" /* Parser and scanner for bistromathic. -*- C -*-
Copyright (C) 2019-2020 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
%require "3.7"
// Emitted on top of the implementation file.
%code top { %code top {
#include <ctype.h> // isdigit #include <ctype.h> // isdigit
#include <locale.h> // LC_ALL #include <locale.h> // LC_ALL
@@ -24,6 +44,7 @@
#endif #endif
} }
// Emitted in the header file, before the definition of YYSTYPE.
%code requires { %code requires {
// Function type. // Function type.
typedef double (func_t) (double); typedef double (func_t) (double);
@@ -44,19 +65,34 @@
symrec *putsym (char const *name, int sym_type); symrec *putsym (char const *name, int sym_type);
symrec *getsym (char const *name); symrec *getsym (char const *name);
// Exchanging information with the parser.
typedef struct
{
// Whether to not emit error messages.
int silent;
// The current input line.
const char *line;
} user_context;
} }
// Emitted in the header file, after the definition of YYSTYPE.
%code provides { %code provides {
# ifndef __attribute__ # ifndef __attribute__
# ifndef __GNUC__ # ifndef __GNUC__
# define __attribute__(Spec) /* empty */ # define __attribute__(Spec) /* empty */
# endif # endif
# endif # endif
int yylex (const char **line, YYSTYPE *yylval, YYLTYPE *yylloc);
void yyerror (YYLTYPE *loc, char const *format, ...) yytoken_kind_t
__attribute__ ((__format__ (__printf__, 2, 3))); yylex (const char **line, YYSTYPE *yylval, YYLTYPE *yylloc,
const user_context *uctx);
void yyerror (YYLTYPE *loc, const user_context *uctx,
char const *format, ...)
__attribute__ ((__format__ (__printf__, 3, 4)));
} }
// Emitted in the implementation file.
%code { %code {
#if defined ENABLE_NLS && ENABLE_NLS #if defined ENABLE_NLS && ENABLE_NLS
# define _(Msgid) gettext (Msgid) # define _(Msgid) gettext (Msgid)
@@ -68,6 +104,9 @@
int done = 0; int done = 0;
} }
// Include the header in the implementation rather than duplicating it.
%define api.header.include {"parse.h"}
// Don't share global variables between the scanner and the parser. // Don't share global variables between the scanner and the parser.
%define api.pure full %define api.pure full
@@ -90,6 +129,9 @@
// Generate the parser description file (calc.output). // Generate the parser description file (calc.output).
%verbose %verbose
// User information exchanged with the parser and scanner.
%param {const user_context *uctx}
// Generate YYSTYPE from the types assigned to symbols. // Generate YYSTYPE from the types assigned to symbols.
%define api.value.type union %define api.value.type union
%token %token
@@ -145,7 +187,7 @@ exp:
{ {
if ($r == 0) if ($r == 0)
{ {
yyerror (&@$, "error: division by zero"); yyerror (&@$, uctx, "error: division by zero");
YYERROR; YYERROR;
} }
else else
@@ -231,8 +273,9 @@ symbol_count (void)
| Scanner. | | Scanner. |
`----------*/ `----------*/
int yytoken_kind_t
yylex (const char **line, YYSTYPE *yylval, YYLTYPE *yylloc) yylex (const char **line, YYSTYPE *yylval, YYLTYPE *yylloc,
const user_context *uctx)
{ {
int c; int c;
@@ -302,7 +345,7 @@ yylex (const char **line, YYSTYPE *yylval, YYLTYPE *yylloc)
// Stray characters. // Stray characters.
default: default:
yyerror (yylloc, "syntax error: invalid character: %c", c); yyerror (yylloc, uctx, "syntax error: invalid character: %c", c);
return TOK_YYerror; return TOK_YYerror;
} }
} }
@@ -340,8 +383,11 @@ error_format_string (int argc)
int int
yyreport_syntax_error (const yypcontext_t *ctx) yyreport_syntax_error (const yypcontext_t *ctx, const user_context *uctx)
{ {
if (uctx->silent)
return 0;
enum { ARGS_MAX = 6 }; enum { ARGS_MAX = 6 };
yysymbol_kind_t arg[ARGS_MAX]; yysymbol_kind_t arg[ARGS_MAX];
int argsize = yypcontext_expected_tokens (ctx, arg, ARGS_MAX); int argsize = yypcontext_expected_tokens (ctx, arg, ARGS_MAX);
@@ -352,11 +398,12 @@ yyreport_syntax_error (const yypcontext_t *ctx)
argsize = ARGS_MAX; argsize = ARGS_MAX;
const char *format = error_format_string (1 + argsize + too_many_expected_tokens); const char *format = error_format_string (1 + argsize + too_many_expected_tokens);
const YYLTYPE *loc = yypcontext_location (ctx);
while (*format) while (*format)
// %@: location. // %@: location.
if (format[0] == '%' && format[1] == '@') if (format[0] == '%' && format[1] == '@')
{ {
YY_LOCATION_PRINT (stderr, *yypcontext_location (ctx)); YY_LOCATION_PRINT (stderr, *loc);
format += 2; format += 2;
} }
// %u: unexpected token. // %u: unexpected token.
@@ -381,13 +428,25 @@ yyreport_syntax_error (const yypcontext_t *ctx)
++format; ++format;
} }
fputc ('\n', stderr); fputc ('\n', stderr);
// Quote the source line.
{
fprintf (stderr, "%5d | %s\n", loc->first_line, uctx->line);
fprintf (stderr, "%5s | %*s", "", loc->first_column, "^");
for (int i = loc->last_column - loc->first_column - 1; 0 < i; --i)
putc ('~', stderr);
putc ('\n', stderr);
}
return 0; return 0;
} }
// Called by yyparse on error. // Called by yyparse on error.
void yyerror (YYLTYPE *loc, char const *format, ...) void yyerror (YYLTYPE *loc, const user_context *uctx, char const *format, ...)
{ {
if (uctx->silent)
return;
YY_LOCATION_PRINT (stderr, *loc); YY_LOCATION_PRINT (stderr, *loc);
fputs (": ", stderr); fputs (": ", stderr);
va_list args; va_list args;
@@ -423,11 +482,13 @@ xstrndup (const char *string, size_t n)
static int static int
process_line (YYLTYPE *lloc, const char *line) process_line (YYLTYPE *lloc, const char *line)
{ {
user_context uctx = {0, line};
yypstate *ps = yypstate_new (); yypstate *ps = yypstate_new ();
int status = 0; int status = 0;
do { do {
YYSTYPE lval; YYSTYPE lval;
status = yypush_parse (ps, yylex (&line, &lval, lloc), &lval, lloc); yytoken_kind_t token = yylex (&line, &lval, lloc, &uctx);
status = yypush_parse (ps, token, &lval, lloc, &uctx);
} while (status == YYPUSH_MORE); } while (status == YYPUSH_MORE);
yypstate_delete (ps); yypstate_delete (ps);
lloc->last_line++; lloc->last_line++;
@@ -442,18 +503,19 @@ expected_tokens (const char *input,
int *tokens, int ntokens) int *tokens, int ntokens)
{ {
YYDPRINTF ((stderr, "expected_tokens (\"%s\")", input)); YYDPRINTF ((stderr, "expected_tokens (\"%s\")", input));
user_context uctx = {1, input};
// Parse the current state of the line. // Parse the current state of the line.
yypstate *ps = yypstate_new (); yypstate *ps = yypstate_new ();
int status = 0; int status = 0;
YYLTYPE lloc = { 1, 1, 1, 1 };
do { do {
YYLTYPE lloc = { 1, 1, 1, 1 };
YYSTYPE lval; YYSTYPE lval;
int token = yylex (&input, &lval, &lloc); yytoken_kind_t token = yylex (&input, &lval, &lloc, &uctx);
// Don't let the parse know when we reach the end of input. // Don't let the parse know when we reach the end of input.
if (!token) if (token == TOK_YYEOF)
break; break;
status = yypush_parse (ps, token, &lval, &lloc); status = yypush_parse (ps, token, &lval, &lloc, &uctx);
} while (status == YYPUSH_MORE); } while (status == YYPUSH_MORE);
int res = 0; int res = 0;
+7
View File
@@ -31,6 +31,13 @@ endif FLEX_WORKS
%D%/parse.c: $(dependencies) %D%/parse.c: $(dependencies)
# Tell Make scan.o depends on parse.h, except that Make sees only
# parse.c, not parse.h. We can't use BUILT_SOURCES to this end, since
# we use the built bison.
%D%/lexcalc$(DASH)scan.o: %D%/parse.c
# Likewise, but for Automake before 1.16.
%D%/examples_c_lexcalc_lexcalc$(DASH)scan.o: %D%/parse.c
EXTRA_DIST += %D%/lexcalc.test EXTRA_DIST += %D%/lexcalc.test
dist_lexcalc_DATA = %D%/parse.y %D%/scan.l %D%/Makefile %D%/README.md dist_lexcalc_DATA = %D%/parse.y %D%/scan.l %D%/Makefile %D%/README.md
CLEANFILES += %D%/parse.[ch] %D%/scan.c %D%/parse.output CLEANFILES += %D%/parse.[ch] %D%/scan.c %D%/parse.output
+22
View File
@@ -1,3 +1,22 @@
/* Parser for lexcalc. -*- C -*-
Copyright (C) 2018-2020 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
// Prologue (directives). // Prologue (directives).
%expect 0 %expect 0
@@ -19,6 +38,9 @@
#include <stdlib.h> // getenv. #include <stdlib.h> // getenv.
} }
// Include the header in the implementation rather than duplicating it.
%define api.header.include {"parse.h"}
// Don't share global variables between the scanner and the parser. // Don't share global variables between the scanner and the parser.
%define api.pure full %define api.pure full
+20 -1
View File
@@ -1,4 +1,23 @@
/* Prologue (directives). -*- C -*- */ /* Scanner for lexcalc. -*- C -*-
Copyright (C) 2018-2020 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* Prologue (directives). */
/* Disable Flex features we don't need, to avoid warnings. */ /* Disable Flex features we don't need, to avoid warnings. */
%option nodefault noinput nounput noyywrap %option nodefault noinput nounput noyywrap
+19
View File
@@ -1,3 +1,22 @@
/* Parser and scanner for pushcalc. -*- C -*-
Copyright (C) 2020 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
%code top { %code top {
#include <ctype.h> /* isdigit. */ #include <ctype.h> /* isdigit. */
#include <stdio.h> /* printf. */ #include <stdio.h> /* printf. */
+36 -2
View File
@@ -1,3 +1,22 @@
/* Parser for reccalc. -*- C -*-
Copyright (C) 2019-2020 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
// Prologue (directives). // Prologue (directives).
%expect 0 %expect 0
@@ -46,14 +65,29 @@
result parse (void); result parse (void);
} }
// Include the header in the implementation rather than duplicating it.
%define api.header.include {"parse.h"}
// Don't share global variables between the scanner and the parser.
%define api.pure full %define api.pure full
// To avoid name clashes (e.g., with C's EOF) prefix token definitions
// with TOK_ (e.g., TOK_EOF).
%define api.token.prefix {TOK_} %define api.token.prefix {TOK_}
// Generate YYSTYPE from the types assigned to symbols.
%define api.value.type union %define api.value.type union
%define parse.error verbose
// Error messages with "unexpected XXX, expected XXX...".
%define parse.error detailed
// Enable run-time traces (yydebug).
%define parse.trace %define parse.trace
// Generate the parser description file (parse.output).
%verbose %verbose
// Scanner and error count are exchanged between main, yyparse and yylex. // Scanner and error count are exchanged between main, yyparse and yylex.
%param {yyscan_t scanner}{result *res} %param {yyscan_t scanner}{result *res}
%token %token
+19
View File
@@ -1,3 +1,22 @@
/* Scanner for reccalc. -*- C -*-
Copyright (C) 2019-2020 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* Prologue (directives). -*- C -*- */ /* Prologue (directives). -*- C -*- */
/* Disable Flex features we don't need, to avoid warnings. */ /* Disable Flex features we don't need, to avoid warnings. */
+19
View File
@@ -1,3 +1,22 @@
/* Parser and scanner for calc in D. -*- D -*-
Copyright (C) 2018-2020 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
%language "D" %language "D"
%define api.parser.class {Calc} %define api.parser.class {Calc}
+1 -1
View File
@@ -27,7 +27,7 @@ EXTRA_DIST += %D%/calc.test
%D%/calc.d: %D%/calc.y $(dependencies) %D%/calc.d: %D%/calc.y $(dependencies)
$(AM_V_GEN)$(MKDIR_P) %D% $(AM_V_GEN)$(MKDIR_P) %D%
$(AM_V_at)$(BISON) $(srcdir)/%D%/calc.y -o $@ $(AM_V_at)$(BISON) -o $@ $(srcdir)/%D%/calc.y
%D%/calc: %D%/calc.d %D%/calc: %D%/calc.d
$(AM_V_GEN) $(DC) $(DCFLAGS) -of$@ %D%/calc.d $(AM_V_GEN) $(DC) $(DCFLAGS) -of$@ %D%/calc.d
+19
View File
@@ -1,3 +1,22 @@
/* Parser and scanner for calc in Java. -*- Java -*-
Copyright (C) 2018-2020 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
%language "Java" %language "Java"
%define api.parser.class {Calc} %define api.parser.class {Calc}
+1 -1
View File
@@ -27,7 +27,7 @@ EXTRA_DIST += %D%/Calc.test
%D%/Calc.java: %D%/Calc.y $(dependencies) %D%/Calc.java: %D%/Calc.y $(dependencies)
$(AM_V_GEN)$(MKDIR_P) %D% $(AM_V_GEN)$(MKDIR_P) %D%
$(AM_V_at)$(BISON) $(srcdir)/%D%/Calc.y -o $@ $(AM_V_at)$(BISON) -o $@ $(srcdir)/%D%/Calc.y
%D%/Calc.class: %D%/Calc.java %D%/Calc.class: %D%/Calc.java
$(AM_V_GEN) $(SHELL) $(top_builddir)/javacomp.sh %D%/Calc.java $(AM_V_GEN) $(SHELL) $(top_builddir)/javacomp.sh %D%/Calc.java
+19
View File
@@ -1,3 +1,22 @@
/* Simple parser and scanner in Java. -*- Java -*-
Copyright (C) 2018-2020 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
%language "Java" %language "Java"
%define api.parser.class {Calc} %define api.parser.class {Calc}
+1 -1
View File
@@ -27,7 +27,7 @@ EXTRA_DIST += %D%/Calc.test
%D%/Calc.java: %D%/Calc.y $(dependencies) %D%/Calc.java: %D%/Calc.y $(dependencies)
$(AM_V_GEN)$(MKDIR_P) %D% $(AM_V_GEN)$(MKDIR_P) %D%
$(AM_V_at)$(BISON) $(srcdir)/%D%/Calc.y -o $@ $(AM_V_at)$(BISON) -o $@ $(srcdir)/%D%/Calc.y
%D%/Calc.class: %D%/Calc.java %D%/Calc.class: %D%/Calc.java
$(AM_V_GEN) $(SHELL) $(top_builddir)/javacomp.sh %D%/Calc.java $(AM_V_GEN) $(SHELL) $(top_builddir)/javacomp.sh %D%/Calc.java
+1 -1
Submodule gnulib updated: 845d69187a...839ed059f4
+5 -2
View File
@@ -20,6 +20,7 @@
/assure.h /assure.h
/attribute.h /attribute.h
/basename-lgpl.c /basename-lgpl.c
/basename-lgpl.h
/basename.c /basename.c
/binary-io.c /binary-io.c
/binary-io.h /binary-io.h
@@ -191,8 +192,6 @@
/localcharset.h /localcharset.h
/locale.h /locale.h
/locale.in.h /locale.in.h
/localtime-buffer.c
/localtime-buffer.h
/lstat.c /lstat.c
/malloc.c /malloc.c
/malloca.c /malloca.c
@@ -312,6 +311,7 @@
/stdlib.h /stdlib.h
/stdlib.in.h /stdlib.in.h
/stpcpy.c /stpcpy.c
/stpncpy.c
/strchrnul.c /strchrnul.c
/strchrnul.valgrind /strchrnul.valgrind
/strdup.c /strdup.c
@@ -336,8 +336,11 @@
/sys_types.in.h /sys_types.in.h
/sys_wait.in.h /sys_wait.in.h
/sysexits.in.h /sysexits.in.h
/termios.h
/termios.in.h
/textstyle.h /textstyle.h
/textstyle.in.h /textstyle.in.h
/thread-optim.h
/time.h /time.h
/time.in.h /time.in.h
/timespec.c /timespec.c
+5 -2
View File
@@ -13,7 +13,6 @@
/codeset.m4 /codeset.m4
/config-h.m4 /config-h.m4
/configmake.m4 /configmake.m4
/dirname.m4
/double-slash-root.m4 /double-slash-root.m4
/dup2.m4 /dup2.m4
/eealloc.m4 /eealloc.m4
@@ -98,7 +97,6 @@
/locale-ja.m4 /locale-ja.m4
/locale-zh.m4 /locale-zh.m4
/locale_h.m4 /locale_h.m4
/localtime-buffer.m4
/lock.m4 /lock.m4
/longlong.m4 /longlong.m4
/lstat.m4 /lstat.m4
@@ -118,6 +116,7 @@
/msvc-inval.m4 /msvc-inval.m4
/msvc-nothrow.m4 /msvc-nothrow.m4
/multiarch.m4 /multiarch.m4
/musl.m4
/nls.m4 /nls.m4
/nocrash.m4 /nocrash.m4
/non-recursive-gnulib-prefix-hack.m4 /non-recursive-gnulib-prefix-hack.m4
@@ -129,6 +128,7 @@
/open.m4 /open.m4
/pathmax.m4 /pathmax.m4
/perror.m4 /perror.m4
/pid_t.m4
/pipe2.m4 /pipe2.m4
/po.m4 /po.m4
/posix_spawn.m4 /posix_spawn.m4
@@ -176,6 +176,7 @@
/stdio_h.m4 /stdio_h.m4
/stdlib_h.m4 /stdlib_h.m4
/stpcpy.m4 /stpcpy.m4
/stpncpy.m4
/strchrnul.m4 /strchrnul.m4
/strdup.m4 /strdup.m4
/strerror.m4 /strerror.m4
@@ -184,6 +185,7 @@
/strndup.m4 /strndup.m4
/strnlen.m4 /strnlen.m4
/strverscmp.m4 /strverscmp.m4
/sys_ioctl_h.m4
/sys_resource_h.m4 /sys_resource_h.m4
/sys_socket_h.m4 /sys_socket_h.m4
/sys_stat_h.m4 /sys_stat_h.m4
@@ -191,6 +193,7 @@
/sys_times_h.m4 /sys_times_h.m4
/sys_types_h.m4 /sys_types_h.m4
/sys_wait_h.m4 /sys_wait_h.m4
/termios_h.m4
/threadlib.m4 /threadlib.m4
/time_h.m4 /time_h.m4
/timespec.m4 /timespec.m4
+5 -5
View File
@@ -169,10 +169,10 @@ AnnotationList__compute_conflicted_tokens (bitset shift_tokens,
bitset_copy (tokens, shift_tokens); bitset_copy (tokens, shift_tokens);
for (int i = 0; i < reds->num; ++i) for (int i = 0; i < reds->num; ++i)
{ {
bitset_and (conflicted_tokens_rule, tokens, reds->lookahead_tokens[i]); bitset_and (conflicted_tokens_rule, tokens, reds->lookaheads[i]);
bitset_or (conflicted_tokens, bitset_or (conflicted_tokens,
conflicted_tokens, conflicted_tokens_rule); conflicted_tokens, conflicted_tokens_rule);
bitset_or (tokens, tokens, reds->lookahead_tokens[i]); bitset_or (tokens, tokens, reds->lookaheads[i]);
/* Check that rules are sorted on rule number or the next step in /* Check that rules are sorted on rule number or the next step in
AnnotationList__compute_from_inadequacies will misbehave. */ AnnotationList__compute_from_inadequacies will misbehave. */
aver (i == 0 || reds->rules[i-1] < reds->rules[i]); aver (i == 0 || reds->rules[i-1] < reds->rules[i]);
@@ -401,7 +401,7 @@ AnnotationList__compute_from_inadequacies (
struct obstack *annotations_obstackp, struct obstack *annotations_obstackp,
InadequacyListNodeCount *inadequacy_list_node_count) InadequacyListNodeCount *inadequacy_list_node_count)
{ {
/* Return an empty list if s->lookahead_tokens = NULL. */ /* Return an empty list if s->lookaheads = NULL. */
if (s->consistent) if (s->consistent)
return; return;
@@ -422,7 +422,7 @@ AnnotationList__compute_from_inadequacies (
/* Allocate the annotation node. */ /* Allocate the annotation node. */
{ {
for (int rule_i = 0; rule_i < s->reductions->num; ++rule_i) for (int rule_i = 0; rule_i < s->reductions->num; ++rule_i)
if (bitset_test (s->reductions->lookahead_tokens[rule_i], if (bitset_test (s->reductions->lookaheads[rule_i],
conflicted_token)) conflicted_token))
++contribution_count; ++contribution_count;
if (bitset_test (shift_tokens, conflicted_token)) if (bitset_test (shift_tokens, conflicted_token))
@@ -445,7 +445,7 @@ AnnotationList__compute_from_inadequacies (
for (int rule_i = 0; rule_i < s->reductions->num; ++rule_i) for (int rule_i = 0; rule_i < s->reductions->num; ++rule_i)
{ {
rule *the_rule = s->reductions->rules[rule_i]; rule *the_rule = s->reductions->rules[rule_i];
if (bitset_test (s->reductions->lookahead_tokens[rule_i], if (bitset_test (s->reductions->lookaheads[rule_i],
conflicted_token)) conflicted_token))
{ {
bitset_set (actions, rule_i); bitset_set (actions, rule_i);
+35 -3
View File
@@ -35,6 +35,13 @@
#include "getargs.h" #include "getargs.h"
#include "quote.h" #include "quote.h"
// The URL of the manual page about diagnostics. Use the per-node
// manual, to avoid downloading repeatedly the whole manual over the
// Internet.
static const char *diagnostics_url
= "https://www.gnu.org/software/bison/manual/html_node/Diagnostics.html";
err_status complaint_status = status_none; err_status complaint_status = status_none;
bool warnings_are_errors = false; bool warnings_are_errors = false;
@@ -96,6 +103,20 @@ end_use_class (const char *s, FILE *out)
} }
} }
static void
begin_hyperlink (FILE *out, const char *ref)
{
if (out == stderr)
styled_ostream_set_hyperlink (errstream, ref, NULL);
}
static void
end_hyperlink (FILE *out)
{
if (out == stderr)
styled_ostream_set_hyperlink (errstream, NULL, NULL);
}
void void
flush (FILE *out) flush (FILE *out)
{ {
@@ -427,9 +448,20 @@ warnings_print_categories (warnings warn_flags, FILE *out)
const char* style = severity_style (s); const char* style = severity_style (s);
fputs (" [", out); fputs (" [", out);
begin_use_class (style, out); begin_use_class (style, out);
fprintf (out, "-W%s%s", // E.g., "counterexamples".
s == severity_error ? "error=" : "", const char *warning = argmatch_warning_argument (&w);
argmatch_warning_argument (&w)); char ref[200];
snprintf (ref, sizeof ref,
"%s#W%s", diagnostics_url, warning);
begin_hyperlink (out, ref);
ostream_printf (errstream,
"-W%s%s",
s == severity_error ? "error=" : "",
warning);
end_hyperlink (out);
// Because we mix stdio with ostream I/O, we need to flush
// here for sake of color == debug.
flush (out);
end_use_class (style, out); end_use_class (style, out);
fputc (']', out); fputc (']', out);
/* Display only the first match, the second is "-Wall". */ /* Display only the first match, the second is "-Wall". */
+29 -25
View File
@@ -250,9 +250,9 @@ flush_shift (state *s, int token)
`--------------------------------------------------------------------*/ `--------------------------------------------------------------------*/
static void static void
flush_reduce (bitset lookahead_tokens, int token) flush_reduce (bitset lookaheads, int token)
{ {
bitset_reset (lookahead_tokens, token); bitset_reset (lookaheads, token);
} }
@@ -275,10 +275,10 @@ resolve_sr_conflict (state *s, int ruleno, symbol **errors, int *nerrs)
/* Find the rule to reduce by to get precedence of reduction. */ /* Find the rule to reduce by to get precedence of reduction. */
rule *redrule = reds->rules[ruleno]; rule *redrule = reds->rules[ruleno];
int redprec = redrule->prec->prec; int redprec = redrule->prec->prec;
bitset lookahead_tokens = reds->lookahead_tokens[ruleno]; bitset lookaheads = reds->lookaheads[ruleno];
for (symbol_number i = 0; i < ntokens; ++i) for (symbol_number i = 0; i < ntokens; ++i)
if (bitset_test (lookahead_tokens, i) if (bitset_test (lookaheads, i)
&& bitset_test (lookahead_set, i) && bitset_test (lookahead_set, i)
&& symbols[i]->content->prec) && symbols[i]->content->prec)
{ {
@@ -295,7 +295,7 @@ resolve_sr_conflict (state *s, int ruleno, symbol **errors, int *nerrs)
{ {
register_precedence (i, redrule->prec->number); register_precedence (i, redrule->prec->number);
log_resolution (redrule, i, shift_resolution); log_resolution (redrule, i, shift_resolution);
flush_reduce (lookahead_tokens, i); flush_reduce (lookaheads, i);
} }
else else
/* Matching precedence levels. /* Matching precedence levels.
@@ -316,7 +316,7 @@ resolve_sr_conflict (state *s, int ruleno, symbol **errors, int *nerrs)
case right_assoc: case right_assoc:
register_assoc (i, redrule->prec->number); register_assoc (i, redrule->prec->number);
log_resolution (redrule, i, right_resolution); log_resolution (redrule, i, right_resolution);
flush_reduce (lookahead_tokens, i); flush_reduce (lookaheads, i);
break; break;
case left_assoc: case left_assoc:
@@ -329,7 +329,7 @@ resolve_sr_conflict (state *s, int ruleno, symbol **errors, int *nerrs)
register_assoc (i, redrule->prec->number); register_assoc (i, redrule->prec->number);
log_resolution (redrule, i, nonassoc_resolution); log_resolution (redrule, i, nonassoc_resolution);
flush_shift (s, i); flush_shift (s, i);
flush_reduce (lookahead_tokens, i); flush_reduce (lookaheads, i);
/* Record an explicit error for this token. */ /* Record an explicit error for this token. */
errors[(*nerrs)++] = symbols[i]; errors[(*nerrs)++] = symbols[i];
break; break;
@@ -369,7 +369,7 @@ set_conflicts (state *s, symbol **errors)
for (int i = 0; i < reds->num; ++i) for (int i = 0; i < reds->num; ++i)
if (reds->rules[i]->prec if (reds->rules[i]->prec
&& reds->rules[i]->prec->prec && reds->rules[i]->prec->prec
&& !bitset_disjoint_p (reds->lookahead_tokens[i], lookahead_set)) && !bitset_disjoint_p (reds->lookaheads[i], lookahead_set))
resolve_sr_conflict (s, i, errors, &nerrs); resolve_sr_conflict (s, i, errors, &nerrs);
if (nerrs) if (nerrs)
@@ -385,13 +385,13 @@ set_conflicts (state *s, symbol **errors)
/* Loop over all rules which require lookahead in this state. Check /* Loop over all rules which require lookahead in this state. Check
for conflicts not resolved above. for conflicts not resolved above.
reds->lookahead_tokens can be NULL if the LR type is LR(0). */ reds->lookaheads can be NULL if the LR type is LR(0). */
if (reds->lookahead_tokens) if (reds->lookaheads)
for (int i = 0; i < reds->num; ++i) for (int i = 0; i < reds->num; ++i)
{ {
if (!bitset_disjoint_p (reds->lookahead_tokens[i], lookahead_set)) if (!bitset_disjoint_p (reds->lookaheads[i], lookahead_set))
conflicts[s->number] = true; conflicts[s->number] = true;
bitset_or (lookahead_set, lookahead_set, reds->lookahead_tokens[i]); bitset_or (lookahead_set, lookahead_set, reds->lookaheads[i]);
} }
} }
@@ -460,7 +460,7 @@ count_state_sr_conflicts (const state *s)
} }
for (int i = 0; i < reds->num; ++i) for (int i = 0; i < reds->num; ++i)
bitset_or (lookahead_set, lookahead_set, reds->lookahead_tokens[i]); bitset_or (lookahead_set, lookahead_set, reds->lookaheads[i]);
bitset_and (lookahead_set, lookahead_set, shift_set); bitset_and (lookahead_set, lookahead_set, shift_set);
@@ -499,7 +499,7 @@ count_state_rr_conflicts (const state *s)
{ {
int count = 0; int count = 0;
for (int j = 0; j < reds->num; ++j) for (int j = 0; j < reds->num; ++j)
count += bitset_test (reds->lookahead_tokens[j], i); count += bitset_test (reds->lookaheads[j], i);
if (2 <= count) if (2 <= count)
res += count-1; res += count-1;
} }
@@ -534,7 +534,7 @@ count_rule_state_sr_conflicts (rule *r, state *s)
for (int i = 0; i < reds->num; ++i) for (int i = 0; i < reds->num; ++i)
if (reds->rules[i] == r) if (reds->rules[i] == r)
{ {
bitset lookaheads = reds->lookahead_tokens[i]; bitset lookaheads = reds->lookaheads[i];
int j; int j;
FOR_EACH_SHIFT (trans, j) FOR_EACH_SHIFT (trans, j)
res += bitset_test (lookaheads, TRANSITION_SYMBOL (trans, j)); res += bitset_test (lookaheads, TRANSITION_SYMBOL (trans, j));
@@ -576,8 +576,8 @@ count_rule_state_rr_conflicts (rule *r, state *s)
if (reds->rules[j] != r) if (reds->rules[j] != r)
{ {
bitset_and (lookaheads, bitset_and (lookaheads,
reds->lookahead_tokens[i], reds->lookaheads[i],
reds->lookahead_tokens[j]); reds->lookaheads[j]);
res += bitset_count (lookaheads); res += bitset_count (lookaheads);
} }
bitset_free (lookaheads); bitset_free (lookaheads);
@@ -686,7 +686,8 @@ conflicts_print (void)
expected_rr_conflicts = -1; expected_rr_conflicts = -1;
} }
bool has_unexpected_conflicts = false; // The warning flags used to emit a diagnostic, if we did.
warnings unexpected_conflicts_warning = Wnone;
/* The following two blocks scream for factoring, but i18n support /* The following two blocks scream for factoring, but i18n support
would make it ugly. */ would make it ugly. */
{ {
@@ -703,7 +704,8 @@ conflicts_print (void)
complain (NULL, complaint, complain (NULL, complaint,
_("shift/reduce conflicts: %d found, %d expected"), _("shift/reduce conflicts: %d found, %d expected"),
total, expected); total, expected);
has_unexpected_conflicts = true; if (total)
unexpected_conflicts_warning = complaint;
} }
} }
else if (total) else if (total)
@@ -713,7 +715,7 @@ conflicts_print (void)
"%d shift/reduce conflicts", "%d shift/reduce conflicts",
total), total),
total); total);
has_unexpected_conflicts = true; unexpected_conflicts_warning = Wconflicts_sr;
} }
} }
@@ -731,7 +733,8 @@ conflicts_print (void)
complain (NULL, complaint, complain (NULL, complaint,
_("reduce/reduce conflicts: %d found, %d expected"), _("reduce/reduce conflicts: %d found, %d expected"),
total, expected); total, expected);
has_unexpected_conflicts = true; if (total)
unexpected_conflicts_warning = complaint;
} }
} }
else if (total) else if (total)
@@ -741,15 +744,16 @@ conflicts_print (void)
"%d reduce/reduce conflicts", "%d reduce/reduce conflicts",
total), total),
total); total);
has_unexpected_conflicts = true; unexpected_conflicts_warning = Wconflicts_rr;
} }
} }
if (warning_is_enabled (Wcounterexamples)) if (warning_is_enabled (Wcounterexamples))
report_counterexamples (); report_counterexamples ();
else if (has_unexpected_conflicts) else if (unexpected_conflicts_warning != Wnone)
complain (NULL, Wother, subcomplain (NULL, unexpected_conflicts_warning,
_("rerun with option '-Wcounterexamples' to generate conflict counterexamples")); _("rerun with option '-Wcounterexamples'"
" to generate conflict counterexamples"));
} }
void void
+173 -105
View File
@@ -26,6 +26,7 @@
#include <gl_linked_list.h> #include <gl_linked_list.h>
#include <gl_rbtreehash_list.h> #include <gl_rbtreehash_list.h>
#include <hash.h> #include <hash.h>
#include <mbswidth.h>
#include <stdlib.h> #include <stdlib.h>
#include <textstyle.h> #include <textstyle.h>
#include <time.h> #include <time.h>
@@ -76,17 +77,29 @@ typedef struct
{ {
derivation *d1; derivation *d1;
derivation *d2; derivation *d2;
bool shift_reduce;
bool unifying; bool unifying;
bool timeout; bool timeout;
} counterexample; } counterexample;
static counterexample * static counterexample *
new_counterexample (derivation *d1, derivation *d2, new_counterexample (derivation *d1, derivation *d2,
bool shift_reduce,
bool u, bool t) bool u, bool t)
{ {
counterexample *res = xmalloc (sizeof (counterexample)); counterexample *res = xmalloc (sizeof *res);
res->d1 = d1; res->shift_reduce = shift_reduce;
res->d2 = d2; if (shift_reduce)
{
// Display the shift first.
res->d1 = d2;
res->d2 = d1;
}
else
{
res->d1 = d1;
res->d2 = d2;
}
res->unifying = u; res->unifying = u;
res->timeout = t; res->timeout = t;
return res; return res;
@@ -101,13 +114,31 @@ free_counterexample (counterexample *cex)
} }
static void static void
print_counterexample (counterexample *cex, FILE *out, const char *prefix) counterexample_print (const counterexample *cex, FILE *out, const char *prefix)
{ {
fprintf (out, " %s%-20s ", const bool flat = getenv ("YYFLAT");
prefix, cex->unifying ? _("Example") : _("First example")); const char *example1_label
derivation_print_leaves (cex->d1, out, prefix); = cex->unifying ? _("Example") : _("First example");
fprintf (out, " %s%-20s ", const char *example2_label
prefix, _("First derivation")); = cex->unifying ? _("Example") : _("Second example");
const char *deriv1_label
= cex->shift_reduce ? _("Shift derivation") : _("First reduce derivation");
const char *deriv2_label
= cex->shift_reduce ? _("Reduce derivation") : _("Second reduce derivation");
const int width =
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), "");
else
fprintf (out, " %s%s: ", prefix, example1_label);
derivation_print_leaves (cex->d1, out);
if (flat)
fprintf (out, " %s%s%*s ", prefix,
deriv1_label, width - mbswidth (deriv1_label, 0), "");
else
fprintf (out, " %s%s", prefix, deriv1_label);
derivation_print (cex->d1, out, prefix); derivation_print (cex->d1, out, prefix);
// If we output to the terminal (via stderr) and we have color // If we output to the terminal (via stderr) and we have color
@@ -115,15 +146,22 @@ print_counterexample (counterexample *cex, FILE *out, const char *prefix)
// to see the differences. // to see the differences.
if (!cex->unifying || is_styled (stderr)) if (!cex->unifying || is_styled (stderr))
{ {
fprintf (out, " %s%-20s ", if (flat)
prefix, cex->unifying ? _("Example") : _("Second example")); fprintf (out, " %s%s%*s ", prefix,
derivation_print_leaves (cex->d2, out, prefix); example2_label, width - mbswidth (example2_label, 0), "");
else
fprintf (out, " %s%s: ", prefix, example2_label);
derivation_print_leaves (cex->d2, out);
} }
fprintf (out, " %s%-20s ", if (flat)
prefix, _("Second derivation")); fprintf (out, " %s%s%*s ", prefix,
deriv2_label, width - mbswidth (deriv2_label, 0), "");
else
fprintf (out, " %s%s", prefix, deriv2_label);
derivation_print (cex->d2, out, prefix); derivation_print (cex->d2, out, prefix);
fputc ('\n', out); if (out != stderr)
putc ('\n', out);
} }
/* /*
@@ -144,7 +182,7 @@ typedef struct si_bfs_node
static si_bfs_node * static si_bfs_node *
si_bfs_new (state_item_number si, si_bfs_node *parent) si_bfs_new (state_item_number si, si_bfs_node *parent)
{ {
si_bfs_node *res = xcalloc (1, sizeof (si_bfs_node)); si_bfs_node *res = xcalloc (1, sizeof *res);
res->si = si; res->si = si;
res->parent = parent; res->parent = parent;
res->reference_count = 1; res->reference_count = 1;
@@ -175,6 +213,8 @@ si_bfs_free (si_bfs_node *n)
} }
} }
typedef gl_list_t si_bfs_node_list;
/** /**
* start is a state_item such that conflict_sym is an element of FIRSTS of the * start is a state_item such that conflict_sym is an element of FIRSTS of the
* nonterminal after the dot in start. Because of this, we should be able to * nonterminal after the dot in start. Because of this, we should be able to
@@ -188,15 +228,16 @@ expand_to_conflict (state_item_number start, symbol_number conflict_sym)
{ {
si_bfs_node *init = si_bfs_new (start, NULL); si_bfs_node *init = si_bfs_new (start, NULL);
gl_list_t queue = gl_list_create (GL_LINKED_LIST, NULL, NULL, si_bfs_node_list queue
(gl_listelement_dispose_fn) si_bfs_free, = gl_list_create (GL_LINKED_LIST, NULL, NULL,
true, 1, (const void **) &init); (gl_listelement_dispose_fn) si_bfs_free,
true, 1, (const void **) &init);
si_bfs_node *node = NULL; si_bfs_node *node = NULL;
// breadth-first search for a path of productions to the conflict symbol // breadth-first search for a path of productions to the conflict symbol
while (gl_list_size (queue) > 0) while (gl_list_size (queue) > 0)
{ {
node = (si_bfs_node *) gl_list_get_at (queue, 0); node = (si_bfs_node *) gl_list_get_at (queue, 0);
state_item *silast = state_items + node->si; state_item *silast = &state_items[node->si];
symbol_number sym = item_number_as_symbol_number (*silast->item); symbol_number sym = item_number_as_symbol_number (*silast->item);
if (sym == conflict_sym) if (sym == conflict_sym)
break; break;
@@ -238,7 +279,7 @@ expand_to_conflict (state_item_number start, symbol_number conflict_sym)
for (si_bfs_node *n = node; n != NULL; n = n->parent) for (si_bfs_node *n = node; n != NULL; n = n->parent)
{ {
state_item *si = state_items + n->si; state_item *si = &state_items[n->si];
item_number *pos = si->item; item_number *pos = si->item;
if (SI_PRODUCTION (si)) if (SI_PRODUCTION (si))
{ {
@@ -274,7 +315,7 @@ expand_to_conflict (state_item_number start, symbol_number conflict_sym)
*/ */
static derivation * static derivation *
complete_diverging_example (symbol_number conflict_sym, complete_diverging_example (symbol_number conflict_sym,
gl_list_t path, derivation_list derivs) state_item_list path, derivation_list derivs)
{ {
// The idea is to transfer each pending symbol on the productions // The idea is to transfer each pending symbol on the productions
// associated with the given StateItems to the resulting derivation. // associated with the given StateItems to the resulting derivation.
@@ -395,15 +436,15 @@ complete_diverging_example (symbol_number conflict_sym,
/* Iterate backwards through the shifts of the path in the reduce /* Iterate backwards through the shifts of the path in the reduce
conflict, and find a path of shifts from the shift conflict that conflict, and find a path of shifts from the shift conflict that
goes through the same states. */ goes through the same states. */
static gl_list_t static state_item_list
nonunifying_shift_path (gl_list_t reduce_path, state_item *shift_conflict) nonunifying_shift_path (state_item_list reduce_path, state_item *shift_conflict)
{ {
gl_list_node_t tmp = gl_list_add_last (reduce_path, NULL); gl_list_node_t tmp = gl_list_add_last (reduce_path, NULL);
gl_list_node_t next_node = gl_list_previous_node (reduce_path, tmp); gl_list_node_t next_node = gl_list_previous_node (reduce_path, tmp);
gl_list_node_t node = gl_list_previous_node (reduce_path, next_node); gl_list_node_t node = gl_list_previous_node (reduce_path, next_node);
gl_list_remove_node (reduce_path, tmp); gl_list_remove_node (reduce_path, tmp);
state_item *si = shift_conflict; state_item *si = shift_conflict;
gl_list_t result = state_item_list result =
gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true); gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true);
// FIXME: bool paths_merged; // FIXME: bool paths_merged;
for (; node != NULL; next_node = node, for (; node != NULL; next_node = node,
@@ -425,10 +466,10 @@ nonunifying_shift_path (gl_list_t reduce_path, state_item *shift_conflict)
// bfs to find a shift to the right state // bfs to find a shift to the right state
si_bfs_node *init = si_bfs_new (si - state_items, NULL); si_bfs_node *init = si_bfs_new (si - state_items, NULL);
gl_list_t queue = si_bfs_node_list queue
gl_list_create (GL_LINKED_LIST, NULL, NULL, = gl_list_create (GL_LINKED_LIST, NULL, NULL,
(gl_listelement_dispose_fn) si_bfs_free, (gl_listelement_dispose_fn) si_bfs_free,
true, 1, (const void **) &init); true, 1, (const void **) &init);
si_bfs_node *sis = NULL; si_bfs_node *sis = NULL;
state_item *prevsi = NULL; state_item *prevsi = NULL;
while (gl_list_size (queue) > 0) while (gl_list_size (queue) > 0)
@@ -438,7 +479,7 @@ nonunifying_shift_path (gl_list_t reduce_path, state_item *shift_conflict)
if (sis->si == 0) if (sis->si == 0)
break; break;
state_item *search_si = state_items + sis->si; state_item *search_si = &state_items[sis->si];
// if the current state-item is a production item, // if the current state-item is a production item,
// its reverse production items get added to the queue. // its reverse production items get added to the queue.
// Otherwise, look for a reverse transition to the target state. // Otherwise, look for a reverse transition to the target state.
@@ -447,7 +488,7 @@ nonunifying_shift_path (gl_list_t reduce_path, state_item *shift_conflict)
state_item_number sin; state_item_number sin;
BITSET_FOR_EACH (biter, rsi, sin, 0) BITSET_FOR_EACH (biter, rsi, sin, 0)
{ {
prevsi = state_items + sin; prevsi = &state_items[sin];
if (SI_TRANSITION (search_si)) if (SI_TRANSITION (search_si))
{ {
if (prevsi->state == refsi->state) if (prevsi->state == refsi->state)
@@ -465,9 +506,9 @@ nonunifying_shift_path (gl_list_t reduce_path, state_item *shift_conflict)
// prepend path to shift we found // prepend path to shift we found
if (sis) if (sis)
{ {
gl_list_node_t ln = gl_list_add_first (result, state_items + sis->si); gl_list_node_t ln = gl_list_add_first (result, &state_items[sis->si]);
for (si_bfs_node *n = sis->parent; n; n = n->parent) for (si_bfs_node *n = sis->parent; n; n = n->parent)
ln = gl_list_add_after (result, ln, state_items + n->si); ln = gl_list_add_after (result, ln, &state_items[n->si]);
} }
si = prevsi; si = prevsi;
@@ -480,7 +521,7 @@ nonunifying_shift_path (gl_list_t reduce_path, state_item *shift_conflict)
for (gl_list_iterator_t it = gl_list_iterator (result); for (gl_list_iterator_t it = gl_list_iterator (result);
state_item_list_next (&it, &sip); state_item_list_next (&it, &sip);
) )
print_state_item (sip, stderr, ""); state_item_print (sip, stderr, "");
} }
return result; return result;
} }
@@ -493,17 +534,17 @@ nonunifying_shift_path (gl_list_t reduce_path, state_item *shift_conflict)
static counterexample * static counterexample *
example_from_path (bool shift_reduce, example_from_path (bool shift_reduce,
state_item_number itm2, state_item_number itm2,
gl_list_t shortest_path, symbol_number next_sym) state_item_list shortest_path, symbol_number next_sym)
{ {
derivation *deriv1 = derivation *deriv1 =
complete_diverging_example (next_sym, shortest_path, NULL); complete_diverging_example (next_sym, shortest_path, NULL);
gl_list_t path_2 state_item_list path_2
= shift_reduce = shift_reduce
? nonunifying_shift_path (shortest_path, &state_items [itm2]) ? nonunifying_shift_path (shortest_path, &state_items [itm2])
: shortest_path_from_start (itm2, next_sym); : shortest_path_from_start (itm2, next_sym);
derivation *deriv2 = complete_diverging_example (next_sym, path_2, NULL); derivation *deriv2 = complete_diverging_example (next_sym, path_2, NULL);
gl_list_free (path_2); gl_list_free (path_2);
return new_counterexample (deriv1, deriv2, false, true); return new_counterexample (deriv1, deriv2, shift_reduce, false, true);
} }
/* /*
@@ -525,7 +566,7 @@ typedef struct
static search_state * static search_state *
initial_search_state (state_item *conflict1, state_item *conflict2) initial_search_state (state_item *conflict1, state_item *conflict2)
{ {
search_state *res = xmalloc (sizeof (search_state)); search_state *res = xmalloc (sizeof *res);
res->states[0] = new_parse_state (conflict1); res->states[0] = new_parse_state (conflict1);
res->states[1] = new_parse_state (conflict2); res->states[1] = new_parse_state (conflict2);
parse_state_retain (res->states[0]); parse_state_retain (res->states[0]);
@@ -537,7 +578,7 @@ initial_search_state (state_item *conflict1, state_item *conflict2)
static search_state * static search_state *
new_search_state (parse_state *ps1, parse_state *ps2, int complexity) new_search_state (parse_state *ps1, parse_state *ps2, int complexity)
{ {
search_state *res = xmalloc (sizeof (search_state)); search_state *res = xmalloc (sizeof *res);
res->states[0] = ps1; res->states[0] = ps1;
res->states[1] = ps2; res->states[1] = ps2;
parse_state_retain (res->states[0]); parse_state_retain (res->states[0]);
@@ -549,8 +590,8 @@ new_search_state (parse_state *ps1, parse_state *ps2, int complexity)
static search_state * static search_state *
copy_search_state (search_state *parent) copy_search_state (search_state *parent)
{ {
search_state *res = xmalloc (sizeof (search_state)); search_state *res = xmalloc (sizeof *res);
memcpy (res, parent, sizeof (search_state)); *res = *parent;
parse_state_retain (res->states[0]); parse_state_retain (res->states[0]);
parse_state_retain (res->states[1]); parse_state_retain (res->states[1]);
return res; return res;
@@ -583,6 +624,8 @@ search_state_print (search_state *ss)
putc ('\n', stderr); putc ('\n', stderr);
} }
typedef gl_list_t search_state_list;
static inline bool static inline bool
search_state_list_next (gl_list_iterator_t *it, search_state **ss) search_state_list_next (gl_list_iterator_t *it, search_state **ss)
{ {
@@ -614,18 +657,20 @@ ss_set_parse_state (search_state *ss, int idx, parse_state *ps)
*/ */
static counterexample * static counterexample *
complete_diverging_examples (search_state *ss, complete_diverging_examples (search_state *ss,
symbol_number next_sym) symbol_number next_sym,
bool shift_reduce)
{ {
derivation *new_derivs[2]; derivation *new_derivs[2];
for (int i = 0; i < 2; ++i) for (int i = 0; i < 2; ++i)
{ {
gl_list_t sitems; state_item_list sitems;
derivation_list derivs; derivation_list derivs;
parse_state_lists (ss->states[i], &sitems, &derivs); parse_state_lists (ss->states[i], &sitems, &derivs);
new_derivs[i] = complete_diverging_example (next_sym, sitems, derivs); new_derivs[i] = complete_diverging_example (next_sym, sitems, derivs);
gl_list_free (sitems); gl_list_free (sitems);
} }
return new_counterexample (new_derivs[0], new_derivs[1], false, true); return new_counterexample (new_derivs[0], new_derivs[1],
shift_reduce, false, true);
} }
/* /*
@@ -635,7 +680,7 @@ complete_diverging_examples (search_state *ss,
*/ */
typedef struct typedef struct
{ {
gl_list_t states; search_state_list states;
int complexity; int complexity;
} search_state_bundle; } search_state_bundle;
@@ -664,6 +709,8 @@ ssb_equals (const search_state_bundle *s1, const search_state_bundle *s2)
return s1->complexity == s2->complexity; return s1->complexity == s2->complexity;
} }
typedef gl_list_t ssb_list;
static size_t static size_t
visited_hasher (const search_state *ss, size_t max) visited_hasher (const search_state *ss, size_t max)
{ {
@@ -679,7 +726,7 @@ visited_comparator (const search_state *ss1, const search_state *ss2)
} }
/* Priority queue for search states with minimal complexity. */ /* Priority queue for search states with minimal complexity. */
static gl_list_t ssb_queue; static ssb_list ssb_queue;
static Hash_table *visited; static Hash_table *visited;
/* The set of parser states on the shortest lookahead-sensitive path. */ /* The set of parser states on the shortest lookahead-sensitive path. */
static bitset scp_set = NULL; static bitset scp_set = NULL;
@@ -702,7 +749,7 @@ ssb_append (search_state *ss)
parse_state_free_contents_early (ss->states[1]); parse_state_free_contents_early (ss->states[1]);
parse_state_retain (ss->states[0]); parse_state_retain (ss->states[0]);
parse_state_retain (ss->states[1]); parse_state_retain (ss->states[1]);
search_state_bundle *ssb = xmalloc (sizeof (search_state_bundle)); search_state_bundle *ssb = xmalloc (sizeof *ssb);
ssb->complexity = ss->complexity; ssb->complexity = ss->complexity;
gl_list_node_t n = gl_list_search (ssb_queue, ssb); gl_list_node_t n = gl_list_search (ssb_queue, ssb);
if (!n) if (!n)
@@ -756,12 +803,12 @@ reduction_cost (const parse_state *ps)
return SHIFT_COST * shifts + PRODUCTION_COST * productions; return SHIFT_COST * shifts + PRODUCTION_COST * productions;
} }
static gl_list_t static search_state_list
reduction_step (search_state *ss, const item_number *conflict_item, reduction_step (search_state *ss, const item_number *conflict_item,
int parser_state, int rule_len) int parser_state, int rule_len)
{ {
(void) conflict_item; // FIXME: Unused (void) conflict_item; // FIXME: Unused
gl_list_t result = search_state_list result =
gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, 1); gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, 1);
parse_state *ps = ss->states[parser_state]; parse_state *ps = ss->states[parser_state];
@@ -897,7 +944,7 @@ search_state_prepend (search_state *ss, symbol_number sym, bitset guide)
* the same prefix up to the dot. * the same prefix up to the dot.
*/ */
static bool static bool
has_common_prefix (const item_number *itm1, const item_number *itm2) have_common_prefix (const item_number *itm1, const item_number *itm2)
{ {
int i = 0; int i = 0;
for (; !item_number_is_rule_number (itm1[i]); ++i) for (; !item_number_is_rule_number (itm1[i]); ++i)
@@ -988,14 +1035,14 @@ generate_next_states (search_state *ss, state_item *conflict1,
// prepended further, reduce. // prepended further, reduce.
if (ready1 && ready2) if (ready1 && ready2)
{ {
gl_list_t reduced1 = reduction_step (ss, conflict1->item, 0, len1); search_state_list reduced1 = reduction_step (ss, conflict1->item, 0, len1);
gl_list_add_last (reduced1, ss); gl_list_add_last (reduced1, ss);
search_state *red1 = NULL; search_state *red1 = NULL;
for (gl_list_iterator_t iter = gl_list_iterator (reduced1); for (gl_list_iterator_t iter = gl_list_iterator (reduced1);
search_state_list_next (&iter, &red1); search_state_list_next (&iter, &red1);
) )
{ {
gl_list_t reduced2 = search_state_list reduced2 =
reduction_step (red1, conflict2->item, 1, len2); reduction_step (red1, conflict2->item, 1, len2);
search_state *red2 = NULL; search_state *red2 = NULL;
for (gl_list_iterator_t iter2 = gl_list_iterator (reduced2); for (gl_list_iterator_t iter2 = gl_list_iterator (reduced2);
@@ -1011,7 +1058,7 @@ generate_next_states (search_state *ss, state_item *conflict1,
} }
else if (ready1) else if (ready1)
{ {
gl_list_t reduced1 = reduction_step (ss, conflict1->item, 0, len1); search_state_list reduced1 = reduction_step (ss, conflict1->item, 0, len1);
search_state *red1 = NULL; search_state *red1 = NULL;
for (gl_list_iterator_t iter = gl_list_iterator (reduced1); for (gl_list_iterator_t iter = gl_list_iterator (reduced1);
search_state_list_next (&iter, &red1); search_state_list_next (&iter, &red1);
@@ -1021,7 +1068,7 @@ generate_next_states (search_state *ss, state_item *conflict1,
} }
else if (ready2) else if (ready2)
{ {
gl_list_t reduced2 = reduction_step (ss, conflict2->item, 1, len2); search_state_list reduced2 = reduction_step (ss, conflict2->item, 1, len2);
search_state *red2 = NULL; search_state *red2 = NULL;
for (gl_list_iterator_t iter2 = gl_list_iterator (reduced2); for (gl_list_iterator_t iter2 = gl_list_iterator (reduced2);
search_state_list_next (&iter2, &red2); search_state_list_next (&iter2, &red2);
@@ -1055,10 +1102,10 @@ static counterexample *
unifying_example (state_item_number itm1, unifying_example (state_item_number itm1,
state_item_number itm2, state_item_number itm2,
bool shift_reduce, bool shift_reduce,
gl_list_t reduce_path, symbol_number next_sym) state_item_list reduce_path, symbol_number next_sym)
{ {
state_item *conflict1 = state_items + itm1; state_item *conflict1 = &state_items[itm1];
state_item *conflict2 = state_items + itm2; state_item *conflict2 = &state_items[itm2];
search_state *initial = initial_search_state (conflict1, conflict2); search_state *initial = initial_search_state (conflict1, conflict2);
ssb_queue = gl_list_create_empty (GL_RBTREEHASH_LIST, ssb_queue = gl_list_create_empty (GL_RBTREEHASH_LIST,
(gl_listelement_equals_fn) ssb_equals, (gl_listelement_equals_fn) ssb_equals,
@@ -1094,7 +1141,7 @@ unifying_example (state_item_number itm1,
const state_item *si1src = parse_state_head (ps1); const state_item *si1src = parse_state_head (ps1);
const state_item *si2src = parse_state_head (ps2); const state_item *si2src = parse_state_head (ps2);
if (item_rule (si1src->item)->lhs == item_rule (si2src->item)->lhs if (item_rule (si1src->item)->lhs == item_rule (si2src->item)->lhs
&& has_common_prefix (si1src->item, si2src->item)) && have_common_prefix (si1src->item, si2src->item))
{ {
// Stage 4: both paths share a prefix // Stage 4: both paths share a prefix
derivation *d1 = parse_state_derivation (ps1); derivation *d1 = parse_state_derivation (ps1);
@@ -1104,7 +1151,7 @@ unifying_example (state_item_number itm1,
{ {
// Once we have two derivations for the same symbol, // Once we have two derivations for the same symbol,
// we've found a unifying counterexample. // we've found a unifying counterexample.
cex = new_counterexample (d1, d2, true, false); cex = new_counterexample (d1, d2, shift_reduce, true, false);
derivation_retain (d1); derivation_retain (d1);
derivation_retain (d2); derivation_retain (d2);
goto cex_search_end; goto cex_search_end;
@@ -1142,7 +1189,7 @@ cex_search_end:;
// If a search state from Stage 3 is available, use it // If a search state from Stage 3 is available, use it
// to construct a more compact nonunifying counterexample. // to construct a more compact nonunifying counterexample.
if (stage3result) if (stage3result)
cex = complete_diverging_examples (stage3result, next_sym); cex = complete_diverging_examples (stage3result, next_sym, shift_reduce);
// Otherwise, construct a nonunifying counterexample that // Otherwise, construct a nonunifying counterexample that
// begins from the start state using the shortest // begins from the start state using the shortest
// lookahead-sensitive path to the reduce item. // lookahead-sensitive path to the reduce item.
@@ -1190,7 +1237,7 @@ counterexample_report (state_item_number itm1, state_item_number itm2,
{ {
// Compute the shortest lookahead-sensitive path and associated sets of // Compute the shortest lookahead-sensitive path and associated sets of
// parser states. // parser states.
gl_list_t shortest_path = shortest_path_from_start (itm1, next_sym); state_item_list shortest_path = shortest_path_from_start (itm1, next_sym);
bool reduce_prod_reached = false; bool reduce_prod_reached = false;
const rule *reduce_rule = item_rule (state_items[itm1].item); const rule *reduce_rule = item_rule (state_items[itm1].item);
@@ -1215,21 +1262,31 @@ counterexample_report (state_item_number itm1, state_item_number itm2,
: example_from_path (shift_reduce, itm2, shortest_path, next_sym); : example_from_path (shift_reduce, itm2, shortest_path, next_sym);
gl_list_free (shortest_path); gl_list_free (shortest_path);
print_counterexample (cex, out, prefix); counterexample_print (cex, out, prefix);
free_counterexample (cex); free_counterexample (cex);
} }
// ITM1 denotes a shift, ITM2 a reduce.
static void static void
counterexample_report_shift_reduce (state_item_number itm1, state_item_number itm2, counterexample_report_shift_reduce (state_item_number itm1, state_item_number itm2,
symbol_number next_sym, symbol_number next_sym,
FILE *out, const char *prefix) FILE *out, const char *prefix)
{ {
fputs (prefix, out); if (out == stderr)
fprintf (out, _("Shift/reduce conflict on token %s:\n"), symbols[next_sym]->tag); complain (NULL, Wcounterexamples,
if (*prefix) _("shift/reduce conflict on token %s"), symbols[next_sym]->tag);
else
{ {
print_state_item (&state_items[itm1], out, prefix); fputs (prefix, out);
print_state_item (&state_items[itm2], out, prefix); fprintf (out, _("shift/reduce conflict on token %s"), symbols[next_sym]->tag);
fprintf (out, "%s\n", _(":"));
}
// In the report, print the items.
if (out != stderr || trace_flag & trace_cex)
{
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); counterexample_report (itm1, itm2, next_sym, true, out, prefix);
} }
@@ -1240,32 +1297,49 @@ counterexample_report_reduce_reduce (state_item_number itm1, state_item_number i
FILE *out, const char *prefix) FILE *out, const char *prefix)
{ {
{ {
fputs (prefix, out); struct obstack obstack;
fputs (ngettext ("Reduce/reduce conflict on token", obstack_init (&obstack);
"Reduce/reduce conflict on tokens",
bitset_count (conflict_syms)), out);
bitset_iterator biter; bitset_iterator biter;
state_item_number sym; state_item_number sym;
const char *sep = " "; const char *sep = "";
BITSET_FOR_EACH (biter, conflict_syms, sym, 0) BITSET_FOR_EACH (biter, conflict_syms, sym, 0)
{ {
fprintf (out, "%s%s", sep, symbols[sym]->tag); obstack_printf (&obstack, "%s%s", sep, symbols[sym]->tag);
sep = ", "; sep = ", ";
} }
fputs (_(":\n"), out); char *tokens = obstack_finish0 (&obstack);
if (out == stderr)
complain (NULL, Wcounterexamples,
ngettext ("reduce/reduce conflict on token %s",
"reduce/reduce conflict on tokens %s",
bitset_count (conflict_syms)),
tokens);
else
{
fputs (prefix, out);
fprintf (out,
ngettext ("reduce/reduce conflict on token %s",
"reduce/reduce conflict on tokens %s",
bitset_count (conflict_syms)),
tokens);
fprintf (out, "%s\n", _(":"));
}
obstack_free (&obstack, NULL);
} }
if (*prefix) // In the report, print the items.
if (out != stderr || trace_flag & trace_cex)
{ {
print_state_item (&state_items[itm1], out, prefix); state_item_print (&state_items[itm1], out, prefix);
print_state_item (&state_items[itm2], out, prefix); state_item_print (&state_items[itm2], out, prefix);
} }
counterexample_report (itm1, itm2, bitset_first (conflict_syms), false, out, prefix); counterexample_report (itm1, itm2, bitset_first (conflict_syms),
false, out, prefix);
} }
static state_item_number static state_item_number
find_state_item_number (const rule *r, state_number sn) find_state_item_number (const rule *r, state_number sn)
{ {
for (int i = state_item_map[sn]; i < state_item_map[sn + 1]; ++i) for (state_item_number i = state_item_map[sn]; i < state_item_map[sn + 1]; ++i)
if (!SI_DISABLED (i) if (!SI_DISABLED (i)
&& item_number_as_rule_number (*state_items[i].item) == r->number) && item_number_as_rule_number (*state_items[i].item) == r->number)
return i; return i;
@@ -1277,41 +1351,35 @@ counterexample_report_state (const state *s, FILE *out, const char *prefix)
{ {
const state_number sn = s->number; const state_number sn = s->number;
const reductions *reds = s->reductions; const reductions *reds = s->reductions;
bitset lookaheads = bitset_create (ntokens, BITSET_FIXED);
for (int i = 0; i < reds->num; ++i) for (int i = 0; i < reds->num; ++i)
{ {
const rule *r1 = reds->rules[i]; const rule *r1 = reds->rules[i];
const state_item_number c1 = find_state_item_number (r1, sn); const state_item_number c1 = find_state_item_number (r1, sn);
for (int j = state_item_map[sn]; j < state_item_map[sn + 1]; ++j) for (state_item_number c2 = state_item_map[sn]; c2 < state_item_map[sn + 1]; ++c2)
if (!SI_DISABLED (j)) if (!SI_DISABLED (c2))
{ {
state_item *si = state_items + j; item_number conf = *state_items[c2].item;
item_number conf = *si->item;
if (item_number_is_symbol_number (conf) if (item_number_is_symbol_number (conf)
&& bitset_test (reds->lookahead_tokens[i], conf)) && bitset_test (reds->lookaheads[i], conf))
counterexample_report_shift_reduce (c1, j, conf, out, prefix); counterexample_report_shift_reduce (c1, c2, conf, out, prefix);
} }
for (int j = i+1; j < reds->num; ++j) for (int j = i+1; j < reds->num; ++j)
{ {
bitset conf = bitset_create (ntokens, BITSET_FIXED); const rule *r2 = reds->rules[j];
bitset_intersection (conf, // Conflicts: common lookaheads.
reds->lookahead_tokens[i], bitset_intersection (lookaheads,
reds->lookahead_tokens[j]); reds->lookaheads[i],
if (!bitset_empty_p (conf)) reds->lookaheads[j]);
{ if (!bitset_empty_p (lookaheads))
const rule *r2 = reds->rules[j]; for (state_item_number c2 = state_item_map[sn]; c2 < state_item_map[sn + 1]; ++c2)
for (int k = state_item_map[sn]; k < state_item_map[sn + 1]; ++k) if (!SI_DISABLED (c2)
if (!SI_DISABLED (k)) && item_rule (state_items[c2].item) == r2)
{ {
state_item *si = state_items + k; counterexample_report_reduce_reduce (c1, c2, lookaheads, out, prefix);
const rule *r = item_rule (si->item); break;
if (r == r2) }
{
counterexample_report_reduce_reduce (c1, k, conf, out, prefix);
break;
}
}
}
bitset_free (conf);
} }
} }
bitset_free (lookaheads);
} }
+8 -2
View File
@@ -20,11 +20,17 @@
#ifndef COUNTEREXAMPLE_H #ifndef COUNTEREXAMPLE_H
# define COUNTEREXAMPLE_H # define COUNTEREXAMPLE_H
# include "state-item.h" # include "state.h"
// Init/deinit this module.
void counterexample_init (void); void counterexample_init (void);
void counterexample_free (void); void counterexample_free (void);
void counterexample_report_state (const state *s, FILE *out, const char *prefix); // Print the counterexamples for the conflicts of state S.
//
// Used both for the warnings on the terminal (OUT = stderr, PREFIX =
// ""), and for the reports (OUT != stderr, PREFIX != "").
void
counterexample_report_state (const state *s, FILE *out, const char *prefix);
#endif /* COUNTEREXAMPLE_H */ #endif /* COUNTEREXAMPLE_H */
+271 -46
View File
@@ -20,8 +20,11 @@
#include <config.h> #include <config.h>
#include "derivation.h" #include "derivation.h"
#include "glyphs.h"
#include <c-ctype.h>
#include <gl_linked_list.h> #include <gl_linked_list.h>
#include <mbswidth.h>
#include "system.h" #include "system.h"
#include "complain.h" #include "complain.h"
@@ -29,11 +32,15 @@
struct derivation struct derivation
{ {
symbol_number sym; symbol_number sym;
gl_list_t children; derivation_list children;
int reference_count; int reference_count;
// Color assigned for styling. Guarantees that the derivation is
// always displayed with the same color, independently of the order
// in which the derivations are traversed.
int color;
}; };
static derivation d_dot = { -1, NULL, -1 }; static derivation d_dot = { -1, NULL, -1, -1 };
derivation * derivation *
derivation_dot (void) derivation_dot (void)
@@ -69,11 +76,12 @@ void derivation_list_free (derivation_list dl)
derivation * derivation *
derivation_new (symbol_number sym, derivation_list children) derivation_new (symbol_number sym, derivation_list children)
{ {
derivation *deriv = xmalloc (sizeof (derivation)); derivation *res = xmalloc (sizeof *res);
deriv->sym = sym; res->sym = sym;
deriv->children = children; res->children = children;
deriv->reference_count = 0; res->reference_count = 0;
return deriv; res->color = -1;
return res;
} }
void void
@@ -126,27 +134,236 @@ derivation_size (const derivation *deriv)
return size; return size;
} }
/* Print DERIV, colored according to COUNTER.
Return false if nothing is printed. */ // Longest distance from root to leaf.
static int
derivation_depth (const derivation *deriv)
{
if (deriv->children)
{
// Children's depth cannot be 0, even if there are no children
// (the case of a derivation with an empty RHS).
int res = 1;
derivation *child;
for (gl_list_iterator_t it = gl_list_iterator (deriv->children);
derivation_list_next (&it, &child);
)
res = max_int (res, derivation_depth (child));
return res + 1;
}
else
return 1;
}
static bool static bool
derivation_print_impl (const derivation *deriv, FILE *f, all_spaces (const char *s)
bool leaves_only, {
int *counter, const char *prefix) while (c_isspace (*s))
s++;
return *s == '\0';
}
// Printing the derivation as trees without trailing spaces is
// painful: we cannot simply pad one "column" before moving to the
// next:
//
// exp
// ↳ x1 e1 foo1 x1
// ↳ x2 ↳ ε ↳ foo2 ↳ x2
// ↳ x3 ↳ foo3 ↳ x3
// ↳ "X" • ↳ x1 foo4 ↳ "X"
// ↳ x2 ↳ "quuux"
// ↳ x3
// ↳ "X"
//
// It's hard for a column to know that it's "last" to decide whether
// to output the right-padding or not. So when we need to pad on the
// right to complete a column, we don't output the spaces, we
// accumulate the width of padding in *PADDING.
//
// Each time we actually print something (non space), we flush that
// padding. When we _don't_ print something, its width is added to
// the current padding.
//
// This function implements this.
//
// When COND is true, put S on OUT, preceded by *PADDING white spaces.
// Otherwise add the width to *PADDING. Return the width of S.
static int
fputs_if (bool cond, FILE *out, int *padding, const char *s)
{
int res = mbswidth (s, 0);
if (cond && !all_spaces (s))
{
fprintf (out, "%*s%s", *padding, "", s);
*padding = 0;
}
else
{
*padding += res;
}
return res;
}
// The width taken to report this derivation recursively down to its
// leaves.
static int
derivation_width (const derivation *deriv)
{ {
if (deriv->children)
{
const symbol *sym = symbols[deriv->sym];
int self_width = mbswidth (sym->tag, 0);
// Arrow and space.
int children_width = down_arrow_width;
if (gl_list_size (deriv->children) == 0)
// Empty rhs.
children_width += empty_width;
else
{
derivation *child;
for (gl_list_iterator_t it = gl_list_iterator (deriv->children);
derivation_list_next (&it, &child);
)
children_width
+= derivation_separator_width + derivation_width (child);
// No separator at the beginning.
children_width -= derivation_separator_width;
}
return max_int (self_width, children_width);
}
else if (deriv == &d_dot)
{
return dot_width;
}
else // leaf.
{
const symbol *sym = symbols[deriv->sym];
return mbswidth (sym->tag, 0);
}
}
// Print DERIV for DEPTH.
//
// The tree is printed from top to bottom with DEPTH ranging from 0 to
// the total depth of the tree. DERIV should only printed when we
// reach its depth, i.e., then DEPTH is 0.
//
// When DEPTH is 1 and we're on a subderivation, then we print the RHS
// of the derivation (in DEPTH 0 we printed its LHS).
//
// Return the "logical printed" width. We might have not have reached
// that width, in which case the missing spaces are in *PADDING.
static int
derivation_print_tree_impl (const derivation *deriv, FILE *out,
int depth, int *padding)
{
const int width = derivation_width (deriv);
int res = 0;
if (deriv->children) if (deriv->children)
{ {
const symbol *sym = symbols[deriv->sym]; const symbol *sym = symbols[deriv->sym];
char style[20]; char style[20];
snprintf (style, 20, "cex-%d", *counter); snprintf (style, 20, "cex-%d", deriv->color);
if (depth == 0 || depth == 1)
{
begin_use_class (style, out);
begin_use_class ("cex-step", out);
}
if (depth == 0)
{
res += fputs_if (true, out, padding, sym->tag);
}
else
{
res += fputs_if (depth == 1, out, padding, down_arrow);
if (gl_list_size (deriv->children) == 0)
// Empty rhs.
res += fputs_if (depth == 1, out, padding, empty);
else
{
bool first = true;
derivation *child;
for (gl_list_iterator_t it = gl_list_iterator (deriv->children);
derivation_list_next (&it, &child);
)
{
if (!first)
res += fputs_if (depth == 1, out, padding, derivation_separator);
res += derivation_print_tree_impl (child, out, depth - 1, padding);
first = false;
}
}
}
if (depth == 0 || depth == 1)
{
end_use_class ("cex-step", out);
end_use_class (style, out);
}
*padding += width - res;
res = width;
}
else if (deriv == &d_dot)
{
if (depth == 0)
begin_use_class ("cex-dot", out);
res += fputs_if (depth == 0, out, padding, dot);
if (depth == 0)
end_use_class ("cex-dot", out);
}
else // leaf.
{
const symbol *sym = symbols[deriv->sym];
if (depth == 0)
begin_use_class ("cex-leaf", out);
res += fputs_if (depth == 0, out, padding, sym->tag);
if (depth == 0)
end_use_class ("cex-leaf", out);
}
return res;
}
static void
derivation_print_tree (const derivation *deriv, FILE *out, const char *prefix)
{
fputc ('\n', out);
for (int depth = 0, max_depth = derivation_depth (deriv);
depth < max_depth; ++depth)
{
int padding = 0;
fprintf (out, " %s", prefix);
derivation_print_tree_impl (deriv, out, depth, &padding);
fputc ('\n', out);
}
}
/* Print DERIV, colored according to COUNTER.
Return false if nothing is printed. */
static bool
derivation_print_flat_impl (derivation *deriv, FILE *out,
bool leaves_only,
int *counter, const char *prefix)
{
if (deriv->children)
{
const symbol *sym = symbols[deriv->sym];
deriv->color = *counter;
++*counter; ++*counter;
begin_use_class (style, f); char style[20];
snprintf (style, 20, "cex-%d", deriv->color);
begin_use_class (style, out);
if (!leaves_only) if (!leaves_only)
{ {
fputs (prefix, f); fputs (prefix, out);
begin_use_class ("cex-step", f); begin_use_class ("cex-step", out);
fprintf (f, "%s ::=[ ", sym->tag); fprintf (out, "%s %s [ ", sym->tag, arrow);
end_use_class ("cex-step", f); end_use_class ("cex-step", out);
prefix = ""; prefix = "";
} }
bool res = false; bool res = false;
@@ -155,7 +372,8 @@ derivation_print_impl (const derivation *deriv, FILE *f,
derivation_list_next (&it, &child); derivation_list_next (&it, &child);
) )
{ {
if (derivation_print_impl (child, f, leaves_only, counter, prefix)) if (derivation_print_flat_impl (child, out,
leaves_only, counter, prefix))
{ {
prefix = " "; prefix = " ";
res = true; res = true;
@@ -165,49 +383,56 @@ derivation_print_impl (const derivation *deriv, FILE *f,
} }
if (!leaves_only) if (!leaves_only)
{ {
begin_use_class ("cex-step", f); begin_use_class ("cex-step", out);
if (res) if (res)
fputs (" ]", f); fputs (" ]", out);
else else
fputs ("]", f); fputs ("]", out);
end_use_class ("cex-step", f); end_use_class ("cex-step", out);
} }
end_use_class (style, f); end_use_class (style, out);
return res; return res;
} }
else if (deriv == &d_dot) else if (deriv == &d_dot)
{ {
fputs (prefix, f); fputs (prefix, out);
begin_use_class ("cex-dot", f); begin_use_class ("cex-dot", out);
print_dot (f); fputs (dot, out);
end_use_class ("cex-dot", f); end_use_class ("cex-dot", out);
} }
else // leaf. else // leaf.
{ {
fputs (prefix, f); fputs (prefix, out);
const symbol *sym = symbols[deriv->sym]; const symbol *sym = symbols[deriv->sym];
begin_use_class ("cex-leaf", f); begin_use_class ("cex-leaf", out);
fprintf (f, "%s", sym->tag); fprintf (out, "%s", sym->tag);
end_use_class ("cex-leaf", f); end_use_class ("cex-leaf", out);
} }
return true; return true;
} }
static void
derivation_print_flat (const derivation *deriv, FILE *out, const char *prefix)
{
int counter = 0;
fputs (prefix, out);
derivation_print_flat_impl ((derivation *)deriv, out, false, &counter, "");
fputc ('\n', out);
}
void
derivation_print_leaves (const derivation *deriv, FILE *out)
{
int counter = 0;
derivation_print_flat_impl ((derivation *)deriv, out, true, &counter, "");
fputc ('\n', out);
}
void void
derivation_print (const derivation *deriv, FILE *out, const char *prefix) derivation_print (const derivation *deriv, FILE *out, const char *prefix)
{ {
int counter = 0; if (getenv ("YYFLAT"))
fputs (prefix, out); derivation_print_flat (deriv, out, prefix);
derivation_print_impl (deriv, out, false, &counter, ""); else
fputc ('\n', out); derivation_print_tree (deriv, out, prefix);
}
void
derivation_print_leaves (const derivation *deriv, FILE *out, const char *prefix)
{
int counter = 0;
fputs (prefix, out);
derivation_print_impl (deriv, out, true, &counter, "");
fputc ('\n', out);
} }
+4 -1
View File
@@ -60,12 +60,15 @@ static inline derivation *derivation_new_leaf (symbol_number sym)
{ {
return derivation_new (sym, NULL); return derivation_new (sym, NULL);
} }
// Number of symbols.
size_t derivation_size (const derivation *deriv); size_t derivation_size (const derivation *deriv);
void derivation_print (const derivation *deriv, FILE *out, const char *prefix); void derivation_print (const derivation *deriv, FILE *out, const char *prefix);
void derivation_print_leaves (const derivation *deriv, FILE *out, const char *prefix); void derivation_print_leaves (const derivation *deriv, FILE *out);
void derivation_free (derivation *deriv); void derivation_free (derivation *deriv);
void derivation_retain (derivation *deriv); void derivation_retain (derivation *deriv);
// A derivation denoting the position of the dot.
derivation *derivation_dot (void); derivation *derivation_dot (void);
#endif /* DERIVATION_H */ #endif /* DERIVATION_H */
+9 -1
View File
@@ -112,7 +112,15 @@ static struct obstack obstack_for_string;
# define STRING_1GROW(Char) \ # define STRING_1GROW(Char) \
obstack_1grow (&obstack_for_string, Char) obstack_1grow (&obstack_for_string, Char)
# define STRING_FREE() \ # ifdef NDEBUG
# define STRING_FREE() \
obstack_free (&obstack_for_string, last_string) obstack_free (&obstack_for_string, last_string)
# else
# define STRING_FREE() \
do { \
obstack_free (&obstack_for_string, last_string); \
last_string = NULL; \
} while (0)
# endif
#endif #endif
+1 -1
View File
@@ -221,7 +221,7 @@ static const argmatch_report_arg argmatch_report_args[] =
{ "none", report_none }, { "none", report_none },
{ "states", report_states }, { "states", report_states },
{ "itemsets", report_states | report_itemsets }, { "itemsets", report_states | report_itemsets },
{ "lookaheads", report_states | report_lookahead_tokens }, { "lookaheads", report_states | report_lookaheads },
{ "solved", report_states | report_solved_conflicts }, { "solved", report_states | report_solved_conflicts },
{ "counterexamples", report_cex }, { "counterexamples", report_cex },
{ "cex", report_cex }, { "cex", report_cex },
+1 -1
View File
@@ -77,7 +77,7 @@ enum report
report_none = 0, report_none = 0,
report_states = 1 << 0, report_states = 1 << 0,
report_itemsets = 1 << 1, report_itemsets = 1 << 1,
report_lookahead_tokens = 1 << 2, report_lookaheads = 1 << 2,
report_solved_conflicts = 1 << 3, report_solved_conflicts = 1 << 3,
report_cex = 1 << 4, report_cex = 1 << 4,
report_all = ~0 report_all = ~0
+93
View File
@@ -0,0 +1,93 @@
/* Graphical symbols.
Copyright (C) 2020 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include "glyphs.h"
#include <assert.h>
#include <attribute.h>
#include <stdbool.h>
#include <string.h>
#include <mbswidth.h>
#include <unicodeio.h>
glyph_buffer_t arrow;
int arrow_width;
glyph_buffer_t down_arrow;
int down_arrow_width;
glyph_buffer_t dot;
int dot_width;
glyph_buffer_t empty;
int empty_width;
const char *derivation_separator = " ";
int derivation_separator_width = 1;
typedef struct
{
glyph_buffer_t *pbuf;
const char *fallback;
} callback_arg_t;
static long
on_success (const char *buf, size_t buflen, void *callback_arg)
{
callback_arg_t *arg = (callback_arg_t *) callback_arg;
assert (buflen + 1 < sizeof *arg->pbuf);
*stpncpy (*arg->pbuf, buf, buflen) = '\0';
return 1;
}
static long
on_failure (unsigned code MAYBE_UNUSED, const char *msg MAYBE_UNUSED,
void *callback_arg)
{
callback_arg_t *arg = (callback_arg_t *) callback_arg;
assert (strlen (arg->fallback) + 1 < sizeof *arg->pbuf);
strcpy (*arg->pbuf, arg->fallback);
return 0;
}
static bool
glyph_set (glyph_buffer_t *glyph, int *width,
unsigned code, const char *fallback)
{
callback_arg_t arg = { glyph, fallback };
int res = unicode_to_mb (code, on_success, on_failure, &arg);
*width = mbswidth (*glyph, 0);
return res;
}
void
glyphs_init (void)
{
glyph_set (&arrow, &arrow_width, 0x2192, "->");
glyph_set (&dot, &dot_width, 0x2022, ".");
glyph_set (&down_arrow, &down_arrow_width, 0x21b3, "`->");
glyph_set (&empty, &empty_width, 0x03b5, "%empty");
strncat (down_arrow, " ", sizeof down_arrow - strlen (down_arrow) - 1);
down_arrow_width += 1;
}
+50
View File
@@ -0,0 +1,50 @@
/* Graphical symbols.
Copyright (C) 2020 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#ifndef GLYPHS_H
# define GLYPHS_H
/* Initialize the following variables. */
void glyphs_init (void);
/* In gnulib/lib/unicodeio.h unicode_to_mb uses a buffer of 25 bytes.
In down_arrow, we append one space. */
typedef char glyph_buffer_t[26];
/* "→", separates the lhs of a rule from its rhs. */
extern glyph_buffer_t arrow;
extern int arrow_width;
/* "•", a point in an item (aka, a dotted rule). */
extern glyph_buffer_t dot;
extern int dot_width;
/* "↳ ", below an lhs to announce the rhs. */
extern glyph_buffer_t down_arrow;
extern int down_arrow_width;
/* "ε", an empty rhs. */
extern glyph_buffer_t empty;
extern int empty_width;
/* " ", separate symbols in the rhs of a derivation. */
extern const char *derivation_separator;
extern int derivation_separator_width;
#endif /* GLYPHS_H */
+2 -2
View File
@@ -23,6 +23,7 @@
#include "complain.h" #include "complain.h"
#include "getargs.h" #include "getargs.h"
#include "glyphs.h"
#include "gram.h" #include "gram.h"
#include "print-xml.h" #include "print-xml.h"
#include "reader.h" #include "reader.h"
@@ -56,8 +57,7 @@ item_print (item_number *item, rule const *previous_rule, FILE *out)
for (item_number *sp = r->rhs; sp < item; sp++) for (item_number *sp = r->rhs; sp < item; sp++)
fprintf (out, " %s", symbols[*sp]->tag); fprintf (out, " %s", symbols[*sp]->tag);
putc (' ', out); fprintf (out, " %s", dot);
print_dot (out);
if (0 <= *r->rhs) if (0 <= *r->rhs)
for (item_number *sp = item; 0 <= *sp; ++sp) for (item_number *sp = item; 0 <= *sp; ++sp)
fprintf (out, " %s", symbols[*sp]->tag); fprintf (out, " %s", symbols[*sp]->tag);
-21
View File
@@ -103,8 +103,6 @@
# include "system.h" # include "system.h"
# include <unicodeio.h>
# include "location.h" # include "location.h"
# include "symtab.h" # include "symtab.h"
@@ -217,25 +215,6 @@ typedef struct
extern rule *rules; extern rule *rules;
extern rule_number nrules; extern rule_number nrules;
/* Fallback in case we can't print "•". */
static inline long
print_dot_fallback (unsigned int code _GL_UNUSED,
const char *msg _GL_UNUSED,
void *callback_arg)
{
FILE *out = (FILE *) callback_arg;
putc ('.', out);
return -1;
}
/* Print "•", the symbol used to represent a point in an item (aka, a
dotted rule). */
static inline void
print_dot (FILE *out)
{
unicode_to_mb (0x2022, fwrite_success_callback, print_dot_fallback, out);
}
/* Get the rule associated to this item. ITEM points inside RITEM. */ /* Get the rule associated to this item. ITEM points inside RITEM. */
static inline rule const * static inline rule const *
item_rule (item_number const *item) item_rule (item_number const *item)
+2 -2
View File
@@ -184,9 +184,9 @@ output_red (state const *s, reductions const *reds, FILE *fout)
bool firste = true; bool firste = true;
rule_number ruleno = reds->rules[j]->number; rule_number ruleno = reds->rules[j]->number;
if (reds->lookahead_tokens) if (reds->lookaheads)
for (int i = 0; i < ntokens; i++) for (int i = 0; i < ntokens; i++)
if (bitset_test (reds->lookahead_tokens[j], i)) if (bitset_test (reds->lookaheads[j], i))
{ {
if (bitset_test (no_reduce_set, i)) if (bitset_test (no_reduce_set, i))
firstd = print_token (&dout, firstd, symbols[i]->tag); firstd = print_token (&dout, firstd, symbols[i]->tag);
+2 -2
View File
@@ -423,7 +423,7 @@ ielr_item_has_lookahead (state *s, symbol_number lhs, size_t item,
check all predecessors' goto follows for the LHS. */ check all predecessors' goto follows for the LHS. */
if (item_number_is_rule_number (ritem[s->items[item] - 2])) if (item_number_is_rule_number (ritem[s->items[item] - 2]))
{ {
aver (lhs != accept->content->number); aver (lhs != acceptsymbol->content->number);
for (state **predecessor = predecessors[s->number]; for (state **predecessor = predecessors[s->number];
*predecessor; *predecessor;
++predecessor) ++predecessor)
@@ -1025,7 +1025,7 @@ ielr_split_states (bitsetv follow_kernel_items, bitsetv always_follows,
{ {
rule *this_rule = node->state->reductions->rules[r]; rule *this_rule = node->state->reductions->rules[r];
bitset lookahead_set = bitset lookahead_set =
node->state->reductions->lookahead_tokens[r]; node->state->reductions->lookaheads[r];
if (item_number_is_rule_number (*this_rule->rhs)) if (item_number_is_rule_number (*this_rule->rhs))
ielr_compute_goto_follow_set (follow_kernel_items, ielr_compute_goto_follow_set (follow_kernel_items,
always_follows, node, always_follows, node,
+24 -27
View File
@@ -256,9 +256,9 @@ lookback_find_state (int lookback_index)
state *res = NULL; state *res = NULL;
for (int j = 0; j < nstates; ++j) for (int j = 0; j < nstates; ++j)
if (states[j]->reductions if (states[j]->reductions
&& states[j]->reductions->lookahead_tokens) && states[j]->reductions->lookaheads)
{ {
if (states[j]->reductions->lookahead_tokens - LA > lookback_index) if (states[j]->reductions->lookaheads - LA > lookback_index)
/* Went too far. */ /* Went too far. */
break; break;
else else
@@ -280,7 +280,7 @@ lookback_print (FILE *out)
{ {
fprintf (out, " %3d = ", i); fprintf (out, " %3d = ", i);
const state *s = lookback_find_state (i); const state *s = lookback_find_state (i);
int rnum = i - (s->reductions->lookahead_tokens - LA); int rnum = i - (s->reductions->lookaheads - LA);
const rule *r = s->reductions->rules[rnum]; const rule *r = s->reductions->rules[rnum];
fprintf (out, "(%3d, ", s->number); fprintf (out, "(%3d, ", s->number);
rule_print (r, NULL, out); rule_print (r, NULL, out);
@@ -305,7 +305,7 @@ static void
add_lookback_edge (state *s, rule const *r, goto_number gotono) add_lookback_edge (state *s, rule const *r, goto_number gotono)
{ {
int ri = state_reduction_find (s, r); int ri = state_reduction_find (s, r);
int idx = (s->reductions->lookahead_tokens - LA) + ri; int idx = (s->reductions->lookaheads - LA) + ri;
lookback[idx] = goto_list_new (gotono, lookback[idx]); lookback[idx] = goto_list_new (gotono, lookback[idx]);
} }
@@ -421,7 +421,7 @@ compute_follows (void)
static void static void
compute_lookahead_tokens (void) compute_lookaheads (void)
{ {
if (trace_flag & trace_automaton) if (trace_flag & trace_automaton)
lookback_print (stderr); lookback_print (stderr);
@@ -437,13 +437,12 @@ compute_lookahead_tokens (void)
} }
/*----------------------------------------------------. /*------------------------------------------------------.
| Count the number of lookahead tokens required for S | | Count the number of lookahead tokens required for S. |
| (N_LOOKAHEAD_TOKENS member). | `------------------------------------------------------*/
`----------------------------------------------------*/
static int static int
state_lookahead_tokens_count (state *s, bool default_reduction_only_for_accept) state_lookaheads_count (state *s, bool default_reduction_only_for_accept)
{ {
const reductions *reds = s->reductions; const reductions *reds = s->reductions;
const transitions *trans = s->transitions; const transitions *trans = s->transitions;
@@ -473,9 +472,9 @@ state_lookahead_tokens_count (state *s, bool default_reduction_only_for_accept)
} }
/*----------------------------------------------------. /*----------------------------------------------.
| Compute LA, NLA, and the lookahead_tokens members. | | Compute LA, NLA, and the lookaheads members. |
`----------------------------------------------------*/ `----------------------------------------------*/
void void
initialize_LA (void) initialize_LA (void)
@@ -491,25 +490,23 @@ initialize_LA (void)
/* Compute the total number of reductions requiring a lookahead. */ /* Compute the total number of reductions requiring a lookahead. */
nLA = 0; nLA = 0;
for (state_number i = 0; i < nstates; ++i) for (state_number i = 0; i < nstates; ++i)
nLA += nLA += state_lookaheads_count (states[i],
state_lookahead_tokens_count (states[i], default_reduction_only_for_accept);
default_reduction_only_for_accept);
/* Avoid having to special case 0. */ /* Avoid having to special case 0. */
if (!nLA) if (!nLA)
nLA = 1; nLA = 1;
bitsetv pLA = LA = bitsetv_create (nLA, ntokens, BITSET_FIXED); bitsetv pLA = LA = bitsetv_create (nLA, ntokens, BITSET_FIXED);
/* Initialize the members LOOKAHEAD_TOKENS for each state whose reductions /* Initialize the members LOOKAHEADS for each state whose reductions
require lookahead tokens. */ require lookahead tokens. */
for (state_number i = 0; i < nstates; ++i) for (state_number i = 0; i < nstates; ++i)
{ {
int count = int count = state_lookaheads_count (states[i],
state_lookahead_tokens_count (states[i], default_reduction_only_for_accept);
default_reduction_only_for_accept);
if (count) if (count)
{ {
states[i]->reductions->lookahead_tokens = pLA; states[i]->reductions->lookaheads = pLA;
pLA += count; pLA += count;
} }
} }
@@ -521,7 +518,7 @@ initialize_LA (void)
`---------------------------------------------*/ `---------------------------------------------*/
static void static void
lookahead_tokens_print (FILE *out) lookaheads_print (FILE *out)
{ {
fputs ("Lookaheads:\n", out); fputs ("Lookaheads:\n", out);
for (state_number i = 0; i < nstates; ++i) for (state_number i = 0; i < nstates; ++i)
@@ -533,11 +530,11 @@ lookahead_tokens_print (FILE *out)
for (int j = 0; j < reds->num; ++j) for (int j = 0; j < reds->num; ++j)
{ {
fprintf (out, " rule %d:", reds->rules[j]->number); fprintf (out, " rule %d:", reds->rules[j]->number);
if (reds->lookahead_tokens) if (reds->lookaheads)
{ {
bitset_iterator iter; bitset_iterator iter;
int k; int k;
BITSET_FOR_EACH (iter, reds->lookahead_tokens[j], k, 0) BITSET_FOR_EACH (iter, reds->lookaheads[j], k, 0)
fprintf (out, " %s", symbols[k]->tag); fprintf (out, " %s", symbols[k]->tag);
} }
fputc ('\n', out); fputc ('\n', out);
@@ -564,10 +561,10 @@ lalr (void)
lookback = xcalloc (nLA, sizeof *lookback); lookback = xcalloc (nLA, sizeof *lookback);
build_relations (); build_relations ();
compute_follows (); compute_follows ();
compute_lookahead_tokens (); compute_lookaheads ();
if (trace_flag & trace_sets) if (trace_flag & trace_sets)
lookahead_tokens_print (stderr); lookaheads_print (stderr);
if (trace_flag & trace_automaton) if (trace_flag & trace_automaton)
{ {
begin_use_class ("trace0", stderr); begin_use_class ("trace0", stderr);
@@ -614,6 +611,6 @@ void
lalr_free (void) lalr_free (void)
{ {
for (state_number s = 0; s < nstates; ++s) for (state_number s = 0; s < nstates; ++s)
states[s]->reductions->lookahead_tokens = NULL; states[s]->reductions->lookaheads = NULL;
bitsetv_free (LA); bitsetv_free (LA);
} }
+4 -1
View File
@@ -53,6 +53,8 @@ src_bison_SOURCES = \
src/flex-scanner.h \ src/flex-scanner.h \
src/getargs.c \ src/getargs.c \
src/getargs.h \ src/getargs.h \
src/glyphs.c \
src/glyphs.h \
src/gram.c \ src/gram.c \
src/gram.h \ src/gram.h \
src/graphviz.c \ src/graphviz.c \
@@ -101,6 +103,8 @@ src_bison_SOURCES = \
src/state.h \ src/state.h \
src/state-item.c \ src/state-item.c \
src/state-item.h \ src/state-item.h \
src/strversion.c \
src/strversion.h \
src/symlist.c \ src/symlist.c \
src/symlist.h \ src/symlist.h \
src/symtab.c \ src/symtab.c \
@@ -141,7 +145,6 @@ src_bison_LDADD = \
$(LIB_SETLOCALE_NULL) \ $(LIB_SETLOCALE_NULL) \
$(LIBICONV) \ $(LIBICONV) \
$(LIBINTL) \ $(LIBINTL) \
$(LIBREADLINE) \
$(LIBTEXTSTYLE) $(LIBTEXTSTYLE)
+3 -13
View File
@@ -40,18 +40,6 @@
location const empty_loc = EMPTY_LOCATION_INIT; location const empty_loc = EMPTY_LOCATION_INIT;
static int
min_int (int a, int b)
{
return a < b ? a : b;
}
static int
max_int (int a, int b)
{
return a >= b ? a : b;
}
/* The terminal width. Not less than 40. */ /* The terminal width. Not less than 40. */
static int static int
columns (void) columns (void)
@@ -167,7 +155,9 @@ int
location_print (location loc, FILE *out) location_print (location loc, FILE *out)
{ {
int res = 0; int res = 0;
if (trace_flag & trace_locations) if (location_empty (loc))
res += fprintf (out, "(empty location)");
else if (trace_flag & trace_locations)
{ {
res += boundary_print (&loc.start, out); res += boundary_print (&loc.start, out);
res += fprintf (out, "-"); res += fprintf (out, "-");
+14 -12
View File
@@ -82,8 +82,10 @@ lssi_comparator (lssi *s1, lssi *s2)
return false; return false;
} }
typedef gl_list_t lssi_list;
static inline bool static inline bool
append_lssi (lssi *sn, Hash_table *visited, gl_list_t queue) append_lssi (lssi *sn, Hash_table *visited, lssi_list queue)
{ {
if (hash_lookup (visited, sn)) if (hash_lookup (visited, sn))
{ {
@@ -100,7 +102,7 @@ append_lssi (lssi *sn, Hash_table *visited, gl_list_t queue)
static void static void
lssi_print (lssi *l) lssi_print (lssi *l)
{ {
print_state_item (state_items + l->si, stdout); print_state_item (&state_items[l->si], stdout);
if (l->lookahead) if (l->lookahead)
{ {
printf ("FOLLOWL = { "); printf ("FOLLOWL = { ");
@@ -121,7 +123,7 @@ static bitset
eligible_state_items (state_item *target) eligible_state_items (state_item *target)
{ {
bitset result = bitset_create (nstate_items, BITSET_FIXED); bitset result = bitset_create (nstate_items, BITSET_FIXED);
gl_list_t queue = state_item_list queue =
gl_list_create (GL_LINKED_LIST, NULL, NULL, NULL, true, 1, gl_list_create (GL_LINKED_LIST, NULL, NULL, NULL, true, 1,
(const void **) &target); (const void **) &target);
while (gl_list_size (queue) > 0) while (gl_list_size (queue) > 0)
@@ -147,7 +149,7 @@ eligible_state_items (state_item *target)
* this conflict. If optimized is true, only consider parser states * this conflict. If optimized is true, only consider parser states
* that can reach the conflict state. * that can reach the conflict state.
*/ */
gl_list_t state_item_list
shortest_path_from_start (state_item_number target, symbol_number next_sym) shortest_path_from_start (state_item_number target, symbol_number next_sym)
{ {
bitset eligible = eligible_state_items (&state_items[target]); bitset eligible = eligible_state_items (&state_items[target]);
@@ -159,7 +161,7 @@ shortest_path_from_start (state_item_number target, symbol_number next_sym)
bitset il = bitset_create (nsyms, BITSET_FIXED); bitset il = bitset_create (nsyms, BITSET_FIXED);
bitset_set (il, 0); bitset_set (il, 0);
lssi *init = new_lssi (0, NULL, il, true); lssi *init = new_lssi (0, NULL, il, true);
gl_list_t queue = gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, lssi_list queue = gl_list_create_empty (GL_LINKED_LIST, NULL, NULL,
NULL, true); NULL, true);
append_lssi (init, visited, queue); append_lssi (init, visited, queue);
// breadth-first search // breadth-first search
@@ -175,7 +177,7 @@ shortest_path_from_start (state_item_number target, symbol_number next_sym)
finished = true; finished = true;
break; break;
} }
state_item *si = state_items + last; state_item *si = &state_items[last];
// Transitions don't change follow_L // Transitions don't change follow_L
if (si->trans >= 0) if (si->trans >= 0)
{ {
@@ -240,10 +242,10 @@ shortest_path_from_start (state_item_number target, symbol_number next_sym)
fputs ("Cannot find shortest path to conflict state.", stderr); fputs ("Cannot find shortest path to conflict state.", stderr);
abort (); abort ();
} }
gl_list_t res = state_item_list res =
gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true); gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true);
for (lssi *sn = n; sn != NULL; sn = sn->parent) for (lssi *sn = n; sn != NULL; sn = sn->parent)
gl_list_add_first (res, state_items + sn->si); gl_list_add_first (res, &state_items[sn->si]);
hash_free (visited); hash_free (visited);
gl_list_free (queue); gl_list_free (queue);
@@ -254,7 +256,7 @@ shortest_path_from_start (state_item_number target, symbol_number next_sym)
gl_list_iterator_t it = gl_list_iterator (res); gl_list_iterator_t it = gl_list_iterator (res);
const void *sip; const void *sip;
while (gl_list_iterator_next (&it, &sip, NULL)) while (gl_list_iterator_next (&it, &sip, NULL))
print_state_item ((state_item *) sip, stdout, ""); state_item_print ((state_item *) sip, stdout, "");
} }
return res; return res;
} }
@@ -306,10 +308,10 @@ intersect (bitset ts, bitset syms)
* Compute a list of state_items that have a production to n with respect * Compute a list of state_items that have a production to n with respect
* to its lookahead * to its lookahead
*/ */
gl_list_t state_item_list
lssi_reverse_production (const state_item *si, bitset lookahead) lssi_reverse_production (const state_item *si, bitset lookahead)
{ {
gl_list_t result = state_item_list result =
gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true); gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true);
if (SI_TRANSITION (si)) if (SI_TRANSITION (si))
return result; return result;
@@ -320,7 +322,7 @@ lssi_reverse_production (const state_item *si, bitset lookahead)
state_item_number sin; state_item_number sin;
BITSET_FOR_EACH (biter, si->revs, sin, 0) BITSET_FOR_EACH (biter, si->revs, sin, 0)
{ {
state_item *prevsi = state_items + sin; state_item *prevsi = &state_items[sin];
if (!production_allowed (prevsi, si)) if (!production_allowed (prevsi, si))
continue; continue;
bitset prev_lookahead = prevsi->lookahead; bitset prev_lookahead = prevsi->lookahead;
+3 -3
View File
@@ -32,8 +32,8 @@
* find shortest lookahead-sensitive path of state-items to target such that * find shortest lookahead-sensitive path of state-items to target such that
* next_sym is in the follow_L set of target in that position. * next_sym is in the follow_L set of target in that position.
*/ */
gl_list_t shortest_path_from_start (state_item_number target, state_item_list shortest_path_from_start (state_item_number target,
symbol_number next_sym); symbol_number next_sym);
/** /**
* Determine if the given terminal is in the given symbol set or can begin * Determine if the given terminal is in the given symbol set or can begin
@@ -52,6 +52,6 @@ bool intersect (bitset ts, bitset syms);
* to this state-item such that the resulting possible lookahead symbols are * to this state-item such that the resulting possible lookahead symbols are
* as given. * as given.
*/ */
gl_list_t lssi_reverse_production (const state_item *si, bitset lookahead); state_item_list lssi_reverse_production (const state_item *si, bitset lookahead);
#endif /* LSSI_H */ #endif /* LSSI_H */
+2
View File
@@ -38,6 +38,7 @@
#include "files.h" #include "files.h"
#include "fixits.h" #include "fixits.h"
#include "getargs.h" #include "getargs.h"
#include "glyphs.h"
#include "gram.h" #include "gram.h"
#include "ielr.h" #include "ielr.h"
#include "lalr.h" #include "lalr.h"
@@ -85,6 +86,7 @@ main (int argc, char *argv[])
atexit (close_stdout); atexit (close_stdout);
glyphs_init ();
uniqstrs_new (); uniqstrs_new ();
muscle_init (); muscle_init ();
complain_init (); complain_init ();
-3
View File
@@ -127,9 +127,6 @@ muscle_init (void)
muscle_table = hash_xinitialize (HT_INITIAL_CAPACITY, NULL, hash_muscle, muscle_table = hash_xinitialize (HT_INITIAL_CAPACITY, NULL, hash_muscle,
hash_compare_muscles, muscle_entry_free); hash_compare_muscles, muscle_entry_free);
/* Version and input file. */
MUSCLE_INSERT_STRING ("version", VERSION);
} }
+8 -4
View File
@@ -42,6 +42,7 @@
#include "scan-skel.h" #include "scan-skel.h"
#include "symtab.h" #include "symtab.h"
#include "tables.h" #include "tables.h"
#include "strversion.h"
static struct obstack format_obstack; static struct obstack format_obstack;
@@ -249,7 +250,7 @@ prepare_symbol_names (char const *muscle_name)
if (i) if (i)
obstack_1grow (&format_obstack, ' '); obstack_1grow (&format_obstack, ' ');
if (translatable) if (translatable)
obstack_sgrow (&format_obstack, "]b4_symbol_translate(["); obstack_sgrow (&format_obstack, "]b4_symbol_translate""([");
obstack_escape (&format_obstack, cp); obstack_escape (&format_obstack, cp);
if (translatable) if (translatable)
obstack_sgrow (&format_obstack, "])["); obstack_sgrow (&format_obstack, "])[");
@@ -554,7 +555,7 @@ prepare_symbol_definitions (void)
/* Map "orig NUM" to new numbers. See data/README. */ /* Map "orig NUM" to new numbers. See data/README. */
for (symbol_number i = ntokens; i < nsyms + nuseless_nonterminals; ++i) for (symbol_number i = ntokens; i < nsyms + nuseless_nonterminals; ++i)
{ {
obstack_printf (&format_obstack, "symbol(orig %d, number)", i); obstack_printf (&format_obstack, "symbol""(orig %d, number)", i);
const char *key = obstack_finish0 (&format_obstack); const char *key = obstack_finish0 (&format_obstack);
MUSCLE_INSERT_INT (key, nterm_map ? nterm_map[i - ntokens] : i); MUSCLE_INSERT_INT (key, nterm_map ? nterm_map[i - ntokens] : i);
} }
@@ -565,12 +566,12 @@ prepare_symbol_definitions (void)
const char *key; const char *key;
#define SET_KEY(Entry) \ #define SET_KEY(Entry) \
obstack_printf (&format_obstack, "symbol(%d, %s)", \ obstack_printf (&format_obstack, "symbol""(%d, %s)", \
i, Entry); \ i, Entry); \
key = obstack_finish0 (&format_obstack); key = obstack_finish0 (&format_obstack);
#define SET_KEY2(Entry, Suffix) \ #define SET_KEY2(Entry, Suffix) \
obstack_printf (&format_obstack, "symbol(%d, %s_%s)", \ obstack_printf (&format_obstack, "symbol""(%d, %s_%s)", \
i, Entry, Suffix); \ i, Entry, Suffix); \
key = obstack_finish0 (&format_obstack); key = obstack_finish0 (&format_obstack);
@@ -807,6 +808,9 @@ prepare (void)
char const *cp = getenv ("BISON_USE_PUSH_FOR_PULL"); char const *cp = getenv ("BISON_USE_PUSH_FOR_PULL");
bool use_push_for_pull_flag = cp && *cp && strtol (cp, 0, 10); bool use_push_for_pull_flag = cp && *cp && strtol (cp, 0, 10);
/* Versions. */
MUSCLE_INSERT_STRING ("version_string", VERSION);
MUSCLE_INSERT_INT ("version", strversion_to_int (VERSION));
MUSCLE_INSERT_INT ("required_version", required_version); MUSCLE_INSERT_INT ("required_version", required_version);
/* Flags. */ /* Flags. */
+45 -75
View File
@@ -1,4 +1,4 @@
/* A Bison parser, made by GNU Bison 3.6.4.130-76c4d. */ /* A Bison parser, made by GNU Bison 3.7.3.7-d831b. */
/* Bison implementation for Yacc-like parsers in C /* Bison implementation for Yacc-like parsers in C
@@ -46,10 +46,10 @@
USER NAME SPACE" below. */ USER NAME SPACE" below. */
/* Identify Bison output. */ /* Identify Bison output. */
#define YYBISON 1 #define YYBISON 30703
/* Bison version. */ /* Bison version. */
#define YYBISON_VERSION "3.6.4.130-76c4d" #define YYBISON_VERSION "3.7.3.7-d831b"
/* Skeleton name. */ /* Skeleton name. */
#define YYSKELETON_NAME "yacc.c" #define YYSKELETON_NAME "yacc.c"
@@ -149,7 +149,7 @@ enum yysymbol_kind_t
YYSYMBOL_BRACED_CODE = 41, /* "{...}" */ YYSYMBOL_BRACED_CODE = 41, /* "{...}" */
YYSYMBOL_BRACED_PREDICATE = 42, /* "%?{...}" */ YYSYMBOL_BRACED_PREDICATE = 42, /* "%?{...}" */
YYSYMBOL_BRACKETED_ID = 43, /* "[identifier]" */ YYSYMBOL_BRACKETED_ID = 43, /* "[identifier]" */
YYSYMBOL_CHAR = 44, /* "character literal" */ YYSYMBOL_CHAR_LITERAL = 44, /* "character literal" */
YYSYMBOL_COLON = 45, /* ":" */ YYSYMBOL_COLON = 45, /* ":" */
YYSYMBOL_EPILOGUE = 46, /* "epilogue" */ YYSYMBOL_EPILOGUE = 46, /* "epilogue" */
YYSYMBOL_EQUAL = 47, /* "=" */ YYSYMBOL_EQUAL = 47, /* "=" */
@@ -162,7 +162,7 @@ enum yysymbol_kind_t
YYSYMBOL_TAG = 54, /* "<tag>" */ YYSYMBOL_TAG = 54, /* "<tag>" */
YYSYMBOL_TAG_ANY = 55, /* "<*>" */ YYSYMBOL_TAG_ANY = 55, /* "<*>" */
YYSYMBOL_TAG_NONE = 56, /* "<>" */ YYSYMBOL_TAG_NONE = 56, /* "<>" */
YYSYMBOL_INT = 57, /* "integer literal" */ YYSYMBOL_INT_LITERAL = 57, /* "integer literal" */
YYSYMBOL_PERCENT_PARAM = 58, /* "%param" */ YYSYMBOL_PERCENT_PARAM = 58, /* "%param" */
YYSYMBOL_PERCENT_UNION = 59, /* "%union" */ YYSYMBOL_PERCENT_UNION = 59, /* "%union" */
YYSYMBOL_PERCENT_EMPTY = 60, /* "%empty" */ YYSYMBOL_PERCENT_EMPTY = 60, /* "%empty" */
@@ -218,8 +218,6 @@ typedef enum yysymbol_kind_t yysymbol_kind_t;
#include "system.h" #include "system.h"
#include <c-ctype.h> #include <c-ctype.h>
#include <errno.h>
#include <intprops.h>
#include <quotearg.h> #include <quotearg.h>
#include <vasnprintf.h> #include <vasnprintf.h>
#include <xmemdup0.h> #include <xmemdup0.h>
@@ -233,6 +231,11 @@ typedef enum yysymbol_kind_t yysymbol_kind_t;
#include "reader.h" #include "reader.h"
#include "scan-code.h" #include "scan-code.h"
#include "scan-gram.h" #include "scan-gram.h"
#include "strversion.h"
/* Pretend to be at least that version, to check features published
in that version while developping it. */
static const char* api_version = "3.7";
static int current_prec = 0; static int current_prec = 0;
static location current_lhs_loc; static location current_lhs_loc;
@@ -623,6 +626,7 @@ union yyalloc
/* YYNSTATES -- Number of states. */ /* YYNSTATES -- Number of states. */
#define YYNSTATES 167 #define YYNSTATES 167
/* YYMAXUTOK -- Last valid token kind. */
#define YYMAXUTOK 315 #define YYMAXUTOK 315
@@ -634,19 +638,19 @@ union yyalloc
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
static const yytype_int16 yyrline[] = static const yytype_int16 yyrline[] =
{ {
0, 308, 308, 317, 318, 322, 323, 329, 333, 338, 0, 311, 311, 320, 321, 325, 326, 332, 336, 341,
339, 340, 341, 342, 343, 344, 349, 354, 355, 356, 342, 343, 344, 345, 346, 347, 352, 357, 358, 359,
357, 358, 359, 359, 360, 361, 362, 363, 364, 365, 360, 361, 362, 362, 363, 364, 365, 366, 367, 368,
366, 367, 371, 372, 381, 382, 386, 397, 401, 405, 369, 370, 374, 375, 384, 385, 389, 400, 404, 408,
413, 423, 424, 434, 435, 441, 454, 454, 459, 459, 416, 426, 427, 437, 438, 444, 457, 457, 462, 462,
464, 468, 478, 479, 480, 481, 485, 486, 491, 492, 467, 471, 481, 482, 483, 484, 488, 489, 494, 495,
496, 497, 501, 502, 503, 516, 525, 529, 533, 541, 499, 500, 504, 505, 506, 519, 528, 532, 536, 544,
542, 546, 559, 560, 565, 566, 567, 585, 589, 593, 545, 549, 562, 563, 568, 569, 570, 588, 592, 596,
601, 603, 608, 615, 625, 629, 633, 641, 646, 658, 604, 606, 611, 618, 628, 632, 636, 644, 649, 661,
659, 665, 666, 667, 674, 674, 682, 683, 684, 689, 662, 668, 669, 670, 677, 677, 685, 686, 687, 692,
692, 694, 696, 698, 700, 702, 704, 706, 708, 713, 695, 697, 699, 701, 703, 705, 707, 709, 711, 716,
714, 723, 747, 748, 749, 750, 762, 764, 788, 793, 717, 726, 750, 751, 752, 753, 765, 767, 791, 796,
794, 799, 807, 808 797, 802, 810, 811
}; };
#endif #endif
@@ -1110,8 +1114,8 @@ tron (yyo);
{ fprintf (yyo, "[%s]", ((*yyvaluep).BRACKETED_ID)); } { fprintf (yyo, "[%s]", ((*yyvaluep).BRACKETED_ID)); }
break; break;
case YYSYMBOL_CHAR: /* "character literal" */ case YYSYMBOL_CHAR_LITERAL: /* "character literal" */
{ fputs (char_name (((*yyvaluep).CHAR)), yyo); } { fputs (char_name (((*yyvaluep).CHAR_LITERAL)), yyo); }
break; break;
case YYSYMBOL_EPILOGUE: /* "epilogue" */ case YYSYMBOL_EPILOGUE: /* "epilogue" */
@@ -1134,8 +1138,8 @@ tron (yyo);
{ fprintf (yyo, "<%s>", ((*yyvaluep).TAG)); } { fprintf (yyo, "<%s>", ((*yyvaluep).TAG)); }
break; break;
case YYSYMBOL_INT: /* "integer literal" */ case YYSYMBOL_INT_LITERAL: /* "integer literal" */
{ fprintf (yyo, "%d", ((*yyvaluep).INT)); } { fprintf (yyo, "%d", ((*yyvaluep).INT_LITERAL)); }
break; break;
case YYSYMBOL_PERCENT_PARAM: /* "%param" */ case YYSYMBOL_PERCENT_PARAM: /* "%param" */
@@ -1748,7 +1752,7 @@ yydestruct (const char *yymsg,
int int
yyparse (void) yyparse (void)
{ {
/* The lookahead symbol. */ /* Lookahead token kind. */
int yychar; int yychar;
@@ -1803,7 +1807,7 @@ YYLTYPE yylloc = yyloc_default;
int yyn; int yyn;
/* The return value of yyparse. */ /* The return value of yyparse. */
int yyresult; int yyresult;
/* Lookahead token as an internal (translated) token number. */ /* Lookahead symbol kind. */
yysymbol_kind_t yytoken = YYSYMBOL_YYEMPTY; yysymbol_kind_t yytoken = YYSYMBOL_YYEMPTY;
/* The variables used to return semantic value and location from the /* The variables used to return semantic value and location from the
action routines. */ action routines. */
@@ -2082,11 +2086,11 @@ yyreduce:
break; break;
case 12: /* prologue_declaration: "%expect" "integer literal" */ case 12: /* prologue_declaration: "%expect" "integer literal" */
{ expected_sr_conflicts = (yyvsp[0].INT); } { expected_sr_conflicts = (yyvsp[0].INT_LITERAL); }
break; break;
case 13: /* prologue_declaration: "%expect-rr" "integer literal" */ case 13: /* prologue_declaration: "%expect-rr" "integer literal" */
{ expected_rr_conflicts = (yyvsp[0].INT); } { expected_rr_conflicts = (yyvsp[0].INT_LITERAL); }
break; break;
case 14: /* prologue_declaration: "%file-prefix" "string" */ case 14: /* prologue_declaration: "%file-prefix" "string" */
@@ -2334,13 +2338,13 @@ yyreduce:
case 67: /* token_decls: "<tag>" token_decl.1 */ case 67: /* token_decls: "<tag>" token_decl.1 */
{ {
(yyval.token_decls) = symbol_list_type_set ((yyvsp[0].yykind_80), (yyvsp[-1].TAG), (yylsp[-1])); (yyval.token_decls) = symbol_list_type_set ((yyvsp[0].yykind_80), (yyvsp[-1].TAG));
} }
break; break;
case 68: /* token_decls: token_decls "<tag>" token_decl.1 */ case 68: /* token_decls: token_decls "<tag>" token_decl.1 */
{ {
(yyval.token_decls) = symbol_list_append ((yyvsp[-2].token_decls), symbol_list_type_set ((yyvsp[0].yykind_80), (yyvsp[-1].TAG), (yylsp[-1]))); (yyval.token_decls) = symbol_list_append ((yyvsp[-2].token_decls), symbol_list_type_set ((yyvsp[0].yykind_80), (yyvsp[-1].TAG)));
} }
break; break;
@@ -2391,13 +2395,13 @@ yyreduce:
case 78: /* token_decls_for_prec: "<tag>" token_decl_for_prec.1 */ case 78: /* token_decls_for_prec: "<tag>" token_decl_for_prec.1 */
{ {
(yyval.token_decls_for_prec) = symbol_list_type_set ((yyvsp[0].yykind_85), (yyvsp[-1].TAG), (yylsp[-1])); (yyval.token_decls_for_prec) = symbol_list_type_set ((yyvsp[0].yykind_85), (yyvsp[-1].TAG));
} }
break; break;
case 79: /* token_decls_for_prec: token_decls_for_prec "<tag>" token_decl_for_prec.1 */ case 79: /* token_decls_for_prec: token_decls_for_prec "<tag>" token_decl_for_prec.1 */
{ {
(yyval.token_decls_for_prec) = symbol_list_append ((yyvsp[-2].token_decls_for_prec), symbol_list_type_set ((yyvsp[0].yykind_85), (yyvsp[-1].TAG), (yylsp[-1]))); (yyval.token_decls_for_prec) = symbol_list_append ((yyvsp[-2].token_decls_for_prec), symbol_list_type_set ((yyvsp[0].yykind_85), (yyvsp[-1].TAG)));
} }
break; break;
@@ -2426,13 +2430,13 @@ yyreduce:
case 85: /* symbol_decls: "<tag>" symbol_decl.1 */ case 85: /* symbol_decls: "<tag>" symbol_decl.1 */
{ {
(yyval.symbol_decls) = symbol_list_type_set ((yyvsp[0].yykind_88), (yyvsp[-1].TAG), (yylsp[-1])); (yyval.symbol_decls) = symbol_list_type_set ((yyvsp[0].yykind_88), (yyvsp[-1].TAG));
} }
break; break;
case 86: /* symbol_decls: symbol_decls "<tag>" symbol_decl.1 */ case 86: /* symbol_decls: symbol_decls "<tag>" symbol_decl.1 */
{ {
(yyval.symbol_decls) = symbol_list_append ((yyvsp[-2].symbol_decls), symbol_list_type_set ((yyvsp[0].yykind_88), (yyvsp[-1].TAG), (yylsp[-1]))); (yyval.symbol_decls) = symbol_list_append ((yyvsp[-2].symbol_decls), symbol_list_type_set ((yyvsp[0].yykind_88), (yyvsp[-1].TAG)));
} }
break; break;
@@ -2501,7 +2505,7 @@ yyreduce:
break; break;
case 105: /* rhs: rhs "%dprec" "integer literal" */ case 105: /* rhs: rhs "%dprec" "integer literal" */
{ grammar_current_rule_dprec_set ((yyvsp[0].INT), (yylsp[0])); } { grammar_current_rule_dprec_set ((yyvsp[0].INT_LITERAL), (yylsp[0])); }
break; break;
case 106: /* rhs: rhs "%merge" "<tag>" */ case 106: /* rhs: rhs "%merge" "<tag>" */
@@ -2509,11 +2513,11 @@ yyreduce:
break; break;
case 107: /* rhs: rhs "%expect" "integer literal" */ case 107: /* rhs: rhs "%expect" "integer literal" */
{ grammar_current_rule_expect_sr ((yyvsp[0].INT), (yylsp[0])); } { grammar_current_rule_expect_sr ((yyvsp[0].INT_LITERAL), (yylsp[0])); }
break; break;
case 108: /* rhs: rhs "%expect-rr" "integer literal" */ case 108: /* rhs: rhs "%expect-rr" "integer literal" */
{ grammar_current_rule_expect_rr ((yyvsp[0].INT), (yylsp[0])); } { grammar_current_rule_expect_rr ((yyvsp[0].INT_LITERAL), (yylsp[0])); }
break; break;
case 109: /* named_ref.opt: %empty */ case 109: /* named_ref.opt: %empty */
@@ -2561,9 +2565,9 @@ yyreduce:
location loc = muscle_percent_define_get_loc (var); location loc = muscle_percent_define_get_loc (var);
subcomplain (&loc, complaint, _("definition of %s"), var); subcomplain (&loc, complaint, _("definition of %s"), var);
} }
(yyval.id) = symbol_get (char_name ((yyvsp[0].CHAR)), (yylsp[0])); (yyval.id) = symbol_get (char_name ((yyvsp[0].CHAR_LITERAL)), (yylsp[0]));
symbol_class_set ((yyval.id), token_sym, (yylsp[0]), false); symbol_class_set ((yyval.id), token_sym, (yylsp[0]), false);
symbol_code_set ((yyval.id), (yyvsp[0].CHAR), (yylsp[0])); symbol_code_set ((yyval.id), (yyvsp[0].CHAR_LITERAL), (yylsp[0]));
} }
break; break;
@@ -3027,41 +3031,11 @@ handle_pure_parser (location const *loc, char const *directive)
} }
/* Convert VERSION into an int (MAJOR * 100 + MINOR). Return -1 on
errors.
Changes of behavior are only on minor version changes, so "3.0.5"
is the same as "3.0": 300. */
static int
str_to_version (char const *version)
{
IGNORE_TYPE_LIMITS_BEGIN
int res = 0;
errno = 0;
char *cp = NULL;
long major = strtol (version, &cp, 10);
if (errno || cp == version || *cp != '.' || major < 0
|| INT_MULTIPLY_WRAPV (major, 100, &res))
return -1;
++cp;
char *cp1 = NULL;
long minor = strtol (cp, &cp1, 10);
if (errno || cp1 == cp || (*cp1 != '\0' && *cp1 != '.')
|| ! (0 <= minor && minor < 100)
|| INT_ADD_WRAPV (minor, res, &res))
return -1;
IGNORE_TYPE_LIMITS_END
return res;
}
static void static void
handle_require (location const *loc, char const *version_quoted) handle_require (location const *loc, char const *version_quoted)
{ {
char *version = unquote (version_quoted); char *version = unquote (version_quoted);
required_version = str_to_version (version); required_version = strversion_to_int (version);
if (required_version == -1) if (required_version == -1)
{ {
complain (loc, complaint, _("invalid version requirement: %s"), complain (loc, complaint, _("invalid version requirement: %s"),
@@ -3070,9 +3044,6 @@ handle_require (location const *loc, char const *version_quoted)
} }
else else
{ {
/* Pretend to be at least that version, to check features published
in that version while developping it. */
const char* api_version = "3.6";
const char* package_version = const char* package_version =
0 < strverscmp (api_version, PACKAGE_VERSION) 0 < strverscmp (api_version, PACKAGE_VERSION)
? api_version : PACKAGE_VERSION; ? api_version : PACKAGE_VERSION;
@@ -3145,8 +3116,7 @@ char_name (char c)
} }
} }
static static void
void
current_lhs (symbol *sym, location loc, named_ref *ref) current_lhs (symbol *sym, location loc, named_ref *ref)
{ {
current_lhs_symbol = sym; current_lhs_symbol = sym;
+5 -5
View File
@@ -1,4 +1,4 @@
/* A Bison parser, made by GNU Bison 3.6.4.130-76c4d. */ /* A Bison parser, made by GNU Bison 3.7.3.7-d831b. */
/* Bison interface for Yacc-like parsers in C /* Bison interface for Yacc-like parsers in C
@@ -123,7 +123,7 @@ extern int gram_debug;
BRACED_CODE = 41, /* "{...}" */ BRACED_CODE = 41, /* "{...}" */
BRACED_PREDICATE = 42, /* "%?{...}" */ BRACED_PREDICATE = 42, /* "%?{...}" */
BRACKETED_ID = 43, /* "[identifier]" */ BRACKETED_ID = 43, /* "[identifier]" */
CHAR = 44, /* "character literal" */ CHAR_LITERAL = 44, /* "character literal" */
COLON = 45, /* ":" */ COLON = 45, /* ":" */
EPILOGUE = 46, /* "epilogue" */ EPILOGUE = 46, /* "epilogue" */
EQUAL = 47, /* "=" */ EQUAL = 47, /* "=" */
@@ -136,7 +136,7 @@ extern int gram_debug;
TAG = 54, /* "<tag>" */ TAG = 54, /* "<tag>" */
TAG_ANY = 55, /* "<*>" */ TAG_ANY = 55, /* "<*>" */
TAG_NONE = 56, /* "<>" */ TAG_NONE = 56, /* "<>" */
INT = 57, /* "integer literal" */ INT_LITERAL = 57, /* "integer literal" */
PERCENT_PARAM = 58, /* "%param" */ PERCENT_PARAM = 58, /* "%param" */
PERCENT_UNION = 59, /* "%union" */ PERCENT_UNION = 59, /* "%union" */
PERCENT_EMPTY = 60 /* "%empty" */ PERCENT_EMPTY = 60 /* "%empty" */
@@ -156,7 +156,7 @@ union GRAM_STYPE
char* EPILOGUE; /* "epilogue" */ char* EPILOGUE; /* "epilogue" */
char* PROLOGUE; /* "%{...%}" */ char* PROLOGUE; /* "%{...%}" */
code_props_type code_props_type; /* code_props_type */ code_props_type code_props_type; /* code_props_type */
int INT; /* "integer literal" */ int INT_LITERAL; /* "integer literal" */
int yykind_82; /* int.opt */ int yykind_82; /* int.opt */
named_ref* yykind_95; /* named_ref.opt */ named_ref* yykind_95; /* named_ref.opt */
param_type PERCENT_PARAM; /* "%param" */ param_type PERCENT_PARAM; /* "%param" */
@@ -188,7 +188,7 @@ union GRAM_STYPE
uniqstr yykind_74; /* tag.opt */ uniqstr yykind_74; /* tag.opt */
uniqstr tag; /* tag */ uniqstr tag; /* tag */
uniqstr variable; /* variable */ uniqstr variable; /* variable */
unsigned char CHAR; /* "character literal" */ unsigned char CHAR_LITERAL; /* "character literal" */
value_type value; /* value */ value_type value; /* value */
+25 -56
View File
@@ -42,8 +42,6 @@
#include "system.h" #include "system.h"
#include <c-ctype.h> #include <c-ctype.h>
#include <errno.h>
#include <intprops.h>
#include <quotearg.h> #include <quotearg.h>
#include <vasnprintf.h> #include <vasnprintf.h>
#include <xmemdup0.h> #include <xmemdup0.h>
@@ -57,6 +55,11 @@
#include "reader.h" #include "reader.h"
#include "scan-code.h" #include "scan-code.h"
#include "scan-gram.h" #include "scan-gram.h"
#include "strversion.h"
/* Pretend to be at least that version, to check features published
in that version while developping it. */
static const char* api_version = "3.7";
static int current_prec = 0; static int current_prec = 0;
static location current_lhs_loc; static location current_lhs_loc;
@@ -210,7 +213,7 @@
BRACED_CODE "{...}" BRACED_CODE "{...}"
BRACED_PREDICATE "%?{...}" BRACED_PREDICATE "%?{...}"
BRACKETED_ID _("[identifier]") BRACKETED_ID _("[identifier]")
CHAR _("character literal") CHAR_LITERAL _("character literal")
COLON ":" COLON ":"
EPILOGUE _("epilogue") EPILOGUE _("epilogue")
EQUAL "=" EQUAL "="
@@ -228,7 +231,7 @@
%code pre-printer {tron (yyo);} %code pre-printer {tron (yyo);}
%code post-printer {troff (yyo);} %code post-printer {troff (yyo);}
%type <unsigned char> CHAR %type <unsigned char> CHAR_LITERAL
%printer { fputs (char_name ($$), yyo); } <unsigned char> %printer { fputs (char_name ($$), yyo); } <unsigned char>
%type <char*> "{...}" "%?{...}" "%{...%}" EPILOGUE STRING TSTRING %type <char*> "{...}" "%?{...}" "%{...%}" EPILOGUE STRING TSTRING
@@ -245,7 +248,7 @@
%printer { fprintf (yyo, "%%%s", $$); } PERCENT_FLAG %printer { fprintf (yyo, "%%%s", $$); } PERCENT_FLAG
%printer { fprintf (yyo, "<%s>", $$); } TAG tag %printer { fprintf (yyo, "<%s>", $$); } TAG tag
%token <int> INT _("integer literal") %token <int> INT_LITERAL _("integer literal")
%printer { fprintf (yyo, "%d", $$); } <int> %printer { fprintf (yyo, "%d", $$); } <int>
%type <symbol*> id id_colon string_as_id symbol token_decl token_decl_for_prec %type <symbol*> id id_colon string_as_id symbol token_decl token_decl_for_prec
@@ -338,8 +341,8 @@ prologue_declaration:
| "%defines" { defines_flag = true; } | "%defines" { defines_flag = true; }
| "%defines" STRING { handle_defines ($2); } | "%defines" STRING { handle_defines ($2); }
| "%error-verbose" { handle_error_verbose (&@$, $1); } | "%error-verbose" { handle_error_verbose (&@$, $1); }
| "%expect" INT { expected_sr_conflicts = $2; } | "%expect" INT_LITERAL { expected_sr_conflicts = $2; }
| "%expect-rr" INT { expected_rr_conflicts = $2; } | "%expect-rr" INT_LITERAL { expected_rr_conflicts = $2; }
| "%file-prefix" STRING { handle_file_prefix (&@$, &@1, $1, $2); } | "%file-prefix" STRING { handle_file_prefix (&@$, &@1, $1, $2); }
| "%glr-parser" | "%glr-parser"
{ {
@@ -528,11 +531,11 @@ token_decls:
} }
| TAG token_decl.1[syms] | TAG token_decl.1[syms]
{ {
$$ = symbol_list_type_set ($syms, $TAG, @TAG); $$ = symbol_list_type_set ($syms, $TAG);
} }
| token_decls TAG token_decl.1[syms] | token_decls TAG token_decl.1[syms]
{ {
$$ = symbol_list_append ($1, symbol_list_type_set ($syms, $TAG, @TAG)); $$ = symbol_list_append ($1, symbol_list_type_set ($syms, $TAG));
} }
; ;
@@ -557,7 +560,7 @@ token_decl:
%type <int> int.opt; %type <int> int.opt;
int.opt: int.opt:
%empty { $$ = -1; } %empty { $$ = -1; }
| INT | INT_LITERAL
; ;
%type <symbol*> alias; %type <symbol*> alias;
@@ -588,11 +591,11 @@ token_decls_for_prec:
} }
| TAG token_decl_for_prec.1[syms] | TAG token_decl_for_prec.1[syms]
{ {
$$ = symbol_list_type_set ($syms, $TAG, @TAG); $$ = symbol_list_type_set ($syms, $TAG);
} }
| token_decls_for_prec TAG token_decl_for_prec.1[syms] | token_decls_for_prec TAG token_decl_for_prec.1[syms]
{ {
$$ = symbol_list_append ($1, symbol_list_type_set ($syms, $TAG, @TAG)); $$ = symbol_list_append ($1, symbol_list_type_set ($syms, $TAG));
} }
; ;
@@ -628,11 +631,11 @@ symbol_decls:
} }
| TAG symbol_decl.1[syms] | TAG symbol_decl.1[syms]
{ {
$$ = symbol_list_type_set ($syms, $TAG, @TAG); $$ = symbol_list_type_set ($syms, $TAG);
} }
| symbol_decls TAG symbol_decl.1[syms] | symbol_decls TAG symbol_decl.1[syms]
{ {
$$ = symbol_list_append ($1, symbol_list_type_set ($syms, $TAG, @TAG)); $$ = symbol_list_append ($1, symbol_list_type_set ($syms, $TAG));
} }
; ;
@@ -691,21 +694,21 @@ rhs:
current_lhs_named_ref); } current_lhs_named_ref); }
| rhs symbol named_ref.opt | rhs symbol named_ref.opt
{ grammar_current_rule_symbol_append ($2, @2, $3); } { grammar_current_rule_symbol_append ($2, @2, $3); }
| rhs tag.opt "{...}"[act] named_ref.opt[name] | rhs tag.opt "{...}"[action] named_ref.opt[name]
{ grammar_current_rule_action_append ($act, @act, $name, $[tag.opt]); } { grammar_current_rule_action_append ($action, @action, $name, $[tag.opt]); }
| rhs "%?{...}" | rhs "%?{...}"
{ grammar_current_rule_predicate_append ($2, @2); } { grammar_current_rule_predicate_append ($2, @2); }
| rhs "%empty" | rhs "%empty"
{ grammar_current_rule_empty_set (@2); } { grammar_current_rule_empty_set (@2); }
| rhs "%prec" symbol | rhs "%prec" symbol
{ grammar_current_rule_prec_set ($3, @3); } { grammar_current_rule_prec_set ($3, @3); }
| rhs "%dprec" INT | rhs "%dprec" INT_LITERAL
{ grammar_current_rule_dprec_set ($3, @3); } { grammar_current_rule_dprec_set ($3, @3); }
| rhs "%merge" TAG | rhs "%merge" TAG
{ grammar_current_rule_merge_set ($3, @3); } { grammar_current_rule_merge_set ($3, @3); }
| rhs "%expect" INT | rhs "%expect" INT_LITERAL
{ grammar_current_rule_expect_sr ($3, @3); } { grammar_current_rule_expect_sr ($3, @3); }
| rhs "%expect-rr" INT | rhs "%expect-rr" INT_LITERAL
{ grammar_current_rule_expect_rr ($3, @3); } { grammar_current_rule_expect_rr ($3, @3); }
; ;
@@ -761,7 +764,7 @@ value:
id: id:
ID ID
{ $$ = symbol_from_uniqstr ($1, @1); } { $$ = symbol_from_uniqstr ($1, @1); }
| CHAR | CHAR_LITERAL
{ {
const char *var = "api.token.raw"; const char *var = "api.token.raw";
if (current_class == nterm_sym) if (current_class == nterm_sym)
@@ -1039,41 +1042,11 @@ handle_pure_parser (location const *loc, char const *directive)
} }
/* Convert VERSION into an int (MAJOR * 100 + MINOR). Return -1 on
errors.
Changes of behavior are only on minor version changes, so "3.0.5"
is the same as "3.0": 300. */
static int
str_to_version (char const *version)
{
IGNORE_TYPE_LIMITS_BEGIN
int res = 0;
errno = 0;
char *cp = NULL;
long major = strtol (version, &cp, 10);
if (errno || cp == version || *cp != '.' || major < 0
|| INT_MULTIPLY_WRAPV (major, 100, &res))
return -1;
++cp;
char *cp1 = NULL;
long minor = strtol (cp, &cp1, 10);
if (errno || cp1 == cp || (*cp1 != '\0' && *cp1 != '.')
|| ! (0 <= minor && minor < 100)
|| INT_ADD_WRAPV (minor, res, &res))
return -1;
IGNORE_TYPE_LIMITS_END
return res;
}
static void static void
handle_require (location const *loc, char const *version_quoted) handle_require (location const *loc, char const *version_quoted)
{ {
char *version = unquote (version_quoted); char *version = unquote (version_quoted);
required_version = str_to_version (version); required_version = strversion_to_int (version);
if (required_version == -1) if (required_version == -1)
{ {
complain (loc, complaint, _("invalid version requirement: %s"), complain (loc, complaint, _("invalid version requirement: %s"),
@@ -1082,9 +1055,6 @@ handle_require (location const *loc, char const *version_quoted)
} }
else else
{ {
/* Pretend to be at least that version, to check features published
in that version while developping it. */
const char* api_version = "3.6";
const char* package_version = const char* package_version =
0 < strverscmp (api_version, PACKAGE_VERSION) 0 < strverscmp (api_version, PACKAGE_VERSION)
? api_version : PACKAGE_VERSION; ? api_version : PACKAGE_VERSION;
@@ -1157,8 +1127,7 @@ char_name (char c)
} }
} }
static static void
void
current_lhs (symbol *sym, location loc, named_ref *ref) current_lhs (symbol *sym, location loc, named_ref *ref)
{ {
current_lhs_symbol = sym; current_lhs_symbol = sym;
+47 -53
View File
@@ -28,19 +28,19 @@
#include "lssi.h" #include "lssi.h"
#include "nullable.h" #include "nullable.h"
typedef struct parse_state struct parse_state
{ {
// path of state-items the parser has traversed // Path of state-items the parser has traversed.
struct si_chunk struct si_chunk
{ {
// elements newly added in this chunk // Elements newly added in this chunk.
gl_list_t contents; state_item_list contents;
// properties of the linked list this chunk represents // Properties of the linked list this chunk represents.
const state_item *head_elt; const state_item *head_elt;
const state_item *tail_elt; const state_item *tail_elt;
size_t total_size; size_t total_size;
} state_items; } state_items;
// list of derivations of the symbols // List of derivations of the symbols.
struct deriv_chunk struct deriv_chunk
{ {
derivation_list contents; derivation_list contents;
@@ -50,18 +50,15 @@ typedef struct parse_state
} derivs; } derivs;
struct parse_state *parent; struct parse_state *parent;
int reference_count; int reference_count;
// incremented during productions, // Incremented during productions, decremented during reductions.
// decremented during reductions
int depth; int depth;
// whether the contents of the chunks should be // Whether the contents of the chunks should be prepended or
// prepended or appended to the list the chunks // appended to the list the chunks represent.
// represent
bool prepend; bool prepend;
// causes chunk contents to be freed when the // Causes chunk contents to be freed when the reference count is
// reference count is one. Used when only the chunk metadata // one. Used when only the chunk metadata will be needed.
// will be needed.
bool free_contents_early; bool free_contents_early;
} parse_state; };
static void static void
@@ -135,7 +132,7 @@ static parse_state *
copy_parse_state (bool prepend, parse_state *parent) copy_parse_state (bool prepend, parse_state *parent)
{ {
parse_state *res = xmalloc (sizeof *res); parse_state *res = xmalloc (sizeof *res);
memcpy (res, parent, sizeof *res); *res = *parent;
res->state_items.contents res->state_items.contents
= gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true); = gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true);
res->derivs.contents = derivation_list_new (); res->derivs.contents = derivation_list_new ();
@@ -252,7 +249,7 @@ parse_state_completed_steps (const parse_state *ps, int *shifts, int *production
while (root_ps->parent) while (root_ps->parent)
root_ps = root_ps->parent; root_ps = root_ps->parent;
gl_list_t sis = root_ps->state_items.contents; state_item_list sis = root_ps->state_items.contents;
int count = 0; int count = 0;
state_item *last = NULL; state_item *last = NULL;
@@ -337,19 +334,17 @@ parser_pop (parse_state *ps, int deriv_index,
for (int i = 0; i < 4; ++i) for (int i = 0; i < 4; ++i)
chunks[i] = gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true); chunks[i] = gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true);
for (parse_state *pn = ps; pn != NULL; pn = pn->parent) for (parse_state *pn = ps; pn != NULL; pn = pn->parent)
{ if (pn->prepend)
if (pn->prepend) {
{ gl_list_add_last (chunks[0], pn->state_items.contents);
gl_list_add_last (chunks[0], pn->state_items.contents); gl_list_add_last (chunks[2], pn->derivs.contents);
gl_list_add_last (chunks[2], pn->derivs.contents); }
} else
else {
{ gl_list_add_first (chunks[1], pn->state_items.contents);
gl_list_add_first (chunks[1], pn->state_items.contents); gl_list_add_first (chunks[3], pn->derivs.contents);
gl_list_add_first (chunks[3], pn->derivs.contents); }
} derivation_list popped_derivs = derivation_list_new ();
}
gl_list_t popped_derivs = derivation_list_new ();
gl_list_t ret_chunks[4] = { ret->state_items.contents, NULL, gl_list_t ret_chunks[4] = { ret->state_items.contents, NULL,
ret->derivs.contents, popped_derivs ret->derivs.contents, popped_derivs
}; };
@@ -390,7 +385,7 @@ parser_pop (parse_state *ps, int deriv_index,
} }
void void
parse_state_lists (parse_state *ps, gl_list_t *sitems, parse_state_lists (parse_state *ps, state_item_list *sitems,
derivation_list *derivs) derivation_list *derivs)
{ {
parse_state *temp = empty_parse_state (); parse_state *temp = empty_parse_state ();
@@ -418,12 +413,12 @@ nullable_closure (parse_state *ps, state_item *si, parse_state_list state_list)
for (state_item_number sin = si->trans; sin != -1; for (state_item_number sin = si->trans; sin != -1;
prev_sin = sin, sin = state_items[sin].trans) prev_sin = sin, sin = state_items[sin].trans)
{ {
state_item *psi = state_items + prev_sin; state_item *psi = &state_items[prev_sin];
symbol_number sp = item_number_as_symbol_number (*psi->item); symbol_number sp = item_number_as_symbol_number (*psi->item);
if (ISTOKEN (sp) || !nullable[sp - ntokens]) if (ISTOKEN (sp) || !nullable[sp - ntokens])
break; break;
state_item *nsi = state_items + sin; state_item *nsi = &state_items[sin];
current_ps = copy_parse_state (false, current_ps); current_ps = copy_parse_state (false, current_ps);
ps_si_append (current_ps, nsi); ps_si_append (current_ps, nsi);
ps_derivs_append (current_ps, derivation_new (sp, derivation_list_new ())); ps_derivs_append (current_ps, derivation_new (sp, derivation_list_new ()));
@@ -431,26 +426,25 @@ nullable_closure (parse_state *ps, state_item *si, parse_state_list state_list)
} }
} }
gl_list_t parse_state_list
simulate_transition (parse_state *ps) simulate_transition (parse_state *ps)
{ {
const state_item *si = ps->state_items.tail_elt; const state_item *si = ps->state_items.tail_elt;
symbol_number sym = item_number_as_symbol_number (*si->item); symbol_number sym = item_number_as_symbol_number (*si->item);
// Transition on the same next symbol, taking nullable // Transition on the same next symbol, taking nullable
// symbols into account. // symbols into account.
gl_list_t result = parse_state_list_new (); parse_state_list result = parse_state_list_new ();
state_item_number si_next = si->trans; state_item_number si_next = si->trans;
// check for disabled transition, shouldn't happen // Check for disabled transition, shouldn't happen as any
// as any state_items that lead to these should be // state_items that lead to these should be disabled.
// disabled.
if (si_next < 0) if (si_next < 0)
return result; return result;
parse_state *next_ps = copy_parse_state (false, ps); parse_state *next_ps = copy_parse_state (false, ps);
ps_si_append (next_ps, state_items + si_next); ps_si_append (next_ps, &state_items[si_next]);
ps_derivs_append (next_ps, derivation_new_leaf (sym)); ps_derivs_append (next_ps, derivation_new_leaf (sym));
parse_state_list_append (result, next_ps); parse_state_list_append (result, next_ps);
nullable_closure (next_ps, state_items + si_next, result); nullable_closure (next_ps, &state_items[si_next], result);
return result; return result;
} }
@@ -473,10 +467,10 @@ compatible (symbol_number sym1, symbol_number sym2)
return false; return false;
} }
gl_list_t parse_state_list
simulate_production (parse_state *ps, symbol_number compat_sym) simulate_production (parse_state *ps, symbol_number compat_sym)
{ {
gl_list_t result = parse_state_list_new (); parse_state_list result = parse_state_list_new ();
const state_item *si = parse_state_tail (ps); const state_item *si = parse_state_tail (ps);
if (si->prods) if (si->prods)
{ {
@@ -486,7 +480,7 @@ simulate_production (parse_state *ps, symbol_number compat_sym)
{ {
// Take production step only if lhs is not nullable and // Take production step only if lhs is not nullable and
// if first rhs symbol is compatible with compat_sym // if first rhs symbol is compatible with compat_sym
state_item *next = state_items + sin; state_item *next = &state_items[sin];
item_number *itm1 = next->item; item_number *itm1 = next->item;
if (!compatible (*itm1, compat_sym) || !production_allowed (si, next)) if (!compatible (*itm1, compat_sym) || !production_allowed (si, next))
continue; continue;
@@ -504,10 +498,10 @@ simulate_production (parse_state *ps, symbol_number compat_sym)
// simulates a reduction on the given parse state, conflict_item is the // simulates a reduction on the given parse state, conflict_item is the
// item associated with ps's conflict. symbol_set is a lookahead set this // item associated with ps's conflict. symbol_set is a lookahead set this
// reduction must be compatible with // reduction must be compatible with
gl_list_t parse_state_list
simulate_reduction (parse_state *ps, int rule_len, bitset symbol_set) simulate_reduction (parse_state *ps, int rule_len, bitset symbol_set)
{ {
gl_list_t result = parse_state_list_new (); parse_state_list result = parse_state_list_new ();
int s_size = ps->state_items.total_size; int s_size = ps->state_items.total_size;
int d_size = ps->derivs.total_size; int d_size = ps->derivs.total_size;
@@ -529,7 +523,7 @@ simulate_reduction (parse_state *ps, int rule_len, bitset symbol_set)
if (s_size != rule_len + 1) if (s_size != rule_len + 1)
{ {
state_item *tail = (state_item *) new_root->state_items.tail_elt; state_item *tail = (state_item *) new_root->state_items.tail_elt;
ps_si_append (new_root, state_items + tail->trans); ps_si_append (new_root, &state_items[tail->trans]);
parse_state_list_append (result, new_root); parse_state_list_append (result, new_root);
} }
else else
@@ -537,7 +531,7 @@ simulate_reduction (parse_state *ps, int rule_len, bitset symbol_set)
// The head state_item is a production item, so we need to prepend // The head state_item is a production item, so we need to prepend
// with possible source state-items. // with possible source state-items.
const state_item *head = ps->state_items.head_elt; const state_item *head = ps->state_items.head_elt;
gl_list_t prev = lssi_reverse_production (head, symbol_set); state_item_list prev = lssi_reverse_production (head, symbol_set);
// TODO: better understand what causes this case. // TODO: better understand what causes this case.
if (gl_list_size (prev) == 0) if (gl_list_size (prev) == 0)
{ {
@@ -560,7 +554,7 @@ simulate_reduction (parse_state *ps, int rule_len, bitset symbol_set)
copy = copy_parse_state (false, copy); copy = copy_parse_state (false, copy);
struct si_chunk *sis = &copy->state_items; struct si_chunk *sis = &copy->state_items;
const state_item *tail = sis->tail_elt; const state_item *tail = sis->tail_elt;
ps_si_append (copy, state_items + tail->trans); ps_si_append (copy, &state_items[tail->trans]);
parse_state_list_append (result, copy); parse_state_list_append (result, copy);
nullable_closure (copy, (state_item *) sis->tail_elt, result); nullable_closure (copy, (state_item *) sis->tail_elt, result);
} }
@@ -570,10 +564,10 @@ simulate_reduction (parse_state *ps, int rule_len, bitset symbol_set)
return result; return result;
} }
gl_list_t parse_state_list
parser_prepend (parse_state *ps) parser_prepend (parse_state *ps)
{ {
gl_list_t res = parse_state_list_new (); parse_state_list res = parse_state_list_new ();
const state_item *head = ps->state_items.head_elt; const state_item *head = ps->state_items.head_elt;
symbol_number prepend_sym = symbol_number prepend_sym =
item_number_as_symbol_number (*(head->item - 1)); item_number_as_symbol_number (*(head->item - 1));
@@ -582,7 +576,7 @@ parser_prepend (parse_state *ps)
BITSET_FOR_EACH (biter, head->revs, sin, 0) BITSET_FOR_EACH (biter, head->revs, sin, 0)
{ {
parse_state *copy = copy_parse_state (true, ps); parse_state *copy = copy_parse_state (true, ps);
ps_si_prepend (copy, state_items + sin); ps_si_prepend (copy, &state_items[sin]);
if (SI_TRANSITION (head)) if (SI_TRANSITION (head))
ps_derivs_prepend (copy, derivation_new_leaf (prepend_sym)); ps_derivs_prepend (copy, derivation_new_leaf (prepend_sym));
parse_state_list_append (res, copy); parse_state_list_append (res, copy);
@@ -596,8 +590,8 @@ print_parse_state (parse_state *ps)
FILE *out = stderr; FILE *out = stderr;
fprintf (out, "(size %zu depth %d rc %d)\n", fprintf (out, "(size %zu depth %d rc %d)\n",
ps->state_items.total_size, ps->depth, ps->reference_count); ps->state_items.total_size, ps->depth, ps->reference_count);
print_state_item (ps->state_items.head_elt, out, ""); state_item_print (ps->state_items.head_elt, out, "");
print_state_item (ps->state_items.tail_elt, out, ""); state_item_print (ps->state_items.tail_elt, out, "");
if (ps->derivs.total_size > 0) if (ps->derivs.total_size > 0)
derivation_print (ps->derivs.head_elt, out, ""); derivation_print (ps->derivs.head_elt, out, "");
putc ('\n', out); putc ('\n', out);
+1 -1
View File
@@ -113,7 +113,7 @@ int parse_state_length (const parse_state *ps);
int parse_state_depth (const parse_state *ps); int parse_state_depth (const parse_state *ps);
/* returns the linked lists that the parse state is supposed to represent */ /* returns the linked lists that the parse state is supposed to represent */
void parse_state_lists (parse_state *ps, gl_list_t *state_items, void parse_state_lists (parse_state *ps, state_item_list *state_items,
derivation_list *derivs); derivation_list *derivs);
/* various functions that return a list of states based off of /* various functions that return a list of states based off of
+3 -3
View File
@@ -96,7 +96,7 @@ print_core (struct obstack *oout, state *s)
obstack_sgrow (oout, " %empty"); obstack_sgrow (oout, " %empty");
/* Experimental feature: display the lookahead tokens. */ /* Experimental feature: display the lookahead tokens. */
if (report_flag & report_lookahead_tokens if (report_flag & report_lookaheads
&& item_number_is_rule_number (*sp1)) && item_number_is_rule_number (*sp1))
{ {
/* Find the reduction we are handling. */ /* Find the reduction we are handling. */
@@ -104,13 +104,13 @@ print_core (struct obstack *oout, state *s)
int redno = state_reduction_find (s, r); int redno = state_reduction_find (s, r);
/* Print them if there are. */ /* Print them if there are. */
if (reds->lookahead_tokens && redno != -1) if (reds->lookaheads && redno != -1)
{ {
bitset_iterator biter; bitset_iterator biter;
int k; int k;
char const *sep = ""; char const *sep = "";
obstack_sgrow (oout, " ["); obstack_sgrow (oout, " [");
BITSET_FOR_EACH (biter, reds->lookahead_tokens[redno], k, 0) BITSET_FOR_EACH (biter, reds->lookaheads[redno], k, 0)
{ {
obstack_sgrow (oout, sep); obstack_sgrow (oout, sep);
obstack_backslash (oout, symbols[k]->tag); obstack_backslash (oout, symbols[k]->tag);
+29 -22
View File
@@ -86,12 +86,12 @@ print_core (FILE *out, int level, state *s)
reductions *reds = s->reductions; reductions *reds = s->reductions;
int red = state_reduction_find (s, r); int red = state_reduction_find (s, r);
/* Print item with lookaheads if there are. */ /* Print item with lookaheads if there are. */
if (reds->lookahead_tokens && red != -1) if (reds->lookaheads && red != -1)
{ {
xml_printf (out, level + 1, xml_printf (out, level + 1,
"<item rule-number=\"%d\" dot=\"%d\">", "<item rule-number=\"%d\" dot=\"%d\">",
r->number, sp1 - sp); r->number, sp1 - sp);
state_rule_lookahead_tokens_print_xml (s, r, state_rule_lookaheads_print_xml (s, r,
out, level + 2); out, level + 2);
xml_puts (out, level + 1, "</item>"); xml_puts (out, level + 1, "</item>");
printed = true; printed = true;
@@ -202,26 +202,26 @@ print_errs (FILE *out, int level, state *s)
} }
/*-------------------------------------------------------------------------. /*-------------------------------------------------------------------.
| Report a reduction of RULE on LOOKAHEAD_TOKEN (which can be 'default'). | | Report a reduction of RULE on LOOKAHEAD (which can be 'default'). |
| If not ENABLED, the rule is masked by a shift or a reduce (S/R and | | If not ENABLED, the rule is masked by a shift or a reduce (S/R and |
| R/R conflicts). | | R/R conflicts). |
`-------------------------------------------------------------------------*/ `-------------------------------------------------------------------*/
static void static void
print_reduction (FILE *out, int level, char const *lookahead_token, print_reduction (FILE *out, int level, char const *lookahead,
rule *r, bool enabled) rule *r, bool enabled)
{ {
if (r->number) if (r->number)
xml_printf (out, level, xml_printf (out, level,
"<reduction symbol=\"%s\" rule=\"%d\" enabled=\"%s\"/>", "<reduction symbol=\"%s\" rule=\"%d\" enabled=\"%s\"/>",
xml_escape (lookahead_token), xml_escape (lookahead),
r->number, r->number,
enabled ? "true" : "false"); enabled ? "true" : "false");
else else
xml_printf (out, level, xml_printf (out, level,
"<reduction symbol=\"%s\" rule=\"accept\" enabled=\"%s\"/>", "<reduction symbol=\"%s\" rule=\"accept\" enabled=\"%s\"/>",
xml_escape (lookahead_token), xml_escape (lookahead),
enabled ? "true" : "false"); enabled ? "true" : "false");
} }
@@ -258,13 +258,13 @@ print_reductions (FILE *out, int level, state *s)
if (default_reduction) if (default_reduction)
report = true; report = true;
if (reds->lookahead_tokens) if (reds->lookaheads)
for (i = 0; i < ntokens; i++) for (i = 0; i < ntokens; i++)
{ {
bool count = bitset_test (no_reduce_set, i); bool count = bitset_test (no_reduce_set, i);
for (j = 0; j < reds->num; ++j) for (j = 0; j < reds->num; ++j)
if (bitset_test (reds->lookahead_tokens[j], i)) if (bitset_test (reds->lookaheads[j], i))
{ {
if (! count) if (! count)
{ {
@@ -289,14 +289,14 @@ print_reductions (FILE *out, int level, state *s)
xml_puts (out, level, "<reductions>"); xml_puts (out, level, "<reductions>");
/* Report lookahead tokens (or $default) and reductions. */ /* Report lookahead tokens (or $default) and reductions. */
if (reds->lookahead_tokens) if (reds->lookaheads)
for (i = 0; i < ntokens; i++) for (i = 0; i < ntokens; i++)
{ {
bool defaulted = false; bool defaulted = false;
bool count = bitset_test (no_reduce_set, i); bool count = bitset_test (no_reduce_set, i);
for (j = 0; j < reds->num; ++j) for (j = 0; j < reds->num; ++j)
if (bitset_test (reds->lookahead_tokens[j], i)) if (bitset_test (reds->lookaheads[j], i))
{ {
if (! count) if (! count)
{ {
@@ -382,14 +382,17 @@ print_grammar (FILE *out, int level)
for (int i = 0; i < max_code + 1; i++) for (int i = 0; i < max_code + 1; i++)
if (token_translations[i] != undeftoken->content->number) if (token_translations[i] != undeftoken->content->number)
{ {
char const *tag = symbols[token_translations[i]]->tag; symbol const *sym = symbols[token_translations[i]];
int precedence = symbols[token_translations[i]]->content->prec; char const *tag = sym->tag;
assoc associativity = symbols[token_translations[i]]->content->assoc; char const *type = sym->content->type_name;
int precedence = sym->content->prec;
assoc associativity = sym->content->assoc;
xml_indent (out, level + 2); xml_indent (out, level + 2);
fprintf (out, fprintf (out,
"<terminal symbol-number=\"%d\" token-number=\"%d\"" "<terminal symbol-number=\"%d\" token-number=\"%d\""
" name=\"%s\" usefulness=\"%s\"", " name=\"%s\" type=\"%s\" usefulness=\"%s\"",
token_translations[i], i, xml_escape (tag), token_translations[i], i, xml_escape_n (0, tag),
type ? xml_escape_n (1, type) : "",
reduce_token_unused_in_grammar (token_translations[i]) reduce_token_unused_in_grammar (token_translations[i])
? "unused-in-grammar" : "useful"); ? "unused-in-grammar" : "useful");
if (precedence) if (precedence)
@@ -404,12 +407,16 @@ print_grammar (FILE *out, int level)
xml_puts (out, level + 1, "<nonterminals>"); xml_puts (out, level + 1, "<nonterminals>");
for (symbol_number i = ntokens; i < nsyms + nuseless_nonterminals; i++) for (symbol_number i = ntokens; i < nsyms + nuseless_nonterminals; i++)
{ {
char const *tag = symbols[i]->tag; symbol const *sym = symbols[i];
char const *tag = sym->tag;
char const *type = sym->content->type_name;
xml_printf (out, level + 2, xml_printf (out, level + 2,
"<nonterminal symbol-number=\"%d\" name=\"%s\"" "<nonterminal symbol-number=\"%d\" name=\"%s\""
" type=\"%s\""
" usefulness=\"%s\"/>", " usefulness=\"%s\"/>",
i, xml_escape (tag), i, xml_escape_n (0, tag),
reduce_nonterminal_useless_in_grammar (symbols[i]->content) type ? xml_escape_n (1, type) : "",
reduce_nonterminal_useless_in_grammar (sym->content)
? "useless-in-grammar" : "useful"); ? "useless-in-grammar" : "useful");
} }
xml_puts (out, level + 1, "</nonterminals>"); xml_puts (out, level + 1, "</nonterminals>");
+22 -21
View File
@@ -90,9 +90,9 @@ print_core (FILE *out, const state *s)
previous_rule = r; previous_rule = r;
/* Display the lookahead tokens? */ /* Display the lookahead tokens? */
if (report_flag & report_lookahead_tokens if (report_flag & report_lookaheads
&& item_number_is_rule_number (*sp1)) && item_number_is_rule_number (*sp1))
state_rule_lookahead_tokens_print (s, r, out); state_rule_lookaheads_print (s, r, out);
fputc ('\n', out); fputc ('\n', out);
} }
} }
@@ -180,19 +180,19 @@ print_errs (FILE *out, const state *s)
} }
/*-------------------------------------------------------------------------. /*-------------------------------------------------------------------.
| Report a reduction of RULE on LOOKAHEAD_TOKEN (which can be 'default'). | | Report a reduction of RULE on LOOKAHEAD (which can be 'default'). |
| If not ENABLED, the rule is masked by a shift or a reduce (S/R and | | If not ENABLED, the rule is masked by a shift or a reduce (S/R and |
| R/R conflicts). | | R/R conflicts). |
`-------------------------------------------------------------------------*/ `-------------------------------------------------------------------*/
static void static void
print_reduction (FILE *out, size_t width, print_reduction (FILE *out, size_t width,
const char *lookahead_token, const char *lookahead,
rule *r, bool enabled) rule *r, bool enabled)
{ {
fprintf (out, " %s", lookahead_token); fprintf (out, " %s", lookahead);
for (int j = width - mbswidth (lookahead_token, 0); j > 0; --j) for (int j = width - mbswidth (lookahead, 0); j > 0; --j)
fputc (' ', out); fputc (' ', out);
if (!enabled) if (!enabled)
fputc ('[', out); fputc ('[', out);
@@ -239,13 +239,13 @@ print_reductions (FILE *out, const state *s)
if (default_reduction) if (default_reduction)
width = mbswidth (_("$default"), 0); width = mbswidth (_("$default"), 0);
if (reds->lookahead_tokens) if (reds->lookaheads)
for (int i = 0; i < ntokens; i++) for (int i = 0; i < ntokens; i++)
{ {
bool count = bitset_test (no_reduce_set, i); bool count = bitset_test (no_reduce_set, i);
for (int j = 0; j < reds->num; ++j) for (int j = 0; j < reds->num; ++j)
if (bitset_test (reds->lookahead_tokens[j], i)) if (bitset_test (reds->lookaheads[j], i))
{ {
if (! count) if (! count)
{ {
@@ -268,7 +268,7 @@ print_reductions (FILE *out, const state *s)
bool default_reduction_only = true; bool default_reduction_only = true;
/* Report lookahead tokens (or $default) and reductions. */ /* Report lookahead tokens (or $default) and reductions. */
if (reds->lookahead_tokens) if (reds->lookaheads)
for (int i = 0; i < ntokens; i++) for (int i = 0; i < ntokens; i++)
{ {
bool defaulted = false; bool defaulted = false;
@@ -277,7 +277,7 @@ print_reductions (FILE *out, const state *s)
default_reduction_only = false; default_reduction_only = false;
for (int j = 0; j < reds->num; ++j) for (int j = 0; j < reds->num; ++j)
if (bitset_test (reds->lookahead_tokens[j], i)) if (bitset_test (reds->lookaheads[j], i))
{ {
if (! count) if (! count)
{ {
@@ -377,11 +377,11 @@ print_terminal_symbols (FILE *out)
for (int i = 0; i < max_code + 1; ++i) for (int i = 0; i < max_code + 1; ++i)
if (token_translations[i] != undeftoken->content->number) if (token_translations[i] != undeftoken->content->number)
{ {
const char *tag = symbols[token_translations[i]]->tag; const symbol *sym = symbols[token_translations[i]];
const char *tag = sym->tag;
fprintf (out, "%4s%s", "", tag); fprintf (out, "%4s%s", "", tag);
if (symbols[token_translations[i]]->content->type_name) if (sym->content->type_name)
fprintf (out, " <%s>", fprintf (out, " <%s>", sym->content->type_name);
symbols[token_translations[i]]->content->type_name);
fprintf (out, " (%d)", i); fprintf (out, " (%d)", i);
for (rule_number r = 0; r < nrules; r++) for (rule_number r = 0; r < nrules; r++)
@@ -403,7 +403,8 @@ print_nonterminal_symbols (FILE *out)
fprintf (out, "%s\n\n", _("Nonterminals, with rules where they appear")); fprintf (out, "%s\n\n", _("Nonterminals, with rules where they appear"));
for (symbol_number i = ntokens; i < nsyms; i++) for (symbol_number i = ntokens; i < nsyms; i++)
{ {
const char *tag = symbols[i]->tag; const symbol *sym = symbols[i];
const char *tag = sym->tag;
bool on_left = false; bool on_left = false;
bool on_right = false; bool on_right = false;
@@ -418,9 +419,9 @@ print_nonterminal_symbols (FILE *out)
int column = 4 + mbswidth (tag, 0); int column = 4 + mbswidth (tag, 0);
fprintf (out, "%4s%s", "", tag); fprintf (out, "%4s%s", "", tag);
if (symbols[i]->content->type_name) if (sym->content->type_name)
column += fprintf (out, " <%s>", column += fprintf (out, " <%s>",
symbols[i]->content->type_name); sym->content->type_name);
fprintf (out, " (%d)\n", i); fprintf (out, " (%d)\n", i);
if (on_left) if (on_left)
+12 -11
View File
@@ -406,8 +406,8 @@ grammar_midrule_action (void)
action. Create the MIDRULE. */ action. Create the MIDRULE. */
location dummy_loc = current_rule->action_props.location; location dummy_loc = current_rule->action_props.location;
symbol *dummy = dummy_symbol_get (dummy_loc); symbol *dummy = dummy_symbol_get (dummy_loc);
symbol_type_set(dummy, symbol_type_set (dummy,
current_rule->action_props.type, current_rule->action_props.location); current_rule->action_props.type, current_rule->action_props.location);
symbol_list *midrule = symbol_list_sym_new (dummy, dummy_loc); symbol_list *midrule = symbol_list_sym_new (dummy, dummy_loc);
/* Remember named_ref of previous action. */ /* Remember named_ref of previous action. */
@@ -695,12 +695,10 @@ packgram (void)
} }
/*------------------------------------------------------------------. /*--------------------------------------------------------------.
| Read in the grammar specification and record it in the format | | Read in the grammar specification and record it in the format |
| described in gram.h. All actions are copied into ACTION_OBSTACK, | | described in gram.h. |
| in each case forming the body of a C function (YYACTION) which | `--------------------------------------------------------------*/
| contains a switch statement to decide which action to execute. |
`------------------------------------------------------------------*/
void void
reader (const char *gram) reader (const char *gram)
@@ -806,7 +804,7 @@ check_and_convert_grammar (void)
$accept: %start $end. */ $accept: %start $end. */
{ {
symbol_list *p = symbol_list_sym_new (accept, empty_loc); symbol_list *p = symbol_list_sym_new (acceptsymbol, empty_loc);
p->rhs_loc = grammar->rhs_loc; p->rhs_loc = grammar->rhs_loc;
p->next = symbol_list_sym_new (startsymbol, empty_loc); p->next = symbol_list_sym_new (startsymbol, empty_loc);
p->next->next = symbol_list_sym_new (eoftoken, empty_loc); p->next->next = symbol_list_sym_new (eoftoken, empty_loc);
@@ -817,8 +815,11 @@ check_and_convert_grammar (void)
grammar = p; grammar = p;
} }
aver (nsyms <= SYMBOL_NUMBER_MAXIMUM); if (SYMBOL_NUMBER_MAXIMUM - nnterms < ntokens)
aver (nsyms == ntokens + nnterms); complain (NULL, fatal, "too many symbols in input grammar (limit is %d)",
SYMBOL_NUMBER_MAXIMUM);
nsyms = ntokens + nnterms;
/* Assign the symbols their symbol numbers. */ /* Assign the symbols their symbol numbers. */
symbols_pack (); symbols_pack ();
+4 -4
View File
@@ -160,9 +160,9 @@ inaccessable_symbols (void)
bitset Pp = bitset_create (nrules, BITSET_FIXED); bitset Pp = bitset_create (nrules, BITSET_FIXED);
/* If the start symbol isn't useful, then nothing will be useful. */ /* If the start symbol isn't useful, then nothing will be useful. */
if (bitset_test (N, accept->content->number - ntokens)) if (bitset_test (N, acceptsymbol->content->number - ntokens))
{ {
bitset_set (V, accept->content->number); bitset_set (V, acceptsymbol->content->number);
while (1) while (1)
{ {
@@ -301,7 +301,7 @@ nonterminals_reduce (void)
for (item_number *rhsp = rules[r].rhs; 0 <= *rhsp; ++rhsp) for (item_number *rhsp = rules[r].rhs; 0 <= *rhsp; ++rhsp)
if (ISVAR (*rhsp)) if (ISVAR (*rhsp))
*rhsp = symbol_number_as_item_number (nterm_map[*rhsp - ntokens]); *rhsp = symbol_number_as_item_number (nterm_map[*rhsp - ntokens]);
accept->content->number = nterm_map[accept->content->number - ntokens]; acceptsymbol->content->number = nterm_map[acceptsymbol->content->number - ntokens];
} }
nsyms -= nuseless_nonterminals; nsyms -= nuseless_nonterminals;
@@ -381,7 +381,7 @@ reduce_grammar (void)
{ {
reduce_print (); reduce_print ();
if (!bitset_test (N, accept->content->number - ntokens)) if (!bitset_test (N, acceptsymbol->content->number - ntokens))
complain (&startsymbol_loc, fatal, complain (&startsymbol_loc, fatal,
_("start symbol %s does not derive any sentence"), _("start symbol %s does not derive any sentence"),
startsymbol->tag); startsymbol->tag);
+1
View File
@@ -145,6 +145,7 @@ void code_props_symbol_action_init (code_props *self, char const *code,
location code_loc); location code_loc);
/** /**
* \param type type for midrule actions
* \pre * \pre
* - <tt>self != NULL</tt>. * - <tt>self != NULL</tt>.
* - <tt>code != NULL</tt>. * - <tt>code != NULL</tt>.
+21 -12
View File
@@ -322,8 +322,8 @@ eqopt ({sp}=)?
BEGIN SC_AFTER_IDENTIFIER; BEGIN SC_AFTER_IDENTIFIER;
} }
{int} RETURN_VALUE (INT, scan_integer (yytext, 10, *loc)); {int} RETURN_VALUE (INT_LITERAL, scan_integer (yytext, 10, *loc));
{xint} RETURN_VALUE (INT, scan_integer (yytext, 16, *loc)); {xint} RETURN_VALUE (INT_LITERAL, scan_integer (yytext, 16, *loc));
/* Identifiers may not start with a digit. Yet, don't silently /* Identifiers may not start with a digit. Yet, don't silently
accept "1FOO" as "1 FOO". */ accept "1FOO" as "1 FOO". */
@@ -403,6 +403,7 @@ eqopt ({sp}=)?
{ {
\0 { \0 {
complain (loc, complaint, _("invalid null character")); complain (loc, complaint, _("invalid null character"));
STRING_FINISH ();
STRING_FREE (); STRING_FREE ();
return GRAM_error; return GRAM_error;
} }
@@ -566,6 +567,8 @@ eqopt ({sp}=)?
_("POSIX Yacc does not support string literals")); _("POSIX Yacc does not support string literals"));
RETURN_VALUE (STRING, last_string); RETURN_VALUE (STRING, last_string);
} }
<<EOF>> unexpected_eof (token_start, "\"");
"\n" unexpected_newline (token_start, "\"");
} }
<SC_ESCAPED_TSTRING> <SC_ESCAPED_TSTRING>
@@ -579,13 +582,10 @@ eqopt ({sp}=)?
_("POSIX Yacc does not support string literals")); _("POSIX Yacc does not support string literals"));
RETURN_VALUE (TSTRING, last_string); RETURN_VALUE (TSTRING, last_string);
} }
<<EOF>> unexpected_eof (token_start, "\")");
"\n" unexpected_newline (token_start, "\")");
} }
<SC_ESCAPED_STRING,SC_ESCAPED_TSTRING>
{
<<EOF>> unexpected_eof (token_start, "\"");
"\n" unexpected_newline (token_start, "\"");
}
/*----------------------------------------------------------. /*----------------------------------------------------------.
@@ -599,7 +599,6 @@ eqopt ({sp}=)?
STRING_FINISH (); STRING_FINISH ();
BEGIN INITIAL; BEGIN INITIAL;
loc->start = token_start; loc->start = token_start;
val->CHAR = last_string[0];
if (last_string[0] == '\0') if (last_string[0] == '\0')
{ {
@@ -615,8 +614,9 @@ eqopt ({sp}=)?
} }
else else
{ {
val->CHAR_LITERAL = last_string[0];
STRING_FREE (); STRING_FREE ();
return CHAR; return CHAR_LITERAL;
} }
} }
{eol} unexpected_newline (token_start, "'"); {eol} unexpected_newline (token_start, "'");
@@ -691,6 +691,15 @@ eqopt ({sp}=)?
p); p);
STRING_1GROW ('?'); STRING_1GROW ('?');
} }
"\\" {
// None of the other rules matched: the last character of this
// file is "\". But Flex does not support "\\<<EOF>>".
unexpected_eof (token_start,
YY_START == SC_ESCAPED_CHARACTER ? "?'"
: YY_START == SC_ESCAPED_STRING ? "?\""
: "?\")");
}
} }
/*--------------------------------------------. /*--------------------------------------------.
@@ -933,9 +942,9 @@ convert_ucn_to_byte (char const *ucn)
} }
/*---------------------------------------------------------------------. /*----------------------------------------------------------------------------.
| Handle '#line INT( "FILE")?\n'. ARGS has already skipped '#line '. | | Handle '#line INT_LITERAL( "FILE")?\n'. ARGS has already skipped '#line '. |
`---------------------------------------------------------------------*/ `----------------------------------------------------------------------------*/
static void static void
handle_syncline (char *args, location loc) handle_syncline (char *args, location loc)
+33 -35
View File
@@ -144,13 +144,13 @@ init_state_items (void)
for (int j = 0; j < s->nitems; ++j) for (int j = 0; j < s->nitems; ++j)
{ {
state_item_set (sidx, s, s->items[j]); state_item_set (sidx, s, s->items[j]);
state_item *si = state_items + sidx; state_item *si = &state_items[sidx];
const rule *r = item_rule (si->item); const rule *r = item_rule (si->item);
if (rule_search_idx < red->num && red->rules[rule_search_idx] < r) if (rule_search_idx < red->num && red->rules[rule_search_idx] < r)
++rule_search_idx; ++rule_search_idx;
if (rule_search_idx < red->num && r == red->rules[rule_search_idx]) if (rule_search_idx < red->num && r == red->rules[rule_search_idx])
{ {
bitsetv lookahead = red->lookahead_tokens; bitsetv lookahead = red->lookaheads;
if (lookahead) if (lookahead)
si->lookahead = lookahead[rule_search_idx]; si->lookahead = lookahead[rule_search_idx];
} }
@@ -163,7 +163,7 @@ init_state_items (void)
state_item_set (sidx, s, off); state_item_set (sidx, s, off);
if (item_number_is_rule_number (ritem[off])) if (item_number_is_rule_number (ritem[off]))
{ {
bitsetv lookahead = red->lookahead_tokens; bitsetv lookahead = red->lookaheads;
if (lookahead) if (lookahead)
state_items[sidx].lookahead = lookahead[rule_search_idx]; state_items[sidx].lookahead = lookahead[rule_search_idx];
++rule_search_idx; ++rule_search_idx;
@@ -211,7 +211,7 @@ init_trans (void)
for (int j = 0; j < t->num; ++j) for (int j = 0; j < t->num; ++j)
if (!TRANSITION_IS_DISABLED (t, j)) if (!TRANSITION_IS_DISABLED (t, j))
hash_xinsert (transition_set, t->states[j]); hash_xinsert (transition_set, t->states[j]);
for (int j = state_item_map[i]; j < state_item_map[i + 1]; ++j) for (state_item_number j = state_item_map[i]; j < state_item_map[i + 1]; ++j)
{ {
item_number *item = state_items[j].item; item_number *item = state_items[j].item;
if (item_number_is_rule_number (*item)) if (item_number_is_rule_number (*item))
@@ -222,16 +222,14 @@ init_trans (void)
// find the item in the destination state that corresponds // find the item in the destination state that corresponds
// to the transition of item // to the transition of item
for (int k = 0; k < dst->nitems; ++k) for (int k = 0; k < dst->nitems; ++k)
{ if (item + 1 == ritem + dst->items[k])
if (item + 1 == ritem + dst->items[k]) {
{ state_item_number dstSI =
state_item_number dstSI = state_item_index_lookup (dst->number, k);
state_item_index_lookup (dst->number, k);
state_items[j].trans = dstSI; state_items[j].trans = dstSI;
bitset_set (state_items[dstSI].revs, j); bitset_set (state_items[dstSI].revs, j);
break; break;
}
} }
} }
hash_free (transition_set); hash_free (transition_set);
@@ -250,10 +248,10 @@ init_prods (void)
// Add the nitems of state to skip to the production portion // Add the nitems of state to skip to the production portion
// of that state's state_items // of that state's state_items
for (int j = state_item_map[i] + s->nitems; for (state_item_number j = state_item_map[i] + s->nitems;
j < state_item_map[i + 1]; ++j) j < state_item_map[i + 1]; ++j)
{ {
state_item *src = state_items + j; state_item *src = &state_items[j];
item_number *item = src->item; item_number *item = src->item;
symbol_number lhs = item_rule (item)->lhs->number; symbol_number lhs = item_rule (item)->lhs->number;
bitset itms = hash_pair_lookup (closure_map, lhs); bitset itms = hash_pair_lookup (closure_map, lhs);
@@ -266,9 +264,9 @@ init_prods (void)
} }
// For each item with a dot followed by a nonterminal, // For each item with a dot followed by a nonterminal,
// try to create a production edge. // try to create a production edge.
for (int j = state_item_map[i]; j < state_item_map[i + 1]; ++j) for (state_item_number j = state_item_map[i]; j < state_item_map[i + 1]; ++j)
{ {
state_item *src = state_items + j; state_item *src = &state_items[j];
item_number item = *(src->item); item_number item = *(src->item);
// Skip reduce items and items with terminals after the dot // Skip reduce items and items with terminals after the dot
if (item_number_is_rule_number (item) || ISTOKEN (item)) if (item_number_is_rule_number (item) || ISTOKEN (item))
@@ -301,12 +299,12 @@ gen_lookaheads (void)
{ {
for (state_item_number i = 0; i < nstate_items; ++i) for (state_item_number i = 0; i < nstate_items; ++i)
{ {
state_item *si = state_items + i; state_item *si = &state_items[i];
if (item_number_is_symbol_number (*(si->item)) || !si->lookahead) if (item_number_is_symbol_number (*(si->item)) || !si->lookahead)
continue; continue;
bitset lookahead = si->lookahead; bitset lookahead = si->lookahead;
gl_list_t queue = state_item_list queue =
gl_list_create (GL_LINKED_LIST, NULL, NULL, NULL, true, 1, gl_list_create (GL_LINKED_LIST, NULL, NULL, NULL, true, 1,
(const void **) &si); (const void **) &si);
@@ -339,7 +337,7 @@ init_firsts (void)
firsts = bitsetv_create (nnterms, nsyms, BITSET_FIXED); firsts = bitsetv_create (nnterms, nsyms, BITSET_FIXED);
for (rule_number i = 0; i < nrules; ++i) for (rule_number i = 0; i < nrules; ++i)
{ {
rule *r = rules + i; rule *r = &rules[i];
item_number *n = r->rhs; item_number *n = r->rhs;
// Iterate through nullable nonterminals to try to find a terminal. // Iterate through nullable nonterminals to try to find a terminal.
while (item_number_is_symbol_number (*n) && ISVAR (*n) while (item_number_is_symbol_number (*n) && ISVAR (*n)
@@ -357,7 +355,7 @@ init_firsts (void)
change = false; change = false;
for (rule_number i = 0; i < nrules; ++i) for (rule_number i = 0; i < nrules; ++i)
{ {
rule *r = rules + i; rule *r = &rules[i];
symbol_number lhs = r->lhs->number; symbol_number lhs = r->lhs->number;
bitset f_lhs = FIRSTS (lhs); bitset f_lhs = FIRSTS (lhs);
for (item_number *n = r->rhs; for (item_number *n = r->rhs;
@@ -392,7 +390,7 @@ disable_state_item (state_item *si)
static void static void
prune_forward (const state_item *si) prune_forward (const state_item *si)
{ {
gl_list_t queue = state_item_list queue =
gl_list_create (GL_LINKED_LIST, NULL, NULL, NULL, true, 1, gl_list_create (GL_LINKED_LIST, NULL, NULL, NULL, true, 1,
(const void **) &si); (const void **) &si);
@@ -401,7 +399,7 @@ prune_forward (const state_item *si)
state_item *dsi = (state_item *) gl_list_get_at (queue, 0); state_item *dsi = (state_item *) gl_list_get_at (queue, 0);
gl_list_remove_at (queue, 0); gl_list_remove_at (queue, 0);
if (dsi->trans >= 0) if (dsi->trans >= 0)
gl_list_add_last (queue, state_items + dsi->trans); gl_list_add_last (queue, &state_items[dsi->trans]);
if (dsi->prods) if (dsi->prods)
{ {
@@ -409,7 +407,7 @@ prune_forward (const state_item *si)
state_item_number sin; state_item_number sin;
BITSET_FOR_EACH (biter, dsi->prods, sin, 0) BITSET_FOR_EACH (biter, dsi->prods, sin, 0)
{ {
const state_item *prod = state_items + sin; const state_item *prod = &state_items[sin];
bitset_reset (prod->revs, dsi - state_items); bitset_reset (prod->revs, dsi - state_items);
if (bitset_empty_p (prod->revs)) if (bitset_empty_p (prod->revs))
gl_list_add_last (queue, prod); gl_list_add_last (queue, prod);
@@ -427,7 +425,7 @@ prune_forward (const state_item *si)
static void static void
prune_backward (const state_item *si) prune_backward (const state_item *si)
{ {
gl_list_t queue = state_item_list queue =
gl_list_create (GL_LINKED_LIST, NULL, NULL, NULL, true, 1, gl_list_create (GL_LINKED_LIST, NULL, NULL, NULL, true, 1,
(const void **) &si); (const void **) &si);
@@ -441,7 +439,7 @@ prune_backward (const state_item *si)
{ {
if (SI_DISABLED (sin)) if (SI_DISABLED (sin))
continue; continue;
state_item *rev = state_items + sin; state_item *rev = &state_items[sin];
if (rev->prods) if (rev->prods)
{ {
bitset_reset (rev->prods, dsi - state_items); bitset_reset (rev->prods, dsi - state_items);
@@ -466,7 +464,7 @@ prune_disabled_paths (void)
{ {
for (int i = nstate_items - 1; i >= 0; --i) for (int i = nstate_items - 1; i >= 0; --i)
{ {
state_item *si = state_items + i; state_item *si = &state_items[i];
if (si->trans == -1 && item_number_is_symbol_number (*si->item)) if (si->trans == -1 && item_number_is_symbol_number (*si->item))
{ {
prune_forward (si); prune_forward (si);
@@ -477,7 +475,7 @@ prune_disabled_paths (void)
} }
void void
print_state_item (const state_item *si, FILE *out, const char *prefix) state_item_print (const state_item *si, FILE *out, const char *prefix)
{ {
fputs (prefix, out); fputs (prefix, out);
item_print (si->item, NULL, out); item_print (si->item, NULL, out);
@@ -494,9 +492,9 @@ state_items_report (void)
for (state_number i = 0; i < nstates; ++i) for (state_number i = 0; i < nstates; ++i)
{ {
printf ("State %d:\n", i); printf ("State %d:\n", i);
for (int j = state_item_map[i]; j < state_item_map[i + 1]; ++j) for (state_item_number j = state_item_map[i]; j < state_item_map[i + 1]; ++j)
{ {
state_item *si = state_items + j; state_item *si = &state_items[j];
item_print (si->item, NULL, stdout); item_print (si->item, NULL, stdout);
if (SI_DISABLED (j)) if (SI_DISABLED (j))
{ {
@@ -508,7 +506,7 @@ state_items_report (void)
if (si->trans >= 0) if (si->trans >= 0)
{ {
fputs (" -> ", stdout); fputs (" -> ", stdout);
print_state_item (state_items + si->trans, stdout, ""); state_item_print (&state_items[si->trans], stdout, "");
} }
bitset sets[2] = { si->prods, si->revs }; bitset sets[2] = { si->prods, si->revs };
@@ -523,7 +521,7 @@ state_items_report (void)
BITSET_FOR_EACH (biter, b, sin, 0) BITSET_FOR_EACH (biter, b, sin, 0)
{ {
fputs (txt[seti], stdout); fputs (txt[seti], stdout);
print_state_item (state_items + sin, stdout, ""); state_item_print (&state_items[sin], stdout, "");
} }
} }
} }
@@ -562,10 +560,10 @@ state_items_init (void)
void void
state_items_free (void) state_items_free (void)
{ {
for (int i = 0; i < nstate_items; ++i) for (state_item_number i = 0; i < nstate_items; ++i)
if (!SI_DISABLED (i)) if (!SI_DISABLED (i))
{ {
state_item *si = state_items + i; state_item *si = &state_items[i];
if (si->prods) if (si->prods)
bitset_free (si->prods); bitset_free (si->prods);
bitset_free (si->revs); bitset_free (si->revs);
@@ -594,5 +592,5 @@ production_allowed (const state_item *si, const state_item *next)
if (prec1 == prec2 && s1->assoc == left_assoc) if (prec1 == prec2 && s1->assoc == left_assoc)
return false; return false;
} }
return true; return true;
} }
+14 -9
View File
@@ -28,16 +28,16 @@
# include "state.h" # include "state.h"
/* Initializes a graph connecting (state, production item) pairs to /* Initializes a graph connecting (state, production item) pairs to
pairs they can make a transition or production step to. This graph pairs they can make a transition or production step to. This graph
is used to search for paths that represent counterexamples of some is used to search for paths that represent counterexamples of some
conflict. conflict.
state_items is an array of state state-item pairs ordered by state. state_items is an array of state state-item pairs ordered by state.
state_item_map maps state numbers to the first item which state_item_map maps state numbers to the first item which
corresponds to it in the array. A state's portion in state_items corresponds to it in the array. A state's portion in state_items
begins with its items in the same order as it was in the begins with its items in the same order as it was in the state.
state. This is then followed by productions from the closure of the This is then followed by productions from the closure of the state
state in order by rule. in order by rule.
There are two type of edges in this graph transitions and There are two type of edges in this graph transitions and
productions. Transitions are the same as transitions from the productions. Transitions are the same as transitions from the
@@ -53,9 +53,9 @@
production edges, and all others will have reverse transition production edges, and all others will have reverse transition
edges. */ edges. */
# define SI_DISABLED(sin) (state_items[sin].trans == -2) # define SI_DISABLED(Sin) (state_items[Sin].trans == -2)
# define SI_PRODUCTION(si) ((si) == state_items || *((si)->item - 1) < 0) # define SI_PRODUCTION(Si) ((Si) == state_items || *((Si)->item - 1) < 0)
# define SI_TRANSITION(si) ((si) != state_items && *((si)->item - 1) >= 0) # define SI_TRANSITION(Si) ((Si) != state_items && *((Si)->item - 1) >= 0)
typedef int state_item_number; typedef int state_item_number;
@@ -69,6 +69,9 @@ typedef struct
bitset lookahead; bitset lookahead;
} state_item; } state_item;
// A path of state-items.
typedef gl_list_t state_item_list;
extern bitsetv firsts; extern bitsetv firsts;
# define FIRSTS(sym) firsts[(sym) - ntokens] # define FIRSTS(sym) firsts[(sym) - ntokens]
@@ -87,11 +90,13 @@ state_item_index_lookup (state_number s, state_item_number off)
} }
void state_items_init (void); void state_items_init (void);
void print_state_item (const state_item *si, FILE *out, const char *prefix);
void state_items_free (void); void state_items_free (void);
void state_item_print (const state_item *si, FILE *out, const char *prefix);
bool production_allowed (const state_item *si, const state_item *next); bool production_allowed (const state_item *si, const state_item *next);
// Iterating on a state_item_list.
static inline bool static inline bool
state_item_list_next (gl_list_iterator_t *it, state_item **si) state_item_list_next (gl_list_iterator_t *it, state_item **si)
{ {
+7 -7
View File
@@ -101,7 +101,7 @@ reductions_new (int num, rule **reds)
size_t rules_size = num * sizeof *reds; size_t rules_size = num * sizeof *reds;
reductions *res = xmalloc (offsetof (reductions, rules) + rules_size); reductions *res = xmalloc (offsetof (reductions, rules) + rules_size);
res->num = num; res->num = num;
res->lookahead_tokens = NULL; res->lookaheads = NULL;
memcpy (res->rules, reds, rules_size); memcpy (res->rules, reds, rules_size);
return res; return res;
} }
@@ -260,20 +260,20 @@ state_errs_set (state *s, int num, symbol **tokens)
`--------------------------------------------------*/ `--------------------------------------------------*/
void void
state_rule_lookahead_tokens_print (state const *s, rule const *r, FILE *out) state_rule_lookaheads_print (state const *s, rule const *r, FILE *out)
{ {
/* Find the reduction we are handling. */ /* Find the reduction we are handling. */
reductions *reds = s->reductions; reductions *reds = s->reductions;
int red = state_reduction_find (s, r); int red = state_reduction_find (s, r);
/* Print them if there are. */ /* Print them if there are. */
if (reds->lookahead_tokens && red != -1) if (reds->lookaheads && red != -1)
{ {
bitset_iterator biter; bitset_iterator biter;
int k; int k;
char const *sep = ""; char const *sep = "";
fprintf (out, " ["); fprintf (out, " [");
BITSET_FOR_EACH (biter, reds->lookahead_tokens[red], k, 0) BITSET_FOR_EACH (biter, reds->lookaheads[red], k, 0)
{ {
fprintf (out, "%s%s", sep, symbols[k]->tag); fprintf (out, "%s%s", sep, symbols[k]->tag);
sep = ", "; sep = ", ";
@@ -283,7 +283,7 @@ state_rule_lookahead_tokens_print (state const *s, rule const *r, FILE *out)
} }
void void
state_rule_lookahead_tokens_print_xml (state const *s, rule const *r, state_rule_lookaheads_print_xml (state const *s, rule const *r,
FILE *out, int level) FILE *out, int level)
{ {
/* Find the reduction we are handling. */ /* Find the reduction we are handling. */
@@ -291,12 +291,12 @@ state_rule_lookahead_tokens_print_xml (state const *s, rule const *r,
int red = state_reduction_find (s, r); int red = state_reduction_find (s, r);
/* Print them if there are. */ /* Print them if there are. */
if (reds->lookahead_tokens && red != -1) if (reds->lookaheads && red != -1)
{ {
bitset_iterator biter; bitset_iterator biter;
int k; int k;
xml_puts (out, level, "<lookaheads>"); xml_puts (out, level, "<lookaheads>");
BITSET_FOR_EACH (biter, reds->lookahead_tokens[red], k, 0) BITSET_FOR_EACH (biter, reds->lookaheads[red], k, 0)
{ {
xml_printf (out, level + 1, "<symbol>%s</symbol>", xml_printf (out, level + 1, "<symbol>%s</symbol>",
xml_escape (symbols[k]->tag)); xml_escape (symbols[k]->tag));
+5 -5
View File
@@ -62,7 +62,7 @@
Each reductions structure describes the possible reductions at the Each reductions structure describes the possible reductions at the
state whose number is in the number field. rules is an array of state whose number is in the number field. rules is an array of
num rules. lookahead_tokens is an array of bitsets, one per rule. num rules. lookaheads is an array of bitsets, one per rule.
Conflict resolution can decide that certain tokens in certain Conflict resolution can decide that certain tokens in certain
states should explicitly be errors (for implementing %nonassoc). states should explicitly be errors (for implementing %nonassoc).
@@ -187,7 +187,7 @@ errs *errs_new (int num, symbol **tokens);
typedef struct typedef struct
{ {
int num; int num;
bitset *lookahead_tokens; bitset *lookaheads;
/* Sorted ascendingly on rule number. */ /* Sorted ascendingly on rule number. */
rule *rules[1]; rule *rules[1];
} reductions; } reductions;
@@ -254,9 +254,9 @@ void state_errs_set (state *s, int num, symbol **errors);
/* Print on OUT all the lookahead tokens such that this STATE wants to /* Print on OUT all the lookahead tokens such that this STATE wants to
reduce R. */ reduce R. */
void state_rule_lookahead_tokens_print (state const *s, rule const *r, FILE *out); void state_rule_lookaheads_print (state const *s, rule const *r, FILE *out);
void state_rule_lookahead_tokens_print_xml (state const *s, rule const *r, void state_rule_lookaheads_print_xml (state const *s, rule const *r,
FILE *out, int level); FILE *out, int level);
/* Create/destroy the states hash table. */ /* Create/destroy the states hash table. */
void state_hash_new (void); void state_hash_new (void);
+67
View File
@@ -0,0 +1,67 @@
/* Convert version string to int.
Copyright (C) 2020 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include "system.h"
#include "strversion.h"
#include <errno.h>
#include <intprops.h>
int
strversion_to_int (char const *version)
{
IGNORE_TYPE_LIMITS_BEGIN
int res = 0;
errno = 0;
char *cp = NULL;
{
long major = strtol (version, &cp, 10);
if (errno || cp == version || *cp != '.' || major < 0
|| INT_MULTIPLY_WRAPV (major, 10000, &res))
return -1;
}
{
++cp;
char *prev = cp;
long minor = strtol (cp, &cp, 10);
if (errno || cp == prev || (*cp != '\0' && *cp != '.')
|| ! (0 <= minor && minor < 100)
|| INT_MULTIPLY_WRAPV (minor, 100, &minor)
|| INT_ADD_WRAPV (minor, res, &res))
return -1;
}
if (*cp == '.')
{
++cp;
char *prev = cp;
long micro = strtol (cp, &cp, 10);
if (errno || cp == prev || (*cp != '\0' && *cp != '.')
|| ! (0 <= micro && micro < 100)
|| INT_ADD_WRAPV (micro, res, &res))
return -1;
}
IGNORE_TYPE_LIMITS_END
return res;
}
+28
View File
@@ -0,0 +1,28 @@
/* Convert version string to int.
Copyright (C) 2020 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#ifndef STRVERSION_H_
# define STRVERSION_H_
/* Convert VERSION into an int (MAJOR * 10000 + MINOR * 100 + MICRO).
E.g., "3.7.4" => 30704, "3.8" => 30800.
Return -1 on errors. */
int strversion_to_int (char const *version);
#endif
+2 -2
View File
@@ -83,10 +83,10 @@ symbol_list_type_new (uniqstr type_name, location loc)
symbol_list * symbol_list *
symbol_list_type_set (symbol_list *syms, uniqstr type_name, location loc) symbol_list_type_set (symbol_list *syms, uniqstr type_name)
{ {
for (symbol_list *l = syms; l; l = l->next) for (symbol_list *l = syms; l; l = l->next)
symbol_type_set (l->content.sym, type_name, loc); symbol_type_set (l->content.sym, type_name, l->sym_loc);
return syms; return syms;
} }
+1 -2
View File
@@ -110,8 +110,7 @@ symbol_list *symbol_list_type_new (uniqstr type_name, location loc);
/** Assign the type \c type_name to all the members of \c syms. /** Assign the type \c type_name to all the members of \c syms.
** \returns \c syms */ ** \returns \c syms */
symbol_list *symbol_list_type_set (symbol_list *syms, symbol_list *symbol_list_type_set (symbol_list *syms, uniqstr type_name);
uniqstr type_name, location loc);
/** Print this list. /** Print this list.
+33 -36
View File
@@ -59,7 +59,7 @@ static semantic_type **semantic_types_sorted = NULL;
symbol *errtoken = NULL; symbol *errtoken = NULL;
symbol *undeftoken = NULL; symbol *undeftoken = NULL;
symbol *eoftoken = NULL; symbol *eoftoken = NULL;
symbol *accept = NULL; symbol *acceptsymbol = NULL;
symbol *startsymbol = NULL; symbol *startsymbol = NULL;
location startsymbol_loc; location startsymbol_loc;
@@ -137,11 +137,6 @@ symbol_new (uniqstr tag, location loc)
res->alias = NULL; res->alias = NULL;
res->content = sym_content_new (res); res->content = sym_content_new (res);
res->is_alias = false; res->is_alias = false;
if (nsyms == SYMBOL_NUMBER_MAXIMUM)
complain (NULL, fatal, _("too many symbols in input grammar (limit is %d)"),
SYMBOL_NUMBER_MAXIMUM);
nsyms++;
return res; return res;
} }
@@ -182,11 +177,11 @@ symbol_free (void *ptr)
*/ */
static void static void
symbols_sort (symbol **first, symbol **second) symbols_sort (const symbol **first, const symbol **second)
{ {
if (0 < location_cmp ((*first)->location, (*second)->location)) if (0 < location_cmp ((*first)->location, (*second)->location))
{ {
symbol* tmp = *first; const symbol* tmp = *first;
*first = *second; *first = *second;
*second = tmp; *second = tmp;
} }
@@ -243,7 +238,11 @@ semantic_type_new (uniqstr tag, const location *loc)
| Print a symbol. | | Print a symbol. |
`-----------------*/ `-----------------*/
#define SYMBOL_ATTR_PRINT(Attr) \ #define SYMBOL_INT_ATTR_PRINT(Attr) \
if (s->content) \
fprintf (f, " %s = %d", #Attr, s->content->Attr)
#define SYMBOL_STR_ATTR_PRINT(Attr) \
if (s->content && s->content->Attr) \ if (s->content && s->content->Attr) \
fprintf (f, " %s { %s }", #Attr, s->content->Attr) fprintf (f, " %s { %s }", #Attr, s->content->Attr)
@@ -264,7 +263,11 @@ symbol_print (symbol const *s, FILE *f)
: c == nterm_sym ? "nterm" : c == nterm_sym ? "nterm"
: NULL, /* abort. */ : NULL, /* abort. */
s->tag); s->tag);
SYMBOL_ATTR_PRINT (type_name); putc (' ', f);
location_print (s->location, f);
SYMBOL_INT_ATTR_PRINT (code);
SYMBOL_INT_ATTR_PRINT (number);
SYMBOL_STR_ATTR_PRINT (type_name);
SYMBOL_CODE_PRINT (destructor); SYMBOL_CODE_PRINT (destructor);
SYMBOL_CODE_PRINT (printer); SYMBOL_CODE_PRINT (printer);
} }
@@ -371,7 +374,7 @@ symbol_from_uniqstr_fuzzy (const uniqstr key)
} }
static void static void
complain_symbol_undeclared (symbol *sym) complain_symbol_undeclared (const symbol *sym)
{ {
assert (sym->content->status != declared); assert (sym->content->status != declared);
const symbol *best = symbol_from_uniqstr_fuzzy (sym->tag); const symbol *best = symbol_from_uniqstr_fuzzy (sym->tag);
@@ -398,7 +401,10 @@ void
symbol_location_as_lhs_set (symbol *sym, location loc) symbol_location_as_lhs_set (symbol *sym, location loc)
{ {
if (!sym->location_of_lhs) if (!sym->location_of_lhs)
sym->location = loc; {
sym->location = loc;
sym->location_of_lhs = true;
}
} }
@@ -548,10 +554,6 @@ symbol_class_set (symbol *sym, symbol_class class, location loc, bool declaring)
if (class == token_sym && s->class == pct_type_sym) if (class == token_sym && s->class == pct_type_sym)
complain_pct_type_on_token (&sym->location); complain_pct_type_on_token (&sym->location);
if (class == nterm_sym && s->class != nterm_sym)
s->number = nnterms++;
else if (class == token_sym && s->number == NUMBER_UNDEFINED)
s->number = ntokens++;
s->class = class; s->class = class;
if (declaring) if (declaring)
@@ -573,9 +575,9 @@ symbol_class_set (symbol *sym, symbol_class class, location loc, bool declaring)
} }
/*------------------------------------------------. /*----------------------------.
| Set the USER_TOKEN_NUMBER associated with SYM. | | Set the token code of SYM. |
`------------------------------------------------*/ `----------------------------*/
void void
symbol_code_set (symbol *sym, int code, location loc) symbol_code_set (symbol *sym, int code, location loc)
@@ -598,10 +600,6 @@ symbol_code_set (symbol *sym, int code, location loc)
if (code == 0 && !eoftoken) if (code == 0 && !eoftoken)
{ {
eoftoken = sym->content->symbol; eoftoken = sym->content->symbol;
/* It is always mapped to 0, so it was already counted in
NTOKENS. */
if (eoftoken->content->number != NUMBER_UNDEFINED)
--ntokens;
eoftoken->content->number = 0; eoftoken->content->number = 0;
} }
} }
@@ -621,9 +619,11 @@ symbol_check_defined (symbol *sym)
{ {
complain_symbol_undeclared (sym); complain_symbol_undeclared (sym);
s->class = nterm_sym; s->class = nterm_sym;
s->number = nnterms++;
} }
if (s->number == NUMBER_UNDEFINED)
s->number = s->class == token_sym ? ntokens++ : nnterms++;
if (s->class == token_sym if (s->class == token_sym
&& sym->tag[0] == '"' && sym->tag[0] == '"'
&& !sym->is_alias) && !sym->is_alias)
@@ -742,7 +742,7 @@ symbol_pack (symbol *sym)
} }
static void static void
complain_code_redeclared (int num, symbol *first, symbol *second) complain_code_redeclared (int num, const symbol *first, const symbol *second)
{ {
symbols_sort (&first, &second); symbols_sort (&first, &second);
complain (&second->location, complaint, complain (&second->location, complaint,
@@ -758,13 +758,11 @@ complain_code_redeclared (int num, symbol *first, symbol *second)
`-------------------------------------------------*/ `-------------------------------------------------*/
static void static void
symbol_translation (symbol *sym) symbol_translation (const symbol *sym)
{ {
/* Nonterminal? */ if (sym->content->class == token_sym && !sym->is_alias)
if (sym->content->class == token_sym
&& !sym->is_alias)
{ {
/* A token which translation has already been set?*/ /* A token whose translation has already been set? */
if (token_translations[sym->content->code] if (token_translations[sym->content->code]
!= undeftoken->content->number) != undeftoken->content->number)
complain_code_redeclared complain_code_redeclared
@@ -849,10 +847,10 @@ symbols_new (void)
hash_symbol_comparator, hash_symbol_comparator,
symbol_free); symbol_free);
/* Construct the accept symbol. */ /* Construct the acceptsymbol symbol. */
accept = symbol_get ("$accept", empty_loc); acceptsymbol = symbol_get ("$accept", empty_loc);
accept->content->class = nterm_sym; acceptsymbol->content->class = nterm_sym;
accept->content->number = nnterms++; acceptsymbol->content->number = nnterms++;
/* Construct the YYerror/"error" token */ /* Construct the YYerror/"error" token */
errtoken = symbol_get ("YYerror", empty_loc); errtoken = symbol_get ("YYerror", empty_loc);
@@ -969,7 +967,6 @@ dummy_symbol_get (location loc)
assure (len < sizeof buf); assure (len < sizeof buf);
symbol *sym = symbol_get (buf, loc); symbol *sym = symbol_get (buf, loc);
sym->content->class = nterm_sym; sym->content->class = nterm_sym;
sym->content->number = nnterms++;
return sym; return sym;
} }
@@ -1002,7 +999,7 @@ symbol_cmp (void const *a, void const *b)
} }
/* Store in *SORTED an array of pointers to the symbols contained in /* Store in *SORTED an array of pointers to the symbols contained in
TABLE, sorted (alphabetically) by tag. */ TABLE, sorted by order of appearance (i.e., by location). */
static void static void
table_sort (struct hash_table *table, symbol ***sorted) table_sort (struct hash_table *table, symbol ***sorted)
+2 -2
View File
@@ -227,7 +227,7 @@ void symbol_precedence_set (symbol *sym, int prec, assoc a, location loc);
void symbol_class_set (symbol *sym, symbol_class class, location loc, void symbol_class_set (symbol *sym, symbol_class class, location loc,
bool declaring); bool declaring);
/** Set the \c code associated with \c sym. */ /** Set the token \c code of \c sym, specified by the user at \c loc. */
void symbol_code_set (symbol *sym, int code, location loc); void symbol_code_set (symbol *sym, int code, location loc);
@@ -245,7 +245,7 @@ extern symbol *eoftoken;
/** The genuine start symbol. /** The genuine start symbol.
$accept: start-symbol $end */ $accept: start-symbol $end */
extern symbol *accept; extern symbol *acceptsymbol;
/** The user start symbol. */ /** The user start symbol. */
extern symbol *startsymbol; extern symbol *startsymbol;
+16
View File
@@ -131,6 +131,22 @@ typedef size_t uintptr_t;
# include <stdbool.h> # include <stdbool.h>
/*-----------.
| Integers. |
`-----------*/
static inline int
min_int (int a, int b)
{
return a < b ? a : b;
}
static inline int
max_int (int a, int b)
{
return a >= b ? a : b;
}
/*-------------. /*-------------.
| Assertions. | | Assertions. |

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